UNPKG

ecdh-es

Version:

Elliptic Curve Diffie-Hellman with ephemeral-static keys implementation for NodeJS

77 lines (66 loc) 2.69 kB
// 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);