Comparing version 3.0.1 to 3.1.0
{ | ||
"name": "bip32", | ||
"version": "3.0.1", | ||
"version": "3.1.0", | ||
"description": "A BIP32 compatible library", | ||
@@ -40,6 +40,6 @@ "keywords": [ | ||
"dependencies": { | ||
"@types/node": "10.12.18", | ||
"bs58check": "^2.1.1", | ||
"create-hash": "^1.2.0", | ||
"create-hmac": "^1.1.7", | ||
"ripemd160": "^2.0.2", | ||
"typeforce": "^1.11.5", | ||
@@ -49,6 +49,8 @@ "wif": "^2.0.6" | ||
"devDependencies": { | ||
"@types/node": "10.12.18", | ||
"@types/ripemd160": "^2.0.0", | ||
"nyc": "^15.0.0", | ||
"prettier": "1.16.4", | ||
"tape": "^4.13.2", | ||
"tiny-secp256k1": "^2.1.0", | ||
"tiny-secp256k1": "^2.2.1", | ||
"tslint": "^6.1.0", | ||
@@ -55,0 +57,0 @@ "typescript": "3.3.3333" |
@@ -18,5 +18,5 @@ # bip32 | ||
let node: BIP32Interface = bip32.fromBase58('xprv9s21ZrQH143K3QTDL4LXw2F7HEK3wJUD2nW2nRk4stbPy6cq3jPPqjiChkVvvNKmPGJxWUtg6LnF5kejMRNNU3TGtRBeJgk33yuGBxrMPHi'); | ||
const node: BIP32Interface = bip32.fromBase58('xprv9s21ZrQH143K3QTDL4LXw2F7HEK3wJUD2nW2nRk4stbPy6cq3jPPqjiChkVvvNKmPGJxWUtg6LnF5kejMRNNU3TGtRBeJgk33yuGBxrMPHi'); | ||
let child: BIP32Interface = node.derivePath('m/0/0'); | ||
const child: BIP32Interface = node.derivePath('m/0/0'); | ||
// ... | ||
@@ -28,12 +28,10 @@ ``` | ||
``` javascript | ||
let BIP32Factory = require('bip32').default | ||
// tiny-secp256k1 v2 is ES module and must be imported, not required | ||
// (This requires v14 of node or greater) | ||
// But as long as you implement the interface, any library is fine | ||
import('tiny-secp256k1').then(ecc => BIP32Factory(ecc)).then(bip32 => { | ||
let node = bip32.fromBase58('xprv9s21ZrQH143K3QTDL4LXw2F7HEK3wJUD2nW2nRk4stbPy6cq3jPPqjiChkVvvNKmPGJxWUtg6LnF5kejMRNNU3TGtRBeJgk33yuGBxrMPHi') | ||
const ecc = require('tiny-secp256k1') | ||
const { BIP32Factory } = require('bip32') | ||
// You must wrap a tiny-secp256k1 compatible implementation | ||
const bip32 = BIP32Factory(ecc) | ||
let child = node.derivePath('m/0/0') | ||
// ... | ||
}) | ||
const node = bip32.fromBase58('xprv9s21ZrQH143K3QTDL4LXw2F7HEK3wJUD2nW2nRk4stbPy6cq3jPPqjiChkVvvNKmPGJxWUtg6LnF5kejMRNNU3TGtRBeJgk33yuGBxrMPHi') | ||
const child = node.derivePath('m/0/0') | ||
``` | ||
@@ -40,0 +38,0 @@ |
128
src/bip32.js
@@ -37,6 +37,60 @@ "use strict"; | ||
} | ||
class BIP32 { | ||
constructor(__D, __Q, chainCode, network, __DEPTH = 0, __INDEX = 0, __PARENT_FINGERPRINT = 0x00000000) { | ||
function toXOnly(pubKey) { | ||
return pubKey.length === 32 ? pubKey : pubKey.slice(1, 33); | ||
} | ||
class Bip32Signer { | ||
constructor(__D, __Q) { | ||
this.__D = __D; | ||
this.__Q = __Q; | ||
this.lowR = false; | ||
} | ||
get publicKey() { | ||
if (this.__Q === undefined) | ||
this.__Q = Buffer.from(ecc.pointFromScalar(this.__D, true)); | ||
return this.__Q; | ||
} | ||
get privateKey() { | ||
return this.__D; | ||
} | ||
sign(hash, lowR) { | ||
if (!this.privateKey) | ||
throw new Error('Missing private key'); | ||
if (lowR === undefined) | ||
lowR = this.lowR; | ||
if (lowR === false) { | ||
return Buffer.from(ecc.sign(hash, this.privateKey)); | ||
} | ||
else { | ||
let sig = Buffer.from(ecc.sign(hash, this.privateKey)); | ||
const extraData = Buffer.alloc(32, 0); | ||
let counter = 0; | ||
// if first try is lowR, skip the loop | ||
// for second try and on, add extra entropy counting up | ||
while (sig[0] > 0x7f) { | ||
counter++; | ||
extraData.writeUIntLE(counter, 0, 6); | ||
sig = Buffer.from(ecc.sign(hash, this.privateKey, extraData)); | ||
} | ||
return sig; | ||
} | ||
} | ||
signSchnorr(hash) { | ||
if (!this.privateKey) | ||
throw new Error('Missing private key'); | ||
if (!ecc.signSchnorr) | ||
throw new Error('signSchnorr not supported by ecc library'); | ||
return Buffer.from(ecc.signSchnorr(hash, this.privateKey)); | ||
} | ||
verify(hash, signature) { | ||
return ecc.verify(hash, this.publicKey, signature); | ||
} | ||
verifySchnorr(hash, signature) { | ||
if (!ecc.verifySchnorr) | ||
throw new Error('verifySchnorr not supported by ecc library'); | ||
return ecc.verifySchnorr(hash, this.publicKey.subarray(1, 33), signature); | ||
} | ||
} | ||
class BIP32 extends Bip32Signer { | ||
constructor(__D, __Q, chainCode, network, __DEPTH = 0, __INDEX = 0, __PARENT_FINGERPRINT = 0x00000000) { | ||
super(__D, __Q); | ||
this.chainCode = chainCode; | ||
@@ -48,3 +102,2 @@ this.network = network; | ||
typeforce(NETWORK_TYPE, network); | ||
this.lowR = false; | ||
} | ||
@@ -60,10 +113,2 @@ get depth() { | ||
} | ||
get publicKey() { | ||
if (this.__Q === undefined) | ||
this.__Q = Buffer.from(ecc.pointFromScalar(this.__D, true)); | ||
return this.__Q; | ||
} | ||
get privateKey() { | ||
return this.__D; | ||
} | ||
get identifier() { | ||
@@ -195,39 +240,32 @@ return crypto.hash160(this.publicKey); | ||
} | ||
sign(hash, lowR) { | ||
if (!this.privateKey) | ||
throw new Error('Missing private key'); | ||
if (lowR === undefined) | ||
lowR = this.lowR; | ||
if (lowR === false) { | ||
return Buffer.from(ecc.sign(hash, this.privateKey)); | ||
} | ||
else { | ||
let sig = Buffer.from(ecc.sign(hash, this.privateKey)); | ||
const extraData = Buffer.alloc(32, 0); | ||
let counter = 0; | ||
// if first try is lowR, skip the loop | ||
// for second try and on, add extra entropy counting up | ||
while (sig[0] > 0x7f) { | ||
counter++; | ||
extraData.writeUIntLE(counter, 0, 6); | ||
sig = Buffer.from(ecc.sign(hash, this.privateKey, extraData)); | ||
} | ||
return sig; | ||
} | ||
tweak(t) { | ||
if (this.privateKey) | ||
return this.tweakFromPrivateKey(t); | ||
return this.tweakFromPublicKey(t); | ||
} | ||
signSchnorr(hash) { | ||
if (!this.privateKey) | ||
throw new Error('Missing private key'); | ||
if (!ecc.signSchnorr) | ||
throw new Error('signSchnorr not supported by ecc library'); | ||
return Buffer.from(ecc.signSchnorr(hash, this.privateKey)); | ||
tweakFromPublicKey(t) { | ||
const xOnlyPubKey = toXOnly(this.publicKey); | ||
const tweakedPublicKey = ecc.xOnlyPointAddTweak(xOnlyPubKey, t); | ||
if (!tweakedPublicKey || tweakedPublicKey.xOnlyPubkey === null) | ||
throw new Error('Cannot tweak public key!'); | ||
const parityByte = Buffer.from([ | ||
tweakedPublicKey.parity === 0 ? 0x02 : 0x03, | ||
]); | ||
const tweakedPublicKeyCompresed = Buffer.concat([ | ||
parityByte, | ||
tweakedPublicKey.xOnlyPubkey, | ||
]); | ||
return new Bip32Signer(undefined, tweakedPublicKeyCompresed); | ||
} | ||
verify(hash, signature) { | ||
return ecc.verify(hash, this.publicKey, signature); | ||
tweakFromPrivateKey(t) { | ||
const hasOddY = this.publicKey[0] === 3 || | ||
(this.publicKey[0] === 4 && (this.publicKey[64] & 1) === 1); | ||
const privateKey = hasOddY | ||
? ecc.privateNegate(this.privateKey) | ||
: this.privateKey; | ||
const tweakedPrivateKey = ecc.privateAdd(privateKey, t); | ||
if (!tweakedPrivateKey) | ||
throw new Error('Invalid tweaked private key!'); | ||
return new Bip32Signer(Buffer.from(tweakedPrivateKey), undefined); | ||
} | ||
verifySchnorr(hash, signature) { | ||
if (!ecc.verifySchnorr) | ||
throw new Error('verifySchnorr not supported by ecc library'); | ||
return ecc.verifySchnorr(hash, this.publicKey.subarray(1, 33), signature); | ||
} | ||
} | ||
@@ -234,0 +272,0 @@ function fromBase58(inString, network) { |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
const RipeMd160 = require("ripemd160"); | ||
const createHash = require('create-hash'); | ||
@@ -15,5 +16,10 @@ const createHmac = require('create-hmac'); | ||
catch (err) { | ||
return createHash('ripemd160') | ||
.update(sha256Hash) | ||
.digest(); | ||
try { | ||
return createHash('ripemd160') | ||
.update(sha256Hash) | ||
.digest(); | ||
} | ||
catch (err2) { | ||
return new RipeMd160().update(sha256Hash).digest(); | ||
} | ||
} | ||
@@ -20,0 +26,0 @@ } |
@@ -17,4 +17,11 @@ "use strict"; | ||
assert(Buffer.from(ecc.pointFromScalar(h('b1121e4088a66a28f5b6b0f5844943ecd9f610196d7bb83b25214b60452c09af'))).equals(h('02b07ba9dca9523b7ef4bd97703d43d20399eb698e194704791a25ce77a400df99'))); | ||
assert(ecc.xOnlyPointAddTweak(h('79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798'), h('fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364140')) === null); | ||
let xOnlyRes = ecc.xOnlyPointAddTweak(h('1617d38ed8d8657da4d4761e8057bc396ea9e4b9d29776d4be096016dbd2509b'), h('a8397a935f0dfceba6ba9618f6451ef4d80637abf4e6af2669fbc9de6a8fd2ac')); | ||
assert(Buffer.from(xOnlyRes.xOnlyPubkey).equals(h('e478f99dab91052ab39a33ea35fd5e6e4933f4d28023cd597c9a1f6760346adf')) && xOnlyRes.parity === 1); | ||
xOnlyRes = ecc.xOnlyPointAddTweak(h('2c0b7cf95324a07d05398b240174dc0c2be444d96b159aa6c7f7b1e668680991'), h('823c3cd2142744b075a87eade7e1b8678ba308d566226a0056ca2b7a76f86b47')); | ||
assert(Buffer.from(ecc.pointAddScalar(h('0379be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798'), h('0000000000000000000000000000000000000000000000000000000000000003'))).equals(h('02c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee5'))); | ||
assert(Buffer.from(ecc.privateAdd(h('fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd036413e'), h('0000000000000000000000000000000000000000000000000000000000000002'))).equals(h('fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364140'))); | ||
assert(Buffer.from(ecc.privateNegate(h('0000000000000000000000000000000000000000000000000000000000000001'))).equals(h('fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364140'))); | ||
assert(Buffer.from(ecc.privateNegate(h('fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd036413e'))).equals(h('0000000000000000000000000000000000000000000000000000000000000003'))); | ||
assert(Buffer.from(ecc.privateNegate(h('b1121e4088a66a28f5b6b0f5844943ecd9f610196d7bb83b25214b60452c09af'))).equals(h('4eede1bf775995d70a494f0a7bb6bc11e0b8cccd41cce8009ab1132c8b0a3792'))); | ||
assert(Buffer.from(ecc.sign(h('5e9f0a0d593efdcf78ac923bc3313e4e7d408d574354ee2b3288c0da9fbba6ed'), h('fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364140'))).equals(h('54c4a33c6423d689378f160a7ff8b61330444abb58fb470f96ea16d99d4a2fed07082304410efa6b2943111b6a4e0aaa7b7db55a07e9861d1fb3cb1f421044a5'))); | ||
@@ -21,0 +28,0 @@ assert(ecc.verify(h('5e9f0a0d593efdcf78ac923bc3313e4e7d408d574354ee2b3288c0da9fbba6ed'), h('0379be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798'), h('54c4a33c6423d689378f160a7ff8b61330444abb58fb470f96ea16d99d4a2fed07082304410efa6b2943111b6a4e0aaa7b7db55a07e9861d1fb3cb1f421044a5'))); |
@@ -13,10 +13,16 @@ /// <reference types="node" /> | ||
} | ||
export interface BIP32Interface { | ||
export interface Signer { | ||
publicKey: Buffer; | ||
lowR: boolean; | ||
sign(hash: Buffer, lowR?: boolean): Buffer; | ||
verify(hash: Buffer, signature: Buffer): boolean; | ||
signSchnorr(hash: Buffer): Buffer; | ||
verifySchnorr(hash: Buffer, signature: Buffer): boolean; | ||
} | ||
export interface BIP32Interface extends Signer { | ||
chainCode: Buffer; | ||
network: Network; | ||
lowR: boolean; | ||
depth: number; | ||
index: number; | ||
parentFingerprint: number; | ||
publicKey: Buffer; | ||
privateKey?: Buffer; | ||
@@ -32,6 +38,3 @@ identifier: Buffer; | ||
derivePath(path: string): BIP32Interface; | ||
sign(hash: Buffer, lowR?: boolean): Buffer; | ||
verify(hash: Buffer, signature: Buffer): boolean; | ||
signSchnorr(hash: Buffer): Buffer; | ||
verifySchnorr(hash: Buffer, signature: Buffer): boolean; | ||
tweak(t: Buffer): Signer; | ||
} | ||
@@ -44,2 +47,6 @@ export interface BIP32API { | ||
} | ||
interface XOnlyPointAddTweakResult { | ||
parity: 1 | 0; | ||
xOnlyPubkey: Uint8Array; | ||
} | ||
export interface TinySecp256k1Interface { | ||
@@ -55,4 +62,6 @@ isPoint(p: Uint8Array): boolean; | ||
verifySchnorr?(h: Uint8Array, Q: Uint8Array, signature: Uint8Array): boolean; | ||
xOnlyPointAddTweak(p: Uint8Array, tweak: Uint8Array): XOnlyPointAddTweakResult | null; | ||
privateNegate(d: Uint8Array): Uint8Array; | ||
} | ||
export declare function BIP32Factory(ecc: TinySecp256k1Interface): BIP32API; | ||
export {}; |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
27296
503
8
39
+ Addedripemd160@^2.0.2
- Removed@types/node@10.12.18
- Removed@types/node@10.12.18(transitive)