|
@ -22,10 +22,10 @@ interface ECPairOptions { |
|
|
export interface ECPairInterface { |
|
|
export interface ECPairInterface { |
|
|
compressed: boolean; |
|
|
compressed: boolean; |
|
|
network: Network; |
|
|
network: Network; |
|
|
|
|
|
publicKey: Buffer; |
|
|
privateKey?: Buffer; |
|
|
privateKey?: Buffer; |
|
|
publicKey?: Buffer; |
|
|
|
|
|
toWIF(): string; |
|
|
toWIF(): string; |
|
|
sign(hash: Buffer): Buffer; |
|
|
sign(hash: Buffer, lowR?: boolean): Buffer; |
|
|
verify(hash: Buffer, signature: Buffer): boolean; |
|
|
verify(hash: Buffer, signature: Buffer): boolean; |
|
|
getPublicKey?(): Buffer; |
|
|
getPublicKey?(): Buffer; |
|
|
} |
|
|
} |
|
@ -51,8 +51,9 @@ class ECPair implements ECPairInterface { |
|
|
return this.__D; |
|
|
return this.__D; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
get publicKey(): Buffer | undefined { |
|
|
get publicKey(): Buffer { |
|
|
if (!this.__Q) this.__Q = ecc.pointFromScalar(this.__D, this.compressed); |
|
|
if (!this.__Q) |
|
|
|
|
|
this.__Q = ecc.pointFromScalar(this.__D, this.compressed) as Buffer; |
|
|
return this.__Q; |
|
|
return this.__Q; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
@ -61,9 +62,23 @@ class ECPair implements ECPairInterface { |
|
|
return wif.encode(this.network.wif, this.__D, this.compressed); |
|
|
return wif.encode(this.network.wif, this.__D, this.compressed); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
sign(hash: Buffer): Buffer { |
|
|
sign(hash: Buffer, lowR: boolean = false): Buffer { |
|
|
if (!this.__D) throw new Error('Missing private key'); |
|
|
if (!this.__D) throw new Error('Missing private key'); |
|
|
|
|
|
if (lowR === false) { |
|
|
return ecc.sign(hash, this.__D); |
|
|
return ecc.sign(hash, this.__D); |
|
|
|
|
|
} else { |
|
|
|
|
|
let sig = ecc.sign(hash, this.__D); |
|
|
|
|
|
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 = ecc.signWithEntropy(hash, this.__D, extraData); |
|
|
|
|
|
} |
|
|
|
|
|
return sig; |
|
|
|
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
verify(hash: Buffer, signature: Buffer): boolean { |
|
|
verify(hash: Buffer, signature: Buffer): boolean { |
|
@ -77,13 +92,13 @@ function fromPrivateKey(buffer: Buffer, options?: ECPairOptions): ECPair { |
|
|
throw new TypeError('Private key not in range [1, n)'); |
|
|
throw new TypeError('Private key not in range [1, n)'); |
|
|
typeforce(isOptions, options); |
|
|
typeforce(isOptions, options); |
|
|
|
|
|
|
|
|
return new ECPair(buffer, undefined, options as ECPairOptions); |
|
|
return new ECPair(buffer, undefined, options); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
function fromPublicKey(buffer: Buffer, options?: ECPairOptions): ECPair { |
|
|
function fromPublicKey(buffer: Buffer, options?: ECPairOptions): ECPair { |
|
|
typeforce(ecc.isPoint, buffer); |
|
|
typeforce(ecc.isPoint, buffer); |
|
|
typeforce(isOptions, options); |
|
|
typeforce(isOptions, options); |
|
|
return new ECPair(undefined, buffer, options as ECPairOptions); |
|
|
return new ECPair(undefined, buffer, options); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
function fromWIF(wifString: string, network?: Network | Network[]): ECPair { |
|
|
function fromWIF(wifString: string, network?: Network | Network[]): ECPair { |
|
|