diff --git a/js/models/core/Message.js b/js/models/core/Message.js deleted file mode 100644 index ad6324440..000000000 --- a/js/models/core/Message.js +++ /dev/null @@ -1,148 +0,0 @@ -'use strict'; - -var bitcore = require('bitcore'); - -/* Encrypted, authenticated messages to be shared between copayers */ -var Message = function() { -}; - -Message.encode = function(topubkey, fromkey, payload, opts) { - var version1 = new Buffer([1]); //peers will reject messges containing not-understood version1 - //i.e., increment version1 to prevent communications with old clients - var version2 = new Buffer([0]); //peers will not reject messages containing not-understood version2 - //i.e., increment version2 to allow communication with old clients, but signal new clients - var nonce; - if (opts && opts.nonce && Buffer.isBuffer(opts.nonce) && opts.nonce.length == 8) { - nonce = opts.nonce; - } else { - nonce = new Buffer(8); - nonce.fill(0); //nonce is a big endian 8 byte number - } - - var toencrypt = Buffer.concat([version1, version2, nonce, payload]); - var toencrypthexbuf = new Buffer(toencrypt.toString('hex')); //due to bug in sjcl/bitcore, must use hex string - var encrypted = Message._encrypt(topubkey, toencrypthexbuf); - var sig = Message._sign(fromkey, encrypted); - var encoded = { - pubkey: fromkey.public.toString('hex'), - sig: sig.toString('hex'), - encrypted: encrypted.toString('hex') - }; - return encoded; -}; - -Message.decode = function(key, encoded, opts) { - var prevnonce; - if (opts && opts.prevnonce && Buffer.isBuffer(opts.prevnonce) && opts.prevnonce.length == 8) { - prevnonce = opts.prevnonce; - } else { - prevnonce = new Buffer(8); - prevnonce.fill(0); //nonce is a big endian 8 byte number - } - - try { - var frompubkey = new Buffer(encoded.pubkey, 'hex'); - } catch (e) { - throw new Error('Error decoding public key: ' + e); - } - - try { - var sig = new Buffer(encoded.sig, 'hex'); - var encrypted = new Buffer(encoded.encrypted, 'hex'); - } catch (e) { - throw new Error('Error decoding data: ' + e); - } - - try { - var v = Message._verify(frompubkey, sig, encrypted); - } catch (e) { - throw new Error('Error verifying signature: ' + e); - } - - if (!v) { - throw new Error('Invalid signature'); - } - - try { - var decryptedhexbuf = Message._decrypt(key.private, encrypted); - var decrypted = new Buffer(decryptedhexbuf.toString(), 'hex'); //workaround for bug in bitcore/sjcl - } catch (e) { - throw new Error('Cannot decrypt data: ' + e); - } - - try { - var version1 = decrypted[0]; - var version2 = decrypted[1]; - var nonce = decrypted.slice(2, 10); - var payload = decrypted.slice(10); - } catch (e) { - throw new Error('Cannot parse decrypted data: ' + e); - } - - if (payload.length === 0) { - throw new Error('No data present'); - } - - if (version1 !== 1) { - throw new Error('Invalid version number'); - } - - if (version2 !== 0) { - //put special version2 handling code here, if ever needed - } - - if (!Message._noncegt(nonce, prevnonce) && prevnonce.toString('hex') !== '0000000000000000') { - throw new Error('Nonce not equal to zero and not greater than the previous nonce'); - } - - var decoded = { - version1: version1, - version2: version2, - nonce: nonce, - payload: payload - }; - - return decoded; -}; - -//return true if nonce > prevnonce; false otherwise -Message._noncegt = function(nonce, prevnonce) { - var noncep1 = nonce.slice(0, 4).readUInt32BE(0); - var prevnoncep1 = prevnonce.slice(0, 4).readUInt32BE(0); - - if (noncep1 > prevnoncep1) - return true; - - if (noncep1 < prevnoncep1) - return false; - - var noncep2 = nonce.slice(4, 8).readUInt32BE(0); - var prevnoncep2 = prevnonce.slice(4, 8).readUInt32BE(0); - - if (noncep2 > prevnoncep2) - return true; - - return false; -}; - -Message._encrypt = function(topubkey, payload, r, iv) { - var encrypted = bitcore.ECIES.encrypt(topubkey, payload, r, iv); - return encrypted; -}; - -Message._decrypt = function(privkey, encrypted) { - var decrypted = bitcore.ECIES.decrypt(privkey, encrypted); - return decrypted; -}; - -Message._sign = function(key, payload) { - var sig = bitcore.Message.sign(payload, key); - return sig; -}; - -Message._verify = function(pubkey, signature, payload) { - var v = bitcore.Message.verifyWithPubKey(pubkey, payload, signature); - return v; -}; - -module.exports = Message; diff --git a/test/test.Message.js b/test/test.Message.js deleted file mode 100644 index 9bad687d1..000000000 --- a/test/test.Message.js +++ /dev/null @@ -1,159 +0,0 @@ -'use strict'; - -var chai = chai || require('chai'); -var should = chai.should(); -var sinon = require('sinon'); -var Message = require('../js/models/core/Message'); -var bitcore = bitcore || require('bitcore'); -var Buffer = bitcore.Buffer; - -describe('Message model', function() { - var key = new bitcore.Key(); - key.private = bitcore.util.sha256(new Buffer('test')); - key.regenerateSync(); - - var key2 = new bitcore.Key(); - key2.private = bitcore.util.sha256(new Buffer('test 2')); - key2.regenerateSync(); - - describe('#encode', function() { - - it('should encode a message', function() { - var message = new Buffer('message'); - var encoded = Message.encode(key2.public, key, message); - should.exist(encoded.pubkey); - should.exist(encoded.sig); - should.exist(encoded.encrypted); - }); - - }); - - describe('#decode', function() { - - it('should decode an encoded message', function() { - var message = new Buffer('message'); - var messagehex = message.toString('hex'); - var encoded = Message.encode(key2.public, key, message); - - var decoded = Message.decode(key2, encoded); - var payload = decoded.payload; - payload.toString('hex').should.equal(messagehex); - }); - - it('should decode an encoded message with proper prevnonce', function() { - var message = new Buffer('message'); - var messagehex = message.toString('hex'); - var nonce = new Buffer([0, 0, 0, 0, 0, 0, 0, 2]); - var opts = {nonce: nonce}; - var encoded = Message.encode(key2.public, key, message, opts); - - var prevnonce = new Buffer([0, 0, 0, 0, 0, 0, 0, 1]); - opts = {prevnonce: prevnonce}; - var decoded = Message.decode(key2, encoded, opts); - var payload = decoded.payload; - payload.toString('hex').should.equal(messagehex); - }); - - it('should decode an encoded message with proper prevnonce - for first part', function() { - var message = new Buffer('message'); - var messagehex = message.toString('hex'); - var nonce = new Buffer([0, 0, 0, 2, 0, 0, 0, 0]); - var opts = {nonce: nonce}; - var encoded = Message.encode(key2.public, key, message, opts); - - var prevnonce = new Buffer([0, 0, 0, 1, 0, 0, 0, 0]); - opts = {prevnonce: prevnonce}; - var decoded = Message.decode(key2, encoded, opts); - var payload = decoded.payload; - payload.toString('hex').should.equal(messagehex); - }); - - it('should fail if prevnonce is too high', function() { - var message = new Buffer('message'); - var messagehex = message.toString('hex'); - var nonce = new Buffer([0, 0, 0, 0, 0, 0, 0, 1]); - var opts = {nonce: nonce}; - var encoded = Message.encode(key2.public, key, message, opts); - - var prevnonce = new Buffer([0, 0, 0, 0, 0, 0, 0, 1]); - opts = {prevnonce: prevnonce}; - (function() {Message.decode(key2, encoded, opts)}).should.throw('Nonce not equal to zero and not greater than the previous nonce'); - }); - - it('should fail if prevnonce is too high - for first part', function() { - var message = new Buffer('message'); - var messagehex = message.toString('hex'); - var nonce = new Buffer([0, 0, 0, 1, 0, 0, 0, 0]); - var opts = {nonce: nonce}; - var encoded = Message.encode(key2.public, key, message, opts); - - var prevnonce = new Buffer([0, 0, 0, 1, 0, 0, 0, 0]); - opts = {prevnonce: prevnonce}; - (function() {Message.decode(key2, encoded, opts)}).should.throw('Nonce not equal to zero and not greater than the previous nonce'); - }); - - it('should fail if the version number is incorrect', function() { - var payload = new Buffer('message'); - var fromkey = key; - var topubkey = key2.public; - var version1 = new Buffer([2]); - var version2 = new Buffer([0]); - var nonce = new Buffer([0, 0, 0, 0, 0, 0, 0, 0]); - var toencrypt = Buffer.concat([version1, version2, nonce, payload]); - var toencrypt_workaround = new Buffer(toencrypt.toString('hex')); - var encrypted = Message._encrypt(topubkey, toencrypt_workaround); - var sig = Message._sign(fromkey, encrypted); - var encoded = { - pubkey: fromkey.public.toString('hex'), - sig: sig.toString('hex'), - encrypted: encrypted.toString('hex') - }; - - (function() {Message.decode(key2, encoded);}).should.throw('Invalid version number'); - }); - - }); - - describe('#_encrypt', function() { - - it('should encrypt data', function() { - var payload = new Buffer('payload'); - var encrypted = Message._encrypt(key.public, payload); - encrypted.length.should.equal(129); - }); - - }); - - describe('#_decrypt', function() { - var payload = new Buffer('payload'); - var payloadhex = payload.toString('hex'); - - it('should decrypt encrypted data', function() { - var encrypted = Message._encrypt(key.public, payload); - var decrypted = Message._decrypt(key.private, encrypted); - decrypted.toString('hex').should.equal(payloadhex); - }); - - }); - - describe('#_sign', function() { - - it('should sign data', function() { - var payload = new Buffer('payload'); - var sig = Message._sign(key, payload); - sig.length.should.be.greaterThan(60); - }); - - }); - - describe('#_verify', function() { - var payload = new Buffer('payload'); - var sig = Message._sign(key, payload); - - it('should verify signed data', function() { - Message._verify(key.public, sig, payload).should.equal(true); - }); - - }); - -});