diff --git a/_code-samples/key-derivation/js/index.js b/_code-samples/key-derivation/js/index.js index eb08b51fb6..bc721f5dc8 100644 --- a/_code-samples/key-derivation/js/index.js +++ b/_code-samples/key-derivation/js/index.js @@ -3,16 +3,49 @@ // Organize imports const assert = require("assert") const brorand = require("brorand") -const BN = require("bn.js") +const { BigNumber } = require("bignumber.js") const elliptic = require("elliptic"); const Ed25519 = elliptic.eddsa('ed25519'); const Secp256k1 = elliptic.ec('secp256k1'); const hashjs = require("hash.js"); -const Sha512 = require("ripple-keypairs/dist/Sha512") +const isomorphic = require("@xrplf/isomorphic/sha512") +const noble = require('@noble/curves/abstract/utils') const { codec, encodeAccountPublic, encodeNodePublic } = require("ripple-address-codec"); const XRPL_SEED_PREFIX = 0x21 +class Sha512 { + // instantiate empty sha512 hash + hash = isomorphic.sha512.create() + + static half(input) { + return new Sha512().add(input).first256() + } + + add(bytes) { + this.hash.update(bytes) + return this + } + + addU32(i) { + const buffer = new Uint8Array(4) + new DataView(buffer.buffer).setUint32(0, i) + return this.add(buffer) + } + + finish() { + return this.hash.digest() + } + + first256() { + return this.finish().slice(0, 32) + } + + first256BigInt() { + return noble.bytesToNumberBE(this.first256()) + } +} + const isHex = function(value) { const regex = new RegExp(/^[0-9a-f]+$/, 'i') return regex.test(value) @@ -27,7 +60,7 @@ const bytesToHex = function(bytes) { const hexToBytes = function(hex) { assert.ok(hex.length % 2 === 0); - return hex.length === 0 ? [] : new BN(hex, 16).toArray(null, hex.length / 2); + return hex.length === 0 ? [] : new BigNumber(hex, 16).toArray(null, hex.length / 2); } const encodeUTF8 = function (string) { @@ -87,7 +120,7 @@ class Seed { const publicKey = prefix + bytesToHex(Ed25519.keyFromSecret(rawPrivateKey).pubBytes()); return { privateKey, publicKey }; } - + _deriveSecp256K1Keypair(entropy, options) { const prefix = '00'; const privateKey = prefix + this._deriveSecp256K1PrivateKey(entropy, options).toString(16, 64).toUpperCase() @@ -112,27 +145,25 @@ class Seed { // Almost everyone just uses the first account, `0`. const accountIndex = opts.accountIndex || 0; - return this._deriveScalar(publicGen.encodeCompressed(), accountIndex) - .add(privateGen) - .mod(order); + const scalar = this._deriveScalar(publicGen.encodeCompressed(), accountIndex) + return BigNumber(scalar).plus(privateGen).mod(order); } _deriveScalar(bytes, discrim) { - const order = Secp256k1.curve.n; - for (let i = 0; i <= 0xffffffff; i++) { - // We hash the bytes to find a 256 bit number, looping until we are sure it + const order = Secp256k1.curve.n + for (let i = 0; i <= 0xffff_ffff; i++) { + // We hash the bytes to find a 256-bit number, looping until we are sure it // is less than the order of the curve. - const hasher = new Sha512.default().add(bytes); + const hasher = new Sha512().add(bytes) // If the optional discriminator index was passed in, update the hash. if (discrim !== undefined) { - hasher.addU32(discrim); + hasher.addU32(discrim) } - hasher.addU32(i); - const key = hasher.first256BN(); + hasher.addU32(i) + const key = hasher.first256BigInt() /* istanbul ignore else */ - /* istanbul ignore else */ - if (key.cmpn(0) > 0 && key.cmp(order) < 0) { - return key; + if (key > 0 && key < order) { + return key } } // This error is practically impossible to reach. @@ -141,10 +172,10 @@ class Seed { // How often will an (essentially) random number generated by Sha512 be larger than that? // There's 2^32 chances (the for loop) to get a number smaller than the order, // and it's rare that you'll even get past the first loop iteration. - // Note that in TypeScript we actually need the throw, otherwise the function signature would be BN | undefined + // Note that in TypeScript we actually need the throw, otherwise the function signature would be bigint | undefined // /* istanbul ignore next */ - throw new Error('impossible unicorn ;)'); + throw new Error('impossible unicorn ;)') } getBase58ED25519Account() { diff --git a/_code-samples/key-derivation/js/package.json b/_code-samples/key-derivation/js/package.json index dfe5d1842a..ce29c3ea52 100644 --- a/_code-samples/key-derivation/js/package.json +++ b/_code-samples/key-derivation/js/package.json @@ -3,7 +3,16 @@ "version": "0.1.0", "license": "MIT", "dependencies": { - "xrpl": "^2.11.0" + "@noble/curves": "^1.3.0", + "@xrplf/isomorphic": "^1.0.0", + "bignumber.js": "^9.1.2", + "brorand": "^1.1.0", + "elliptic": "^6.5.4", + "hash.js": "^1.1.7", + "ripple-address-codec": "^5.0.0", + "ripple-keypairs": "^2.0.0", + "secp256k1": "^5.0.0", + "xrpl": "^3.0.0" }, "main": "index.js", "scripts": {