From fd6df49f5536f3ab3d5e7d4fcc949a80cf899ecf Mon Sep 17 00:00:00 2001 From: Nicholas Dudfield Date: Thu, 16 Jul 2015 20:23:19 +0800 Subject: [PATCH] Updates: * Expose abstract KeyPair * Update ripple-address-codec dependency * Add keyPairFromSeed method, which can handle ed25519 seeds --- packages/ripple-keypairs/package.json | 2 +- packages/ripple-keypairs/src/index.js | 41 ++++++++++--------- .../ripple-keypairs/test/keypairs-test.js | 25 +++++++++-- 3 files changed, 44 insertions(+), 24 deletions(-) diff --git a/packages/ripple-keypairs/package.json b/packages/ripple-keypairs/package.json index a6c3a49c..9934b7fd 100644 --- a/packages/ripple-keypairs/package.json +++ b/packages/ripple-keypairs/package.json @@ -18,7 +18,7 @@ "bn.js": "^3.0.1", "elliptic": "^5.0.0", "hash.js": "^1.0.3", - "ripple-address-codec": "^1.0.3" + "ripple-address-codec": "^1.1.0" }, "devDependencies": { "assert-diff": "^1.0.1", diff --git a/packages/ripple-keypairs/src/index.js b/packages/ripple-keypairs/src/index.js index a35eee10..9f7d06f4 100644 --- a/packages/ripple-keypairs/src/index.js +++ b/packages/ripple-keypairs/src/index.js @@ -188,46 +188,39 @@ Ed25519Pair.prototype.verify = function(message, signature) { * @class * @private */ -function Secp256k1Pair(key) { +function K256Pair(key) { KeyPair.apply(this, arguments); this.type = KeyType.secp256k1; this.key = key; } -util.inherits(Secp256k1Pair, KeyPair); +util.inherits(K256Pair, KeyPair); -Secp256k1Pair.fromSeed = function(seed) { - return new Secp256k1Pair(secp256k1.keyFromPrivate(derivek256Secret(seed))); +K256Pair.fromSeed = function(seed) { + return new K256Pair(secp256k1.keyFromPrivate(derivek256Secret(seed))); }; -hasCachedProperty(Secp256k1Pair, 'pubKeyCanonicalBytes', function() { +hasCachedProperty(K256Pair, 'pubKeyCanonicalBytes', function() { return this.key.getPublic(/*compact*/ true, /*enc*/ 'bytes'); }); /* @param {Array} message (bytes) */ -Secp256k1Pair.prototype.sign = function(message) { +K256Pair.prototype.sign = function(message) { return this._createSignature(message).toDER(); }; -Secp256k1Pair.prototype._createSignature = function(message) { +K256Pair.prototype._createSignature = function(message) { // The key.sign message silently discards options return secp256k1.sign(this.hashMessage(message), this.key, {canonical: true}); }; /* -@param {Array} message (bytes) +@param {Array} message - (bytes) +@return {Array} - 256 bit hash of the message */ -Secp256k1Pair.prototype.signMessage = function(message) { - return this.key.sign(this.hashMessage(message), {canonical: true}); -}; - -/* -@param {Array} message (bytes) -@return {Array} 256 bit hash of the message - */ -Secp256k1Pair.prototype.hashMessage = function(message) { +K256Pair.prototype.hashMessage = function(message) { return hashjs.sha512().update(message).digest().slice(0, 32); }; @@ -235,7 +228,7 @@ Secp256k1Pair.prototype.hashMessage = function(message) { @param {Array} message - bytes @param {Array} signature - DER encoded signature bytes */ -Secp256k1Pair.prototype.verify = function(message, signature) { +K256Pair.prototype.verify = function(message, signature) { try { return this.key.verify(this.hashMessage(message), signature); } catch (e) { @@ -243,10 +236,18 @@ Secp256k1Pair.prototype.verify = function(message, signature) { } }; +function keyPairFromSeed(seedString) { + var decoded = codec.decodeSeed(seedString); + var pair = decoded.type === 'EdSeed' ? Ed25519Pair : K256Pair; + return pair.fromSeed(decoded.bytes); +} + module.exports = { - Secp256k1Pair, + KeyPair, + K256Pair, Ed25519Pair, KeyType, seedFromPhrase, - createAccountID + createAccountID, + keyPairFromSeed }; diff --git a/packages/ripple-keypairs/test/keypairs-test.js b/packages/ripple-keypairs/test/keypairs-test.js index 66d05f8c..e395e8b8 100644 --- a/packages/ripple-keypairs/test/keypairs-test.js +++ b/packages/ripple-keypairs/test/keypairs-test.js @@ -2,7 +2,15 @@ const assert = require('assert'); const utils = require('../src/utils'); -const {KeyType, Secp256k1Pair, seedFromPhrase, Ed25519Pair} = require('../src'); +const keypairs = require('../src'); + +const { + KeyType, + K256Pair, + seedFromPhrase, + Ed25519Pair, + keyPairFromSeed +} = keypairs const {SerializedObject} = require('ripple-lib'); const TX_HASH_PREFIX_SIGN = [0x53, 0x54, 0x58, 0x00]; @@ -68,7 +76,18 @@ describe('ED25519Pair', function() { }); }); -describe('Secp256k1Pair', function() { +describe('keyPairFromSeed', function() { + it('returns an Ed25519Pair from an ed25519 seed', function() { + const pair = keyPairFromSeed('sEdTM1uX8pu2do5XvTnutH6HsouMaM2'); + assert(pair instanceof Ed25519Pair); + }); + it('returns a K256Pair from an secp256k1 (default) seed', function() { + const pair = keyPairFromSeed('sn259rEFXrQrWyx3Q7XneWcwV6dfL'); + assert(pair instanceof K256Pair); + }); +}); + +describe('K256Pair', function() { describe('generated tests', function() { /*eslint-disable max-len*/ const expected = [ @@ -79,7 +98,7 @@ describe('Secp256k1Pair', function() { '3045022100998ABE378F4119D8BEE9843482C09F0D5CE5C6012921548182454C610C57A269022036BD8EB71235C4B2C67339DE6A59746B1F7E5975987B7AB99B313D124A69BB9F' ]; /*eslint-enable max-len*/ - const key = Secp256k1Pair.fromSeed(seedFromPhrase('niq')); + const key = K256Pair.fromSeed(seedFromPhrase('niq')); function test_factory(i) { it('can deterministically sign/verify message [' + i + ']', function() { const message = [i];