From 8979a3cf02c3726dbd53f3c6481d9f898194e79d Mon Sep 17 00:00:00 2001 From: wltsmrz Date: Thu, 15 May 2014 07:25:16 -0700 Subject: [PATCH] Merge branch account-ids --- src/js/ripple/seed.js | 52 ++++++++++++++++++++++++++++------- test/seed-test.js | 63 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 105 insertions(+), 10 deletions(-) create mode 100644 test/seed-test.js diff --git a/src/js/ripple/seed.js b/src/js/ripple/seed.js index 511379f9..688cfeac 100644 --- a/src/js/ripple/seed.js +++ b/src/js/ripple/seed.js @@ -11,6 +11,7 @@ var BigInteger = utils.jsbn.BigInteger; var Base = require('./base').Base; var UInt = require('./uint').UInt; var UInt256 = require('./uint256').UInt256; +var UInt160 = require('./uint160').UInt160; var KeyPair = require('./keypair').KeyPair; var Seed = extend(function () { @@ -83,16 +84,33 @@ function SHA256_RIPEMD160(bits) { return sjcl.hash.ripemd160.hash(sjcl.hash.sha256.hash(bits)); }; -Seed.prototype.get_key = function (account_id) { +/** +* @param account +* {undefined} take first, default, KeyPair +* +* {Number} specifies the account number of the KeyPair +* desired. +* +* {Uint160} (from_json able), specifies the address matching the KeyPair +* that is desired. +*/ +Seed.prototype.get_key = function (account) { + var account_number = 0, address; + if (!this.is_valid()) { throw new Error('Cannot generate keys from invalid seed!'); } - - // XXX Should loop over keys until we find the right one + if (account) { + if (typeof account === 'number') { + account_number = account; + } else { + address = UInt160.from_json(account); + } + } var private_gen, public_gen; var curve = this._curve; - var seq = 0, i = 0; + var i = 0; do { private_gen = sjcl.bn.fromBits(firstHalfOfSHA512(append_int(this.to_bytes(), i))); @@ -102,16 +120,30 @@ Seed.prototype.get_key = function (account_id) { public_gen = curve.G.mult(private_gen); var sec; - i = 0; + var key_pair; + var max_loops = 1000; // TODO do { - sec = sjcl.bn.fromBits(firstHalfOfSHA512(append_int(append_int(public_gen.toBytesCompressed(), seq), i))); - i++; - } while (!curve.r.greaterEquals(sec)); + i = 0; - sec = sec.add(private_gen).mod(curve.r); + do { + sec = sjcl.bn.fromBits(firstHalfOfSHA512(append_int(append_int(public_gen.toBytesCompressed(), account_number), i))); + i++; + } while (!curve.r.greaterEquals(sec)); - return KeyPair.from_bn_secret(sec); + account_number++; + sec = sec.add(private_gen).mod(curve.r); + key_pair = KeyPair.from_bn_secret(sec); + + if (--max_loops <= 0) { + // We are almost certainly looking for an account that would take same + // value of $too_long {forever, ...} + throw new Error('Too many loops looking for KeyPair yielding '+ + address.to_json() +' from ' + this.to_json()); + }; + } while (address && !key_pair.get_address().equals(address)); + + return key_pair; }; exports.Seed = Seed; diff --git a/test/seed-test.js b/test/seed-test.js new file mode 100644 index 00000000..d3785197 --- /dev/null +++ b/test/seed-test.js @@ -0,0 +1,63 @@ +var assert = require('assert'); +var utils = require('./testutils'); +var Seed = utils.load_module('seed').Seed; +var config = require('./testutils').get_config(); + +describe('Seed', function() { + it('can generate many addresses', function () { + var seed = Seed.from_json("masterpassphrase"); + + // Note: Created with jRippleAPI code + // Link: https://github.com/pmarches/jRippleAPI/blob/master/src/jrippleapi/keys/RippleDeterministicKeyGenerator.java + + // To reviewer/merger: Even generating keypairs for thi this small amount of + // addresses makes the test suite run SO SLOW. Consider cutting at the tail. + var first_nth_addresses = [ + // 0th implied + "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh", + // 1th implied + "r4bYF7SLUMD7QgSLLpgJx38WJSY12ViRjP", + // 2th implied + "rLpAd4peHUMBPbVJASMYK5GTBUSwXRD9nx", + // ... + "rN9HWHPAftXC6xNxJRqgVr1HexpUi6FBUa", + "rhwPfeEkeQh2vqoKGPBpPyS9nKmKZdpypu", + "rKdNfPfrzfisDCPCqK67YhDLezuVKGKXNm", + "rsn4NeGzMRvMn5ABQxmt9VNEkSknVneBK4", + "rUSJGFH1kQnaKpoAhkArfyw6HZVe8GT5w3", + "r3EYp6isx2Row5pu19C4Ujvp68oEEabhuA", + "rGiYpnAn9DTXiM78CCJcYAuL6QHEDdazHA", + "rVrRVeqqEJHAove5B9TqBAHEXBTzMi5eu", + "rJbarThDXYXxtCgDxRoTCDf2NoYdgSjuVk", + "rfuWNJ1TkQzoZZcc4K8wmtsUiGwURFbed1", + "rpuTqebfbZZdKEUV3bjecoViNL4W4gepWZ", + "r42ywHUco4C2AjgaSmYM7uX13Kbz6GdDKp", + "rnWb45MLd5hQiB6Arr94DdY2z95quL7XNf", + "rMukaQ87bfAeddcT16RtgS3RbFmaQWrSGu", + "rN6dMHU51K9y8eVMhjQMsQVp5gPwt3eYYx", + "rfRFyeJDNqpfZVFmjNj9tNzFVsCNAWKtNc", + "rMoGSX48KrT31HKx9KfMSnYhjvRw3YYzQW", + "rfTiEfbeVsYU7QEe1Zfogiz7h43x6ChKGC" + ] + + function assert_helper(account_id, expected) { + var keypair = seed.get_key(account_id); + assert.strictEqual(keypair.get_address().to_json(), + expected); + } + for (var nth = 0; nth < first_nth_addresses.length; nth++) { + var expected = first_nth_addresses[nth], looking_for; + + //`seed.get_key($ripple_address)` is arguably an ill concieved feature + // as it needs to generate `nth` many keypairs and generate hashed public + // keys (addresses) for equality tests ?? + // Would need remote.set_secret(address, private_key_not_seed) ?? + assert_helper((looking_for = expected), expected) + + // This isn't too bad as it only needs to generate one keypair `seq` + assert_helper((looking_for = nth), expected) + }; + }); +}); + +// vim:sw=2:sts=2:ts=8:et