Reputation: 4850
I'm needing to compute a shared secret in JavaScript using ECC keys an ECDH. I see two possible projects that may do this but I'm not sure which if any to pursue:.
1) Is a chrome extension so I assume that means it is not going to run in other browsers. 2) Someone had a problem with SJCL stating they thought this was using ECMQV instead of plain ECDH (Can't bridge Elliptic Curve Diffie-Hellman with javascript).
Can someone please recommend a good course of action for my implementation? And Option 3 (a preferred option): I have a hunch that is may be straight forward to include a shared secret implementation here: https://github.com/bitcoinjs/bitcoinjs-lib/blob/master/src/ecdsa.js.
This is C++ code to create the shared secret on the server:
void * ecies_key_derivation(const void *input, size_t ilen, void *output, size_t *olen)
{
*olen = SHA512_DIGEST_LENGTH;
return (void*)SHA512((const unsigned char*)input, ilen, (unsigned char*)output);
}
...
fc::sha512 shared_secret;
ECDH_compute_key( (unsigned char*)&shared_secret, sizeof(shared_secret), EC_KEY_get0_public_key(recipient.my->_key), my->_key, ecies_key_derivation );
Upvotes: 2
Views: 3830
Reputation: 4850
Obviously this needs to be consolidated but it is at least working!
Option 1 is chrome specific: https://bugzilla.mozilla.org/show_bug.cgi?id=1022106 "cursory glance at the code (git clone-able from git clone https://code.google.com/p/end-to-end/), and it seems to very much be designed to be a Chrome-only add-on"
Option 2 works as seen here using bitcore (bitcore uses sjcl behind the scenes):
# npm install bitcore
ECIES = require '../node_modules/bitcore/lib/ECIES'
ot_pubkey = new Buffer(onetime_public_key, 'hex')
my_privkey = new Buffer(d_receiver_hex, 'hex')
ecies = new ECIES.encryptObj ot_pubkey, new Buffer(''), my_privkey
S = ecies.getSfromPubkey()
console.log 'bitcore sharedsecret\t',S.toString 'hex'
S_kdf_buf = ECIES.kdf(S)
console.log 'bitcore sharedsecret kdf\t',S_kdf_buf.toString 'hex'
Additionally elliptic.js worked which uses it own code including bn.js for big numbers (same author):
# git clone https://github.com/indutny/elliptic.git
elliptic = require('../elliptic/lib/elliptic.js')
# npm install bn.js
bn = require('bn.js')
#Providing ecies_key_derivation https://github.com/indutny/elliptic/issues/9
ec = new elliptic.ec('secp256k1')
s0 = ec.keyPair(onetime_private_key, 'hex')
# ../testnet/config/genesis_private_keys.txt
s1 = ec.keyPair(d_receiver_hex, "hex")
sh0 = s0.derive(s1.getPublic())
sh1 = s1.derive(s0.getPublic())
assert.equal sh0.toString(16), sh1.toString(16), "shared secret did not match"
shared_secret = "0"+sh0.toString(16) #### only works for this shared secret (bn.js::toString(16))
At this point, I got these libraries to produce the shared secrets correctly. For decryption I ended up using crypto-js.
# https://code.google.com/p/crypto-js/#Custom_Key_and_IV
# see wallet_records.cpp master_key::decrypt_key
CryptoJS.AES.decrypt(
ciphertext: cipher
salt: null
, @key,
iv: @iv
)
For decryption, I require a 256 bit IV (initialization vector) for the task so that leaves SJCL out until this is updated (https://github.com/bitwiseshiftleft/sjcl/issues/197). Also, I did not have much luck decrypting with elliptic.js either although I'm not sure if that was my error.
Upvotes: 4