TypeScript wrappers for Bitcoin-related cryptographic operations, built on audited libraries.
Security Note: This package wraps @noble/curves, @noble/hashes, and @scure/base - all of which have undergone security audits.
# npm
npm install @vbyte/crypto
# yarn
yarn add @vbyte/crypto
# pnpm
pnpm add @vbyte/crypto<script src="https://unpkg.com/@vbyte/crypto/dist/script.js"></script>import { get_pubkey, sign_ecdsa, verify_ecdsa, sign_bip340, verify_bip340 } from '@vbyte/crypto/ecc'
// Generate public key from private key
const privateKey = '0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef'
const ecdsaPubkey = get_pubkey(privateKey, 'ecdsa') // 33-byte compressed
const bip340Pubkey = get_pubkey(privateKey, 'bip340') // 32-byte x-only
// ECDSA signatures (message must be hex)
const messageHash = '0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef'
const ecdsaSig = sign_ecdsa(privateKey, messageHash)
const isValid = verify_ecdsa(ecdsaSig, messageHash, ecdsaPubkey)
// BIP340 Schnorr signatures
const schnorrSig = sign_bip340(privateKey, messageHash)
const isValidSchnorr = verify_bip340(schnorrSig, messageHash, bip340Pubkey)Note: All string inputs must be valid hexadecimal. Use
Buff.str('text').hexfrom@vbyte/buffto convert UTF-8 text to hex.
import { sha256, hash256, hash160, hmac256, pkdf256 } from '@vbyte/crypto/hash'
import { Buff } from '@vbyte/buff'
// SHA-256 (input as hex string or Uint8Array)
const dataHex = '48656c6c6f' // 'Hello' in hex
const hash = sha256(dataHex)
// Double SHA-256 (Bitcoin-style)
const doubleHash = hash256(dataHex)
// RIPEMD160(SHA256(x)) for Bitcoin addresses
const addressHash = hash160(dataHex)
// HMAC-SHA256
const keyHex = '736563726574' // 'secret' in hex
const mac = hmac256(keyHex, dataHex)
// PBKDF2-SHA256
const passwordHex = Buff.str('password').hex
const saltHex = Buff.str('salt').hex
const derivedKey = pkdf256(passwordHex, saltHex, { c: 100000, dk_len: 32 })import { B58chk, Bech32, Bech32m, Base64 } from '@vbyte/crypto/encode'
// Base58Check (Bitcoin addresses)
const encoded = B58chk.encode(data)
const decoded = B58chk.decode(encoded)
// Bech32 (SegWit v0 addresses)
const words = Bech32.to_words(data)
const bech32Addr = Bech32.encode('bc', words)
const { prefix, words: decodedWords } = Bech32.decode(bech32Addr)
// Bech32m (SegWit v1+ / Taproot addresses)
const taprootAddr = Bech32m.encode('bc', [1, ...words])
// Base64
const b64 = Base64.encode(data)
const original = Base64.decode(b64)All functions throw standard Error on invalid input:
import { verify_seckey } from '@vbyte/crypto/ecc'
try {
verify_seckey('invalid-key')
} catch (err) {
console.error(err.message) // "invalid hex string: invalid-key"
}import { B58chk } from '@vbyte/crypto/encode'
try {
B58chk.decode('invalid!@#')
} catch (err) {
console.error(err.message) // "invalid base58 string"
}| Function | Description |
|---|---|
get_seckey(secret, even_y?) |
Derive secret key, optionally with even Y coordinate |
get_pubkey(seckey, format) |
Generate public key ('ecdsa' or 'bip340' format) |
tweak_seckey(seckey, tweak, even_y?) |
Tweak a secret key |
tweak_pubkey(pubkey, tweak, format, even_y?) |
Tweak a public key |
verify_seckey(seckey) |
Validate a secret key |
verify_pubkey(pubkey, format) |
Validate a public key |
sign_ecdsa(seckey, message) |
Create ECDSA signature |
sign_bip340(seckey, message) |
Create BIP340 Schnorr signature |
verify_ecdsa(sig, message, pubkey) |
Verify ECDSA signature |
verify_bip340(sig, message, pubkey) |
Verify BIP340 signature |
serialize_bytes(bytes) |
Serialize hex string or Uint8Array to Buff |
serialize_pubkey(pubkey, format) |
Normalize pubkey to specified format |
get_pubkey_format(pubkey) |
Detect pubkey format from length |
| Function | Description |
|---|---|
sha256(...input) |
SHA-256 hash |
hash256(...input) |
Double SHA-256 |
hash160(...input) |
RIPEMD160(SHA256(x)) |
hashtag(tag) |
Create tagged hash prefix |
hash340(tag, ...input) |
BIP340-style tagged hash |
hmac256(key, ...input) |
HMAC-SHA256 |
hmac512(key, ...input) |
HMAC-SHA512 |
pkdf256(secret, salt, options?) |
PBKDF2-SHA256 |
pkdf512(secret, salt, options?) |
PBKDF2-SHA512 |
| Namespace | Functions |
|---|---|
B58chk |
encode(data), decode(str) |
Base64 |
encode(data), decode(str) |
B64url |
encode(data), decode(str) |
Bech32 |
encode(prefix, words, limit?), decode(str, limit?), to_words(data), to_bytes(words) |
Bech32m |
encode(prefix, words, limit?), decode(str, limit?), to_words(data), to_bytes(words) |
// Full package (includes all modules)
import { sha256, get_pubkey, B58chk } from '@vbyte/crypto'
// Tree-shaking friendly imports
import { sha256, hash256 } from '@vbyte/crypto/hash'
import { get_pubkey, sign_ecdsa } from '@vbyte/crypto/ecc'
import { B58chk, Bech32 } from '@vbyte/crypto/encode'| File | Format | Use Case |
|---|---|---|
dist/index.js |
ESM | Modern bundlers, Node.js |
dist/main.cjs |
CommonJS | Legacy Node.js |
dist/script.js |
IIFE | Browser script tag |
<script src="https://unpkg.com/@vbyte/crypto/dist/script.js"></script>
<script>
const { Hash, Buff } = window.vbyteCrypto
// Convert text to hex, then hash
const dataHex = Buff.str('hello world').hex
const hash = Hash.sha256(dataHex)
console.log(hash.hex)
</script>All cryptographic operations are delegated to audited libraries:
| Package | Purpose | Audit |
|---|---|---|
| @noble/curves | secp256k1, ECDSA, Schnorr | Cure53 (2022) |
| @noble/hashes | SHA256, RIPEMD160, HMAC, PBKDF2 | Cure53 (2022) |
| @scure/base | Base58, Bech32, Base64 | Cure53 (2022) |
| @vbyte/buff | Buffer utilities | - |
See CONTRIBUTING.md for guidelines.
Report vulnerabilities via GitHub Security Advisories. See SECURITY.md.