From 614a213d449244cadbdb83f2e4db93c2fbc8f816 Mon Sep 17 00:00:00 2001 From: Daniel Cousens Date: Sat, 10 May 2014 09:33:02 +1000 Subject: [PATCH 1/3] Transaction: remove untested hash array support --- src/transaction.js | 1 - 1 file changed, 1 deletion(-) diff --git a/src/transaction.js b/src/transaction.js index a0d77d0..6601ae9 100644 --- a/src/transaction.js +++ b/src/transaction.js @@ -68,7 +68,6 @@ Transaction.prototype.addInput = function (tx, outIndex) { } else { hash = typeof tx === "string" ? tx : tx.hash - hash = Array.isArray(hash) ? convert.bytesToHex(hash) : hash } this.ins.push(new TransactionIn({ From f70ccc9215ef34e44187bd58d001d0c2f46c4909 Mon Sep 17 00:00:00 2001 From: Daniel Cousens Date: Sat, 10 May 2014 08:58:24 +1000 Subject: [PATCH 2/3] convert: remove hex functions --- src/convert.js | 41 +++++------------------------------------ test/convert.js | 23 ----------------------- 2 files changed, 5 insertions(+), 59 deletions(-) diff --git a/src/convert.js b/src/convert.js index 0188ffa..5bcb4a7 100644 --- a/src/convert.js +++ b/src/convert.js @@ -2,36 +2,6 @@ var assert = require('assert') var Crypto = require('crypto-js') var WordArray = Crypto.lib.WordArray -function lpad(str, padString, length) { - while (str.length < length) str = padString + str - return str -} - -function bytesToHex(bytes) { - // FIXME: transitionary fix - if (Buffer.isBuffer(bytes)) { - return bytes.toString('hex') - } - - return bytes.map(function(x) { - return lpad(x.toString(16), '0', 2) - }).join('') -} - -function hexToBytes(hex) { - return hex.match(/../g).map(function(x) { - return parseInt(x,16) - }) -} - -/** - * Convert a byte array to the number that it represents - */ -function bytesToNum(bytes) { - if (bytes.length === 0) return 0 - return bytes[0] + 256 * bytesToNum(bytes.slice(1)) -} - function bytesToWords(bytes) { assert(Array.isArray(bytes) || Buffer.isBuffer(bytes), 'Input must be a byte array') var words = [] @@ -57,15 +27,14 @@ function wordArrayToBytes(wordArray) { return wordsToBytes(wordArray.words) } -function reverseEndian (hex) { - return bytesToHex(hexToBytes(hex).reverse()) +function reverseEndian(hex) { + var buffer = new Buffer(hex, 'hex') + Array.prototype.reverse.call(buffer) + + return buffer.toString('hex') } module.exports = { - lpad: lpad, - bytesToHex: bytesToHex, - hexToBytes: hexToBytes, - bytesToNum: bytesToNum, bytesToWords: bytesToWords, wordsToBytes: wordsToBytes, bytesToWordArray: bytesToWordArray, diff --git a/test/convert.js b/test/convert.js index a22907f..10abfff 100644 --- a/test/convert.js +++ b/test/convert.js @@ -2,29 +2,6 @@ var assert = require('assert') var convert = require('../').convert describe('convert', function() { - describe('bytesToHex', function() { - it('handles example 1', function() { - assert.equal(convert.bytesToHex([0, 1, 2, 255]), '000102ff') - }) - }) - - describe('hexToBytes', function() { - it('handles example 1', function() { - assert.deepEqual(convert.hexToBytes('000102ff'), [0, 1, 2, 255]) - }) - }) - - it('converts from bytes to hex and back', function() { - var bytes = [] - for (var i=0 ; i<256 ; ++i) { - bytes.push(i) - } - - var hex = convert.bytesToHex(bytes) - assert.equal(hex.length, 512) - assert.deepEqual(convert.hexToBytes(hex), bytes) - }) - describe('byte array and word array conversions', function(){ var bytes, wordArray From 276a339d60ab26f91154d067181d45f95f0fe6c8 Mon Sep 17 00:00:00 2001 From: Daniel Cousens Date: Sat, 10 May 2014 09:55:55 +1000 Subject: [PATCH 3/3] crypto: HMACSHA512 into crypto and add tests --- src/crypto.js | 17 ++++++++++++++++- src/hdwallet.js | 17 ++--------------- test/crypto.js | 14 ++++++++++++++ test/fixtures/crypto.js | 11 ++++++++++- 4 files changed, 42 insertions(+), 17 deletions(-) diff --git a/src/crypto.js b/src/crypto.js index 64d69e6..6937f05 100644 --- a/src/crypto.js +++ b/src/crypto.js @@ -1,4 +1,5 @@ // Crypto, crypto, where art thou crypto +var assert = require('assert') var CryptoJS = require('crypto-js') var crypto = require('crypto') var convert = require('./convert') @@ -32,9 +33,23 @@ function sha256(buffer) { return crypto.createHash('sha256').update(buffer).digest() } +// FIXME: Name not consistent with others +function HmacSHA512(data, secret) { + assert(Buffer.isBuffer(data), 'Expected Buffer for data, got ' + data) + assert(Buffer.isBuffer(secret), 'Expected Buffer for secret, got ' + secret) + + var dataWords = convert.bytesToWordArray(data) + var secretWords = convert.bytesToWordArray(secret) + + var hash = CryptoJS.HmacSHA512(dataWords, secretWords) + + return new Buffer(convert.wordArrayToBytes(hash)) +} + module.exports = { sha1: sha1, sha256: sha256, hash160: hash160, - hash256: hash256 + hash256: hash256, + HmacSHA512: HmacSHA512 } diff --git a/src/hdwallet.js b/src/hdwallet.js index 513d08a..c0d68db 100644 --- a/src/hdwallet.js +++ b/src/hdwallet.js @@ -4,7 +4,6 @@ var convert = require('./convert') var Address = require('./address') var BigInteger = require('bigi') -var CJS = require('crypto-js') var crypto = require('./crypto') var ECKey = require('./eckey').ECKey var ECPubKey = require('./eckey').ECPubKey @@ -13,18 +12,6 @@ var networks = require('./networks') var sec = require('./sec') var ecparams = sec("secp256k1") -function HmacSHA512(data, secret) { - assert(Buffer.isBuffer(data)) - assert(Buffer.isBuffer(secret)) - - var dataWords = convert.bytesToWordArray(data) - var secretWords = convert.bytesToWordArray(secret) - - var hash = CJS.HmacSHA512(dataWords, secretWords) - - return new Buffer(convert.wordArrayToBytes(hash)) -} - function HDWallet(seed, networkString) { if (seed == undefined) return; // FIXME: Boo, should be stricter @@ -34,7 +21,7 @@ function HDWallet(seed, networkString) { throw new Error("Unknown network: " + this.network) } - var I = HmacSHA512(seed, HDWallet.MASTER_SECRET) + var I = crypto.HmacSHA512(seed, HDWallet.MASTER_SECRET) var IL = I.slice(0, 32) var IR = I.slice(32) @@ -217,7 +204,7 @@ HDWallet.prototype.derive = function(index) { ]) } - var I = HmacSHA512(data, this.chaincode) + var I = crypto.HmacSHA512(data, this.chaincode) var IL = I.slice(0, 32) var IR = I.slice(32) diff --git a/test/crypto.js b/test/crypto.js index 9b2068b..ff414d7 100644 --- a/test/crypto.js +++ b/test/crypto.js @@ -46,4 +46,18 @@ describe('Crypto', function() { }) }) }) + + describe('HMAC SHA512', function() { + it('matches the test vector', function() { + fixture.before.hex.forEach(function(hex, i) { + var data = new Buffer(hex, 'hex') + var secret = new Buffer(fixture.after.hmacsha512.secret) + + var actual = crypto.HmacSHA512(data, secret) + var expected = fixture.after.hmacsha512.hash[i] + + assert.equal(actual.toString('hex'), expected) + }) + }) + }) }) diff --git a/test/fixtures/crypto.js b/test/fixtures/crypto.js index 790fa9e..1600a06 100644 --- a/test/fixtures/crypto.js +++ b/test/fixtures/crypto.js @@ -32,6 +32,15 @@ module.exports = { '04abc8821a06e5a30937967d11ad10221cb5ac3b5273e434f1284ee87129a061', '12a3ae445661ce5dee78d0650d33362dec29c4f82af05e7e57fb595bbbacf0ca', 'a7fb8276035057ed6479c5f2305a96da100ac43f0ac10f277e5ab8c5457429da' - ] + ], + hmacsha512: { + secret: 'vires is numeris', + hash: [ + '4c0595aed1f5d066ea9f797727c060eb86cb55ff29d4d4fd2cd0ad3a012386763aea604c030619c79aa7fd8d03cda1b73a9ebd17906a3d2a350108d1a98b24ac', + 'f80b90d63b804b3d2ab03b9bfb3ac94ee271352eb8bddfb6b4f5cf2a4fc9176acea35f517728e64943d1eb8af1e4674a114082c81bc8874d88b408b3b406d6a4', + '134cf60c30a5cd412c7a5cd6c3f878279e139b47c19550b7456fa137fbf90e580ae0a923a22052f42ec801ac658db32821e271161b563eac4926285ba6b8f410', + '7dee95aa3c462d3eb7ecb61536cb215e471d1fa73d8643a967905946e26c536588c5058abd5a049a22b987db95a7fb420f3bff12359dc53d03d7ce7df714e029' + ] + } } }