ecdh-es
Version:
Elliptic Curve Diffie-Hellman with ephemeral-static keys implementation for NodeJS
77 lines (66 loc) • 2.69 kB
JavaScript
// Generated by CoffeeScript 1.8.0
(function() {
var BigInt, CHECKSUM_SIZE, PUBKEY_SIZE, Point, buff_eq, create_ecdh, crypto, getCurveByName, get_pub, hmac, k, rand, rand_key, reader, sha256, sha512, v, _ref, _ref1, _ref2;
crypto = require('crypto');
BigInt = require('bigi');
_ref = require('ecurve'), Point = _ref.Point, getCurveByName = _ref.getCurveByName;
_ref1 = require('./util'), reader = _ref1.reader, sha256 = _ref1.sha256, sha512 = _ref1.sha512, hmac = _ref1.hmac, rand = _ref1.rand, rand_key = _ref1.rand_key, get_pub = _ref1.get_pub, buff_eq = _ref1.buff_eq;
PUBKEY_SIZE = 33;
CHECKSUM_SIZE = 32;
create_ecdh = function(_arg) {
var cipher_algo, curve, curve_name, iv_size, key_size, shared_secret;
curve_name = _arg.curve_name, cipher_algo = _arg.cipher_algo, key_size = _arg.key_size, iv_size = _arg.iv_size;
curve = getCurveByName(curve_name);
shared_secret = function(d, Q) {
if (Buffer.isBuffer(d)) {
d = BigInt.fromBuffer(d);
}
if (Buffer.isBuffer(Q)) {
Q = Point.decodeFrom(curve, Q);
}
return sha512(Q.multiply(d).getEncoded(false));
};
return {
encrypt: function(pubkey, msg) {
var checksum, cipher, ct, eph, eph_p, iv, secret;
eph = rand_key(curve, pubkey, msg);
eph_p = get_pub(curve, eph);
secret = shared_secret(eph, pubkey);
iv = sha256(eph_p).slice(0, iv_size);
cipher = crypto.createCipheriv(cipher_algo, secret.slice(0, key_size), iv);
cipher.setAutoPadding(true);
ct = cipher.update(msg);
ct = Buffer.concat([ct, cipher.final()]);
checksum = hmac(secret.slice(key_size), eph_p, ct);
return Buffer.concat([eph_p, checksum, ct]);
},
decrypt: function(privkey, enc) {
var checksum, cipher, ct, iv, msg, pubkey, read, secret;
read = reader(enc);
pubkey = read(PUBKEY_SIZE);
checksum = read(CHECKSUM_SIZE);
ct = read();
secret = shared_secret(privkey, pubkey);
iv = sha256(pubkey).slice(0, iv_size);
if (!buff_eq(checksum, hmac(secret.slice(key_size), pubkey, ct))) {
throw new Error('Invalid checksum');
}
cipher = crypto.createDecipheriv(cipher_algo, secret.slice(0, key_size), iv);
cipher.setAutoPadding(true);
msg = cipher.update(ct);
return Buffer.concat([msg, cipher.final()]);
}
};
};
module.exports = create_ecdh;
_ref2 = create_ecdh({
curve_name: 'secp256k1',
cipher_algo: 'AES-128-CBC',
key_size: 16,
iv_size: 16
});
for (k in _ref2) {
v = _ref2[k];
module.exports[k] = v;
}
}).call(this);