Skip to content

Commit

Permalink
Add schnorr signing and verification
Browse files Browse the repository at this point in the history
  • Loading branch information
junderw committed Nov 11, 2021
1 parent f6b9b5b commit c8dfd2c
Show file tree
Hide file tree
Showing 4 changed files with 30 additions and 1 deletion.
8 changes: 8 additions & 0 deletions src/bip32.js
Original file line number Diff line number Diff line change
Expand Up @@ -209,9 +209,17 @@ function default_1(ecc) {
return sig;
}
}
signSchnorr(hash) {
if (!this.privateKey)
throw new Error('Missing private key');
return Buffer.from(ecc.signSchnorr(hash, this.privateKey));
}
verify(hash, signature) {
return ecc.verify(hash, this.publicKey, signature);
}
verifySchnorr(hash, signature) {
return ecc.verifySchnorr(hash, this.publicKey.subarray(1, 33), signature);
}
}
function fromBase58(inString, network) {
const buffer = bs58check.decode(inString);
Expand Down
6 changes: 5 additions & 1 deletion test/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -215,15 +215,19 @@ tape('ecdsa', (t) => {
let seed = Buffer.alloc(32, 1)
let hash = Buffer.alloc(32, 2)
let signature = Buffer.from('9636ee2fac31b795a308856b821ebe297dda7b28220fb46ea1fbbd7285977cc04c82b734956246a0f15a9698f03f546d8d96fe006c8e7bd2256ca7c8229e6f5c', 'hex')
let schnorrsig = Buffer.from('2fae8b517cb0e7302ca48a4109d1819e3d75af96bd58d297023e3058c4e98ff812fe6ae32a2b2bc4abab10f88f7fe56efbafc8a4e4fa437af78926f528b0585e', 'hex')
let signatureLowR = Buffer.from('0587a40b391b76596c257bf59565b24eaff2cc42b45caa2640902e73fb97a6e702c3402ab89348a7dae1bf171c3e172fa60353d7b01621a94cb7caca59b995db', 'hex')
let node = BIP32.fromSeed(seed)

t.plan(6)
t.plan(9)
t.equal(node.sign(hash).toString('hex'), signature.toString('hex'))
t.equal(node.sign(hash, true).toString('hex'), signatureLowR.toString('hex'))
t.equal(node.signSchnorr(hash).toString('hex'), schnorrsig.toString('hex'))
t.equal(node.verify(hash, signature), true)
t.equal(node.verify(seed, signature), false)
t.equal(node.verify(hash, signatureLowR), true)
t.equal(node.verify(seed, signatureLowR), false)
t.equal(node.verifySchnorr(hash, schnorrsig), true)
t.equal(node.verifySchnorr(seed, schnorrsig), false)
})
})
13 changes: 13 additions & 0 deletions ts-src/bip32.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ export interface BIP32Interface {
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;
}

export interface BIP32API {
Expand Down Expand Up @@ -63,12 +65,14 @@ export interface TinySecp256k1Interface {
): Uint8Array | null;
privateAdd(d: Uint8Array, tweak: Uint8Array): Uint8Array | null;
sign(h: Uint8Array, d: Uint8Array, e?: Uint8Array): Uint8Array;
signSchnorr(h: Uint8Array, d: Uint8Array, e?: Uint8Array): Uint8Array;
verify(
h: Uint8Array,
Q: Uint8Array,
signature: Uint8Array,
strict?: boolean,
): boolean;
verifySchnorr(h: Uint8Array, Q: Uint8Array, signature: Uint8Array): boolean;
}

export default function(ecc: TinySecp256k1Interface): BIP32API {
Expand Down Expand Up @@ -340,9 +344,18 @@ export default function(ecc: TinySecp256k1Interface): BIP32API {
}
}

signSchnorr(hash: Buffer): Buffer {
if (!this.privateKey) throw new Error('Missing private key');
return Buffer.from(ecc.signSchnorr(hash, this.privateKey));
}

verify(hash: Buffer, signature: Buffer): boolean {
return ecc.verify(hash, this.publicKey, signature);
}

verifySchnorr(hash: Buffer, signature: Buffer): boolean {
return ecc.verifySchnorr(hash, this.publicKey.subarray(1, 33), signature);
}
}

function fromBase58(inString: string, network?: Network): BIP32Interface {
Expand Down
4 changes: 4 additions & 0 deletions types/bip32.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ export interface BIP32Interface {
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;
}
export interface BIP32API {
fromSeed(seed: Buffer, network?: Network): BIP32Interface;
Expand All @@ -44,7 +46,9 @@ export interface TinySecp256k1Interface {
pointAddScalar(p: Uint8Array, tweak: Uint8Array, compressed?: boolean): Uint8Array | null;
privateAdd(d: Uint8Array, tweak: Uint8Array): Uint8Array | null;
sign(h: Uint8Array, d: Uint8Array, e?: Uint8Array): Uint8Array;
signSchnorr(h: Uint8Array, d: Uint8Array, e?: Uint8Array): Uint8Array;
verify(h: Uint8Array, Q: Uint8Array, signature: Uint8Array, strict?: boolean): boolean;
verifySchnorr(h: Uint8Array, Q: Uint8Array, signature: Uint8Array): boolean;
}
export default function (ecc: TinySecp256k1Interface): BIP32API;
export {};

0 comments on commit c8dfd2c

Please sign in to comment.