From cc316e94555e6210d3582ac43fd71181ef78ddc9 Mon Sep 17 00:00:00 2001 From: "Ryan X. Charles" Date: Thu, 28 Aug 2014 14:43:21 -0700 Subject: [PATCH] ECIES --- index.js | 1 + lib/expmt/ecies.js | 52 ++++++++++++++++++++++++++++++++++++++++++++++ test/test.ecies.js | 41 ++++++++++++++++++++++++++++++++++++ 3 files changed, 94 insertions(+) create mode 100644 lib/expmt/ecies.js create mode 100644 test/test.ecies.js diff --git a/index.js b/index.js index 097bf4b..18db7a0 100644 --- a/index.js +++ b/index.js @@ -24,6 +24,7 @@ bitcore.Signature = require('./lib/signature'); bitcore.expmt = {}; bitcore.expmt.AES = require('./lib/expmt/aes'); bitcore.expmt.CBC = require('./lib/expmt/cbc'); +bitcore.expmt.ECIES = require('./lib/ecies'); bitcore.expmt.SymEnc = require('./lib/expmt/symenc'); bitcore.expmt.Stealth = require('./lib/expmt/stealth'); diff --git a/lib/expmt/ecies.js b/lib/expmt/ecies.js new file mode 100644 index 0000000..b96cf2a --- /dev/null +++ b/lib/expmt/ecies.js @@ -0,0 +1,52 @@ +var SymEnc = require('./symenc'); +var Key = require('../key'); +var Point = require('../point'); +var Hash = require('../hash'); +var Pubkey = require('../pubkey'); + +// http://en.wikipedia.org/wiki/Integrated_Encryption_Scheme +var ECIES = function ECIES() { + if (!(this instanceof ECIES)) + return new ECIES(); +}; + +ECIES.encrypt = function(messagebuf, tokey, fromkey, ivbuf) { + var r = fromkey.privkey.bn; + var R = fromkey.pubkey.point; + var Rpubkey = fromkey.pubkey; + var Rbuf = Rpubkey.toDER(true); + var KB = tokey.pubkey.point; + var P = KB.mul(r); + var S = P.getX(); + var Sbuf = S.toBuffer({size: 32}); + var kEkM = Hash.sha512(Sbuf); + var kE = kEkM.slice(0, 32); + var kM = kEkM.slice(32, 64); + var c = SymEnc.encryptCipherkey(messagebuf, kE, ivbuf); + var d = Hash.sha256hmac(c, kM); + var encbuf = Buffer.concat([Rbuf, c, d]); + return encbuf; +}; + +ECIES.decrypt = function(encbuf, tokey) { + var kB = tokey.privkey.bn; + var frompubkey = Pubkey().fromDER(encbuf.slice(0, 33)); + var R = frompubkey.point; + var P = R.mul(kB); + if (P.eq(new Point())) + throw new Error('P equals 0'); + var S = P.getX(); + var Sbuf = S.toBuffer({size: 32}); + var kEkM = Hash.sha512(Sbuf); + var kE = kEkM.slice(0, 32); + var kM = kEkM.slice(32, 64); + var c = encbuf.slice(33, encbuf.length - 32); + var d = encbuf.slice(encbuf.length - 32, encbuf.length); + var d2 = Hash.sha256hmac(c, kM); + if (d.toString('hex') !== d2.toString('hex')) + throw new Error('Invalid checksum'); + var messagebuf = SymEnc.decryptCipherkey(c, kE); + return messagebuf; +}; + +module.exports = ECIES; diff --git a/test/test.ecies.js b/test/test.ecies.js new file mode 100644 index 0000000..4ee661b --- /dev/null +++ b/test/test.ecies.js @@ -0,0 +1,41 @@ +var ECIES = require('../lib/expmt/ecies'); +var should = require('chai').should(); +var Key = require('../lib/key'); +var Hash = require('../lib/hash'); + +describe('#ECIES', function() { + + it('should make a new ECIES object', function() { + var ecies = new ECIES(); + should.exist(ecies); + }); + + it('should make a new ECIES object when called without "new"', function() { + var ecies = ECIES(); + should.exist(ecies); + }); + + var fromkey = Key().fromRandom(); + var tokey = Key().fromRandom(); + var messagebuf = Hash.sha256(new Buffer('my message is the hash of this string')); + + describe('@encrypt', function() { + + it('should return a buffer', function() { + var encbuf = ECIES.encrypt(messagebuf, tokey, fromkey); + Buffer.isBuffer(encbuf).should.equal(true); + }); + + }); + + describe('@decrypt', function() { + + it('should decrypt that which was encrypted', function() { + var encbuf = ECIES.encrypt(messagebuf, tokey, fromkey); + var messagebuf2 = ECIES.decrypt(encbuf, tokey); + messagebuf2.toString('hex').should.equal(messagebuf.toString('hex')); + }); + + }); + +});