CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-bsv

JavaScript library for Bitcoin SV (BSV) blockchain development with cryptographic primitives, transaction handling, and protocol implementations

Pending

Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

Overview
Eval results
Files

cryptography.mddocs/

Cryptography

Low-level cryptographic operations for digital signatures, hashing, and key management.

Imports

// ES6 imports
import { Hash, ECDSA, Sig, KeyPair, Point, Random } from 'bsv'

// CommonJS imports  
const { Hash, ECDSA, Sig, KeyPair, Point, Random } = require('bsv')

Hash Functions

Comprehensive cryptographic hash functions used throughout Bitcoin protocols.

Class Definition

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
}

Usage Examples

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

ECDSA (Elliptic Curve Digital Signature Algorithm)

Digital signature creation and verification using secp256k1 elliptic curve.

Class Definition

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

Usage Examples

// 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-S

Signature (Sig)

Digital signature representation with multiple encoding formats.

Class Definition

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
}

Usage Examples

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

KeyPair

Public/private key pair management for cryptographic operations.

Class Definition

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
}

Usage Examples

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

Point (Elliptic Curve Points)

Elliptic curve point operations for secp256k1 curve.

Class Definition

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
}

Usage Examples

// 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=true

Random Number Generation

Cryptographically secure random number generation for keys and nonces.

Class Definition

class Random {
  // Generate cryptographically secure random bytes
  static getRandomBuffer(size: number): Buffer
}

Usage Examples

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

Advanced Cryptographic Operations

Message Signing and Verification

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

Deterministic Signatures (RFC 6979)

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

Low-Level Hash Operations

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

Error Handling

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

Install with Tessl CLI

npx tessl i tessl/npm-bsv

docs

core-bitcoin.md

cryptography.md

encryption.md

hd-wallets.md

index.md

transaction-building.md

utilities.md

tile.json