ts-sdk

Digital Signatures

How digital signatures work in Bitcoin and their implementation in the BSV TypeScript SDK.

What are Digital Signatures?

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 Signatures

Bitcoin uses ECDSA (Elliptic Curve Digital Signature Algorithm):

SIGHASH Types

SIGHASH flags determine what parts of a transaction are signed:

SIGHASH_ALL (Default)

Signs all inputs and outputs:

const signature = privateKey.sign(txHash, 'all')

SIGHASH_NONE

Signs all inputs but no outputs:

const signature = privateKey.sign(txHash, 'none')

SIGHASH_SINGLE

Signs all inputs and one corresponding output:

const signature = privateKey.sign(txHash, 'single')

SIGHASH_ANYONECANPAY

Can be combined with other flags to sign only one input:

const signature = privateKey.sign(txHash, 'all|anyonecanpay')

Transaction Signing

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

Signature Verification

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)

DER Encoding

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

Security Considerations

Nonce Security

Signature Malleability

Hash Types

Common Patterns

Multi-Input Signing

// 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)
}

Conditional Signatures

// Different signatures for different conditions
const signature1 = privateKey1.sign(txHash, 'all')
const signature2 = privateKey2.sign(txHash, 'single')

Error Handling

Common signature issues:

try {
  const signature = privateKey.sign(message)
} catch (error) {
  console.error('Signing failed:', error.message)
}

Best Practices

Wallet Integration

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

Next Steps