How digital signatures work in Bitcoin and their implementation in the BSV TypeScript SDK.
Digital signatures prove ownership and authorize Bitcoin transactions:
import { PrivateKey, Transaction } from '@bsv/sdk'
// Create a signature
const privateKey = PrivateKey.fromRandom()
const message = 'transaction data'
const signature = privateKey.sign(message)
// Verify the signature
const publicKey = privateKey.toPublicKey()
const isValid = publicKey.verify(message, signature)
Bitcoin uses ECDSA (Elliptic Curve Digital Signature Algorithm):
SIGHASH flags determine what parts of a transaction are signed:
Signs all inputs and outputs:
const signature = privateKey.sign(txHash, 'all')
Signs all inputs but no outputs:
const signature = privateKey.sign(txHash, 'none')
Signs all inputs and one corresponding output:
const signature = privateKey.sign(txHash, 'single')
Can be combined with other flags to sign only one input:
const signature = privateKey.sign(txHash, 'all|anyonecanpay')
The SDK handles transaction signing automatically:
// Manual signing (low-level)
const tx = new Transaction()
const signature = tx.sign(privateKey, inputIndex, sighashType)
// Wallet signing (recommended)
const wallet = new WalletClient()
const action = await wallet.createAction({
outputs: [/* outputs */]
})
// Wallet handles signing internally
Verify signatures to ensure transaction validity:
// Verify a specific signature
const isValid = publicKey.verify(messageHash, signature)
// Verify entire transaction
const txValid = await transaction.verify(chainTracker)
Signatures are encoded in DER format:
// Get DER-encoded signature
const derSignature = signature.toDER()
// Parse DER signature
const sig = Signature.fromDER(derBytes)
// Get r and s components
const r = signature.r
const s = signature.s
// Sign multiple inputs in a transaction
for (let i = 0; i < transaction.inputs.length; i++) {
const signature = privateKey.sign(transaction.getSignatureHash(i))
transaction.inputs[i].unlockingScript = createUnlockingScript(signature)
}
// Different signatures for different conditions
const signature1 = privateKey1.sign(txHash, 'all')
const signature2 = privateKey2.sign(txHash, 'single')
Common signature issues:
try {
const signature = privateKey.sign(message)
} catch (error) {
console.error('Signing failed:', error.message)
}
Most applications use wallets for signing:
// Wallet handles signature creation
const wallet = new WalletClient()
const result = await wallet.createAction({
description: 'Payment transaction',
outputs: [/* outputs */]
})
// Signatures created automatically