Low-level cryptographic operations for digital signatures, hashing, and key management.
// ES6 imports
import { Hash, ECDSA, Sig, KeyPair, Point, Random } from 'bsv'
// CommonJS imports
const { Hash, ECDSA, Sig, KeyPair, Point, Random } = require('bsv')Comprehensive cryptographic hash functions used throughout Bitcoin protocols.
class Hash {
// SHA family hash functions
static sha1(buf: Buffer): Buffer
static sha256(buf: Buffer): Buffer
static sha256Sha256(buf: Buffer): Buffer // Double SHA-256 (Bitcoin standard)
static sha512(buf: Buffer): Buffer
// RIPEMD hash functions
static ripemd160(buf: Buffer): Buffer
static sha256Ripemd160(buf: Buffer): Buffer // SHA-256 + RIPEMD-160 (address hash)
// HMAC functions
static hmac(
hashFStr: string, // Hash function name ('sha1', 'sha256', 'sha512')
data: Buffer, // Data to authenticate
key: Buffer // HMAC key
): Buffer
static sha1Hmac(data: Buffer, key: Buffer): Buffer
static sha256Hmac(data: Buffer, key: Buffer): Buffer
static sha512Hmac(data: Buffer, key: Buffer): Buffer
// Async variants for non-blocking computation
static asyncSha1(buf: Buffer): Promise<Buffer>
static asyncSha256(buf: Buffer): Promise<Buffer>
static asyncSha256Sha256(buf: Buffer): Promise<Buffer>
static asyncSha512(buf: Buffer): Promise<Buffer>
static asyncRipemd160(buf: Buffer): Promise<Buffer>
static asyncSha256Ripemd160(buf: Buffer): Promise<Buffer>
// Block size constants
static sha1.blockSize: number // 512 bits
static sha256.blockSize: number // 512 bits
static sha512.blockSize: number // 1024 bits
}// Standard hash functions
const data = Buffer.from('Hello, BSV!', 'utf8')
// SHA-256 (most common in Bitcoin)
const sha256Hash = Hash.sha256(data)
// Double SHA-256 (Bitcoin block and transaction hashes)
const doubleHash = Hash.sha256Sha256(data)
// Bitcoin address hash (SHA-256 + RIPEMD-160)
const pubKeyBuf = pubKey.toBuffer()
const addressHash = Hash.sha256Ripemd160(pubKeyBuf)
// RIPEMD-160 (used in Bitcoin addresses)
const ripemd = Hash.ripemd160(data)
// HMAC authentication
const key = Buffer.from('secret-key', 'utf8')
const hmac = Hash.sha256Hmac(data, key)
// Async operations for large data
const hash = await Hash.asyncSha256(largeBuffer)
const doubleHash = await Hash.asyncSha256Sha256(largeBuffer)
// Block size information
console.log('SHA-256 block size:', Hash.sha256.blockSize) // 512Digital signature creation and verification using secp256k1 elliptic curve.
class Ecdsa {
constructor(
sig?: Sig, // Signature object
keyPair?: KeyPair, // Key pair for signing/verification
hashBuf?: Buffer, // Hash to sign/verify
k?: Bn, // Nonce value (should be random)
endian?: string, // Byte order ('big' or 'little')
verified?: boolean // Verification result cache
)
// Core properties
sig: Sig // Signature
keyPair: KeyPair // Key pair
hashBuf: Buffer // Message hash
k: Bn // Nonce
endian: string // Byte order
verified: boolean // Verification result
// Signing operations
sign(): Ecdsa // Create signature
randomK(): Ecdsa // Generate random nonce
deterministicK(badrs?: Bn[]): Ecdsa // Generate deterministic nonce (RFC 6979)
// Verification operations
verify(enforceLowS?: boolean): Ecdsa // Verify signature
// Public key recovery
calcrecovery(): Ecdsa // Calculate recovery parameter
sig2PubKey(): PubKey // Recover public key from signature
// Static methods for direct operations
static sign(
hashBuf: Buffer,
keyPair: KeyPair,
endian?: string
): Sig
static verify(
hashBuf: Buffer,
sig: Sig,
pubKey: PubKey,
endian?: string,
enforceLowS?: boolean
): boolean
static calcrecovery(
sig: Sig,
pubKey: PubKey,
hashBuf: Buffer
): number
// Async variants
asyncSign(): Promise<Ecdsa>
asyncVerify(enforceLowS?: boolean): Promise<Ecdsa>
asyncCalcrecovery(): Promise<Ecdsa>
asyncSig2PubKey(): Promise<PubKey>
}// Create ECDSA signature
const keyPair = KeyPair.fromPrivKey(privKey)
const hashBuf = Hash.sha256(messageBuf)
// Method 1: Using static methods (recommended)
const sig = Ecdsa.sign(hashBuf, keyPair)
const isValid = Ecdsa.verify(hashBuf, sig, pubKey)
// Method 2: Using instance methods
const ecdsa = new Ecdsa()
ecdsa.hashBuf = hashBuf
ecdsa.keyPair = keyPair
ecdsa.randomK() // Generate random nonce
ecdsa.sign()
const signature = ecdsa.sig
// Verify signature
const ecdsa2 = new Ecdsa()
ecdsa2.hashBuf = hashBuf
ecdsa2.sig = signature
ecdsa2.keyPair = KeyPair.fromPubKey(pubKey)
ecdsa2.verify()
console.log('Valid:', ecdsa2.verified)
// Deterministic nonce generation (RFC 6979)
ecdsa.deterministicK()
ecdsa.sign()
// Public key recovery
const recoveredPubKey = ecdsa.sig2PubKey()
// Recovery parameter calculation
const recoveryParam = Ecdsa.calcrecovery(sig, pubKey, hashBuf)
// Async operations
const sig = await ecdsa.asyncSign()
const isValid = await ecdsa.asyncVerify(true) // Enforce low-SDigital signature representation with multiple encoding formats.
class Sig {
constructor(
r?: Bn, // R component
s?: Bn, // S component
nHashType?: number, // Hash type for transactions
recovery?: number, // Public key recovery value
compressed?: boolean // Whether pubkey is compressed
)
// Core properties
r: Bn // R component
s: Bn // S component
nHashType: number // Hash type
recovery: number // Recovery parameter
compressed: boolean // Pubkey compression flag
// Creation methods
static fromDer(buf: Buffer, strict?: boolean): Sig
static fromTxFormat(buf: Buffer): Sig // DER + nHashType
static fromCompact(buf: Buffer): Sig // Recovery format
static fromProperties(obj: object): Sig
// Serialization methods
toDer(): Buffer // DER encoding
toTxFormat(): Buffer // Transaction format
toCompact(): Buffer // Compact format with recovery
// Validation
hasLowS(): boolean // Check BIP 62 low-S constraint
static IsTxDer(buf: Buffer): boolean // Check transaction DER format
// Hash type constants
static SIGHASH_ALL: number // Sign all inputs and outputs
static SIGHASH_NONE: number // Sign all inputs, no outputs
static SIGHASH_SINGLE: number // Sign all inputs, one output
static SIGHASH_ANYONECANPAY: number // Modifier: sign only this input
static SIGHASH_FORKID: number // Bitcoin SV fork ID
}// Create signature from components
const r = Bn.fromHex('...')
const s = Bn.fromHex('...')
const sig = new Sig(r, s, Sig.SIGHASH_ALL)
// Parse DER format signature
const derBuf = Buffer.from('30440220...', 'hex')
const sig = Sig.fromDer(derBuf)
// Transaction format (DER + hash type)
const txSig = Sig.fromTxFormat(txSigBuf)
console.log('Hash type:', txSig.nHashType)
// Compact format with recovery
const compactSig = Sig.fromCompact(compactBuf)
console.log('Recovery param:', compactSig.recovery)
// Serialization
const derBuf = sig.toDer()
const txFormatBuf = sig.toTxFormat()
const compactBuf = sig.toCompact()
// BIP 62 low-S validation
const hasLowS = sig.hasLowS()
if (!hasLowS) {
// Convert to low-S if needed
sig.s = sig.s.neg().mod(Point.getN())
}
// Hash type usage
const allSig = new Sig(r, s, Sig.SIGHASH_ALL)
const noneSig = new Sig(r, s, Sig.SIGHASH_NONE)
const singleSig = new Sig(r, s, Sig.SIGHASH_SINGLE)
const anyoneCanPay = new Sig(r, s, Sig.SIGHASH_ALL | Sig.SIGHASH_ANYONECANPAY)
// Bitcoin SV signatures include FORKID
const bsvSig = new Sig(r, s, Sig.SIGHASH_ALL | Sig.SIGHASH_FORKID)Public/private key pair management for cryptographic operations.
class KeyPair {
constructor(
privKey?: PrivKey, // Private key
pubKey?: PubKey // Public key
)
// Core properties
privKey: PrivKey // Private key component
pubKey: PubKey // Public key component
// Creation methods
static fromRandom(): KeyPair
static fromPrivKey(privKey: PrivKey): KeyPair
static fromString(str: string): KeyPair
static fromJSON(json: object): KeyPair
// Serialization methods
toString(): string
toJSON(): object
// Network variants
static Mainnet: typeof KeyPair
static Testnet: typeof KeyPair
}// Generate random key pair
const keyPair = KeyPair.fromRandom()
console.log('Private key WIF:', keyPair.privKey.toWif())
console.log('Public key hex:', keyPair.pubKey.toHex())
// Create from existing private key
const privKey = PrivKey.fromWif('L1aW4aubDFB7yfras2S1mN3bqg9nwySY8nkoLmJebSLD5BWv3ENZ')
const keyPair = KeyPair.fromPrivKey(privKey)
// Network-specific key pairs
const mainnetPair = KeyPair.Mainnet.fromRandom()
const testnetPair = KeyPair.Testnet.fromRandom()
// Use for signing
const message = Buffer.from('Hello, BSV!', 'utf8')
const hashBuf = Hash.sha256(message)
const sig = Ecdsa.sign(hashBuf, keyPair)
// Serialization
const keyPairStr = keyPair.toString()
const keyPair2 = KeyPair.fromString(keyPairStr)Elliptic curve point operations for secp256k1 curve.
class Point {
constructor(
x?: Bn, // X coordinate
y?: Bn // Y coordinate
)
// Core properties
x: Bn // X coordinate
y: Bn // Y coordinate
// Creation methods
static fromX(odd: boolean, x: Bn): Point
static getG(): Point // Get generator point
static getN(): Bn // Get curve order
// Coordinate access
getX(): Bn // Get X coordinate
getY(): Bn // Get Y coordinate
// Point operations
add(p: Point): Point // Point addition
mul(d: Bn): Point // Scalar multiplication
// Validation
validate(): Point // Validate point is on curve
isValid(): boolean
}// Get secp256k1 generator point
const G = Point.getG()
const n = Point.getN() // Curve order
// Create point from coordinates
const x = Bn.fromHex('...')
const y = Bn.fromHex('...')
const point = new Point(x, y)
// Create from X coordinate (compressed format)
const point = Point.fromX(true, x) // odd=true
// Point operations
const privKeyBn = Bn.fromRandom()
const pubKeyPoint = G.mul(privKeyBn) // Public key = privKey * G
// Point addition
const sum = point1.add(point2)
// Validation
const isValid = point.isValid()
point.validate() // Throws if invalid
// Use with PubKey
const pubKey = new PubKey(pubKeyPoint, true) // compressed=trueCryptographically secure random number generation for keys and nonces.
class Random {
// Generate cryptographically secure random bytes
static getRandomBuffer(size: number): Buffer
}// Generate random bytes for keys
const randomBytes = Random.getRandomBuffer(32) // 256 bits
const privKey = PrivKey.fromBn(Bn.fromBuffer(randomBytes))
// Generate random nonces
const nonce = Random.getRandomBuffer(32)
const k = Bn.fromBuffer(nonce)
// Random initialization vectors
const iv = Random.getRandomBuffer(16) // 128 bits for AES
// Random salts
const salt = Random.getRandomBuffer(16)// Complete message signing workflow
const message = 'Hello, BSV blockchain!'
const messageBuf = Buffer.from(message, 'utf8')
// Create message hash (Bitcoin message signing uses double SHA-256)
const hashBuf = Hash.sha256Sha256(messageBuf)
// Sign with private key
const keyPair = KeyPair.fromPrivKey(privKey)
const sig = Ecdsa.sign(hashBuf, keyPair)
// Verify signature
const pubKey = PubKey.fromPrivKey(privKey)
const isValid = Ecdsa.verify(hashBuf, sig, pubKey, 'big', true)
console.log('Signature valid:', isValid)
// Recover public key from signature
const ecdsa = new Ecdsa(sig, null, hashBuf)
const recoveredPubKey = ecdsa.sig2PubKey()// Create deterministic signature (same message + key = same signature)
const ecdsa = new Ecdsa()
ecdsa.hashBuf = hashBuf
ecdsa.keyPair = keyPair
ecdsa.deterministicK() // Generate deterministic nonce
ecdsa.sign()
const sig1 = ecdsa.sig
// Signing again will produce identical signature
ecdsa.deterministicK()
ecdsa.sign()
const sig2 = ecdsa.sig
// sig1 equals sig2// HMAC-based key derivation
const password = Buffer.from('password', 'utf8')
const salt = Random.getRandomBuffer(16)
const iterations = 10000
// PBKDF2 (available via deps)
const derivedKey = bsv.deps.pbkdf2(password, salt, iterations, 32, 'sha256')
// Custom HMAC operations
const key = derivedKey.slice(0, 16)
const data = Buffer.from('authenticate this', 'utf8')
const hmac = Hash.sha256Hmac(data, key)Cryptographic operations include comprehensive validation:
// Hash validation
try {
const hash = Hash.sha256(null) // Will throw
} catch (error) {
console.error('Hash error:', error.message)
}
// Signature validation
try {
const sig = Sig.fromDer(invalidBuffer)
} catch (error) {
console.error('Invalid signature format:', error.message)
}
// Point validation
try {
const point = new Point(invalidX, invalidY)
point.validate() // Will throw if not on curve
} catch (error) {
console.error('Invalid curve point:', error.message)
}
// ECDSA verification
try {
const ecdsa = new Ecdsa()
ecdsa.verify() // May throw on invalid signature
} catch (error) {
console.error('Signature verification failed:', error.message)
}