Skip to content

Commit

Permalink
Infer network from given address during signing
Browse files Browse the repository at this point in the history
  • Loading branch information
ACken2 committed May 15, 2024
1 parent 653fa83 commit d9af849
Show file tree
Hide file tree
Showing 2 changed files with 45 additions and 13 deletions.
9 changes: 5 additions & 4 deletions src/Signer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,16 +14,17 @@ class Signer {

/**
* Sign a BIP-322 signature from P2WPKH, P2SH-P2WPKH, and single-key-spend P2TR address and its corresponding private key.
* Network is automatically inferred from the given address.
*
* @param privateKey Private key used to sign the message
* @param address Address to be signing the message
* @param message message_challenge to be signed by the address
* @param network Network that the address is located, defaults to the Bitcoin mainnet
* @returns BIP-322 simple signature, encoded in base-64
*/
public static sign(privateKey: string, address: string, message: string, network: bitcoin.Network = bitcoin.networks.bitcoin) {
public static sign(privateKey: string, address: string, message: string) {
// Initialize private key used to sign the transaction
const ECPair = ECPairFactory(ecc);
let signer = ECPair.fromWIF(privateKey, network);
let signer = ECPair.fromWIF(privateKey, [bitcoin.networks.bitcoin, bitcoin.networks.testnet, bitcoin.networks.regtest]);
// Check if the private key can sign message for the given address
if (!this.checkPubKeyCorrespondToAddress(signer.publicKey, address)) {
throw new Error(`Invalid private key provided for signing message for ${address}.`);
Expand All @@ -45,7 +46,7 @@ class Signer {
// Derive the P2SH-P2WPKH redeemScript from the corresponding hashed public key
const redeemScript = bitcoin.payments.p2wpkh({
hash: bitcoin.crypto.hash160(signer.publicKey),
network: network
network: Address.getNetworkFromAddess(address)
}).output as Buffer;
toSignTx = BIP322.buildToSignTx(toSpendTx.getId(), redeemScript, true);
}
Expand Down
49 changes: 40 additions & 9 deletions test/Signer.test.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
// Import dependencies
import { expect } from 'chai';
import * as bitcoin from 'bitcoinjs-lib';
import * as bitcoinMessage from 'bitcoinjs-message';

// Import module to be tested
Expand All @@ -18,14 +17,22 @@ describe('Signer Test', () => {
const message = 'Hello World';

// Act
// Sign with mainnet key
const signature = Signer.sign(privateKey, address, message);
const signatureTestnet = Signer.sign(privateKeyTestnet, addressTestnet, message, bitcoin.networks.testnet);
const signatureRegtest = Signer.sign(privateKeyTestnet, addressRegtest, message, bitcoin.networks.regtest);
const signatureTestnet = Signer.sign(privateKey, addressTestnet, message);
const signatureRegtest = Signer.sign(privateKey, addressRegtest, message);
// Sign with testnet key
const signatureTestnetKey = Signer.sign(privateKeyTestnet, address, message);
const signatureTestnetTestnetKey = Signer.sign(privateKeyTestnet, addressTestnet, message);
const signatureRegtestTestnetKey = Signer.sign(privateKeyTestnet, addressRegtest, message);

// Assert
expect(bitcoinMessage.verify(message, address, signature)).to.be.true;
expect(bitcoinMessage.verify(message, addressTestnet, signatureTestnet)).to.be.true;
expect(bitcoinMessage.verify(message, addressRegtest, signatureRegtest)).to.be.true;
expect(bitcoinMessage.verify(message, address, signatureTestnetKey)).to.be.true;
expect(bitcoinMessage.verify(message, addressTestnet, signatureTestnetTestnetKey)).to.be.true;
expect(bitcoinMessage.verify(message, addressRegtest, signatureRegtestTestnetKey)).to.be.true;
});

it('Can sign BIP-322 signature using nested segwit address', () => {
Expand All @@ -39,14 +46,22 @@ describe('Signer Test', () => {
const expectedSignature = 'AkgwRQIhAMd2wZSY3x0V9Kr/NClochoTXcgDaGl3OObOR17yx3QQAiBVWxqNSS+CKen7bmJTG6YfJjsggQ4Fa2RHKgBKrdQQ+gEhAxa5UDdQCHSQHfKQv14ybcYm1C9y6b12xAuukWzSnS+w';

// Act
// Sign with mainnet key
const signature = Signer.sign(privateKey, address, message);
const signatureTestnet = Signer.sign(privateKeyTestnet, addressTestnet, message, bitcoin.networks.testnet);
const signatureRegtest = Signer.sign(privateKeyTestnet, addressRegtest, message, bitcoin.networks.regtest);
const signatureTestnet = Signer.sign(privateKey, addressTestnet, message);
const signatureRegtest = Signer.sign(privateKey, addressRegtest, message);
// Sign with testnet key
const signatureTestnetKey = Signer.sign(privateKeyTestnet, address, message);
const signatureTestnetTestnetKey = Signer.sign(privateKeyTestnet, addressTestnet, message);
const signatureRegtestTestnetKey = Signer.sign(privateKeyTestnet, addressRegtest, message);

// Assert
expect(signature).to.equal(expectedSignature);
expect(signatureTestnet).to.equal(expectedSignature);
expect(signatureRegtest).to.equal(expectedSignature);
expect(signatureTestnetKey).to.equal(expectedSignature);
expect(signatureTestnetTestnetKey).to.equal(expectedSignature);
expect(signatureRegtestTestnetKey).to.equal(expectedSignature);
});

it('Can sign BIP-322 signature using native segwit address', () => {
Expand All @@ -61,14 +76,22 @@ describe('Signer Test', () => {
const expectedSignature = 'AkgwRQIhAOzyynlqt93lOKJr+wmmxIens//zPzl9tqIOua93wO6MAiBi5n5EyAcPScOjf1lAqIUIQtr3zKNeavYabHyR8eGhowEhAsfxIAMZZEKUPYWI4BruhAQjzFT8FSFSajuFwrDL1Yhy';

// Act
// Sign with mainnet key
const signature = Signer.sign(privateKey, address, message);
const signatureTestnet = Signer.sign(privateKeyTestnet, addressTestnet, message, bitcoin.networks.testnet);
const signatureRegtest = Signer.sign(privateKeyTestnet, addressRegtest, message, bitcoin.networks.regtest);
const signatureTestnet = Signer.sign(privateKey, addressTestnet, message);
const signatureRegtest = Signer.sign(privateKey, addressRegtest, message);
// Sign with testnet key
const signatureTestnetKey = Signer.sign(privateKeyTestnet, address, message);
const signatureTestnetTestnetKey = Signer.sign(privateKeyTestnet, addressTestnet, message);
const signatureRegtestTestnetKey = Signer.sign(privateKeyTestnet, addressRegtest, message);

// Assert
expect(signature).to.equal(expectedSignature);
expect(signatureTestnet).to.equal(expectedSignature);
expect(signatureRegtest).to.equal(expectedSignature);
expect(signatureTestnetKey).to.equal(expectedSignature);
expect(signatureTestnetTestnetKey).to.equal(expectedSignature);
expect(signatureRegtestTestnetKey).to.equal(expectedSignature);
});

it('Can sign BIP-322 using single-key-spend taproot address', () => {
Expand All @@ -83,14 +106,22 @@ describe('Signer Test', () => {
const expectedSignature = "AUHd69PrJQEv+oKTfZ8l+WROBHuy9HKrbFCJu7U1iK2iiEy1vMU5EfMtjc+VSHM7aU0SDbak5IUZRVno2P5mjSafAQ==";

// Act
// Sign with mainnet key
const signature = Signer.sign(privateKey, address, message);
const signatureTestnet = Signer.sign(privateKeyTestnet, addressTestnet, message, bitcoin.networks.testnet);
const signatureRegtest = Signer.sign(privateKeyTestnet, addressRegtest, message, bitcoin.networks.regtest);
const signatureTestnet = Signer.sign(privateKey, addressTestnet, message);
const signatureRegtest = Signer.sign(privateKey, addressRegtest, message);
// Sign with testnet key
const signatureTestnetKey = Signer.sign(privateKeyTestnet, address, message);
const signatureTestnetTestnetKey = Signer.sign(privateKeyTestnet, addressTestnet, message);
const signatureRegtestTestnetKey = Signer.sign(privateKeyTestnet, addressRegtest, message);

// Assert
expect(signature).to.equal(expectedSignature);
expect(signatureTestnet).to.equal(expectedSignature);
expect(signatureRegtest).to.equal(expectedSignature);
expect(signatureTestnetKey).to.equal(expectedSignature);
expect(signatureTestnetTestnetKey).to.equal(expectedSignature);
expect(signatureRegtestTestnetKey).to.equal(expectedSignature);
});

it('Throw when the provided private key cannot derive the given signing address', () => {
Expand Down

0 comments on commit d9af849

Please sign in to comment.