Please check the build logs for more information.
See Builds for ideas on how to fix a failed build, or Metadata for how to configure docs.rs builds.
If you believe this is docs.rs' fault, open an issue.
libbitcoinpqc-bindings
Language bindings (Rust, Python, Node.js, WASM) for the libbitcoinpqc C library. The library implements the three BIP-360 signature algorithms for the Bitcoin QuBit soft fork:
- secp256k1 Schnorr (BIP-340): Classical elliptic-curve signatures with x-only public keys.
- ML-DSA-44 (formerly CRYSTALS-Dilithium): A lattice-based scheme from the NIST PQC standardization.
- SLH-DSA-SHA2-128s (formerly SPHINCS+): A stateless hash-based scheme using SHA-256, aligned with Bitcoin's native hash primitive.
The two PQC algorithms are FIPS-certified, which should help with future native hardware support.
Bitcoin QuBit Integration
This library serves as the cryptographic foundation for the Bitcoin QuBit soft fork, which aims to make Bitcoin's signature verification quantum-resistant through the implementation of BIP-360. QuBit introduces new post-quantum secure transaction types that can protect Bitcoin from potential threats posed by quantum computers.
Features
- Clean, unified C API for all three signature algorithms
- Safe Rust bindings with memory safety and zero-copy operations
- NodeJS TypeScript bindings with full type safety
- Python bindings for easy integration
- WASM builds for browser and Node.js (
@jbride/bitcoinpqc-wasm) - User-provided entropy (bring your own randomness)
- Key generation, signing, and verification functions
- Minimal dependencies
Key Characteristics
| Algorithm | Public Key Size | Secret Key Size | Signature Size | Security Level |
|---|---|---|---|---|
| SECP256K1_SCHNORR | 32 bytes | 32 bytes | 64 bytes | Classical |
| ML-DSA-44 | 1,312 bytes | 2,560 bytes | 2,420 bytes | NIST Level 2 |
| SLH-DSA-SHA2-128s | 32 bytes | 64 bytes | 7,856 bytes | NIST Level 1 |
See REPORT.md for performance and size comparison to secp256k1.
Breaking Changes (Phase 2)
Phase 2 renames SLH-DSA bindings from SHAKE-128s to SHA2-128s. Update identifiers as follows:
| Old identifier | New identifier |
|---|---|
SLH_DSA_128S (Rust) |
SLH_DSA_SHA2_128S |
SLH_DSA_SHAKE_128S (Python/Node.js/WASM) |
SLH_DSA_SHA2_128S |
- Enum wire value
2is unchanged. - Key sizes (32/64/7856 bytes) are unchanged.
- Enum wire values:
SECP256K1_SCHNORR=0,ML_DSA_44=1,SLH_DSA_SHA2_128S=2. RemovedFN_DSA_512. - Re-keying required: keys and signatures from SHAKE-128s are cryptographically incompatible with SHA2-128s. Generate new key pairs after upgrading.
Security Notes
- This library does not provide its own random number generation. It is essential that the user provide entropy from a cryptographically secure source. See docs/user_provided_entropy.md.
- Random data is required for key generation, but not for signing. All signatures are deterministic, based on the message and secret key.
- The implementations are based on reference code from the NIST PQC standardization process and are not production-hardened.
- Care should be taken to securely manage secret keys in applications.
BIP-360 Compliance
This library implements the cryptographic primitives required by BIP-360, which defines the standard for post-quantum resistant signatures in Bitcoin. It supports all three recommended algorithms with the specified parameter sets.
License
This project is licensed under the MIT License - see the LICENSE file for details.
Dependencies
The C library is included as a git submodule from libbitcoinpqc at libbitcoinpqc/, tracking branch 27-slh-dsa-sha-2-128s (see .gitmodules). To bump the pinned commit after upstream changes on that branch (or once merged to main):
&& && &&
&&
Build outputs belong in the parent build/ directory (make c-lib, make c-lib-test). Do not run cmake -B build or bare ctest inside libbitcoinpqc/ — that leaves libbitcoinpqc/build/ and libbitcoinpqc/Testing/ behind and makes git submodule status report untracked content. Run make clean (or make clean-submodule) to remove those artifacts.
Building
Prerequisites
- CMake 3.10 or higher
- C99 compiler
- Rust 1.50 or higher
Building
# Clone the repository (with submodules)
# Or, if already cloned without submodules:
# git submodule update --init --recursive
# Build the Rust bindings (automatically builds the C library from the submodule)
# Or use the Makefile
Fuzz Testing
This library includes fuzz testing targets using cargo-fuzz.
Prerequisites
# Install cargo-fuzz
Available Fuzz Targets
- keypair_generation - Tests key pair generation with different algorithms
- sign_verify - Tests signature creation and verification
- cross_algorithm - Tests verification with mismatched keys and signatures from different algorithms
Running Fuzz Tests
# Run a specific fuzz target
# Run a fuzz target for a specific amount of time (in seconds)
# Run a fuzz target with a specific number of iterations
See fuzz/README.md for more details on fuzz testing.
C API Usage
// Generate random data (from a secure source in production)
uint8_t random_data;
// Fill random_data with entropy...
// Generate a key pair
bitcoin_pqc_keypair_t keypair;
;
// Sign a message
const uint8_t message = "Message to sign";
bitcoin_pqc_signature_t signature;
;
// Verify the signature
bitcoin_pqc_error_t result = ;
// Clean up resources
;
;
Rust API Usage
Rust docs can be found on docs.rs.
use ;
use ;
// Generate random data for key generation
let mut random_data = vec!;
OsRng.fill_bytes;
// Generate a key pair
let keypair = generate_keypair.unwrap;
// Create a message to sign
let message = b"Message to sign";
// Sign the message deterministically
let signature = sign.unwrap;
// Verify the signature
verify.unwrap;
Python API Usage
Python bindings for all three algorithms.
Installation
# Install the Python package
Prerequisites
- Python 3.7 or higher
- The libbitcoinpqc C library must be built and installed
Example Usage
# Generate random data for key generation
=
# Generate a key pair
= # CRYSTALS-Dilithium
=
# Create a message to sign
= b
# Sign the message
=
# Verify the signature
=
# Should print True
# Verification with incorrect message will fail
= b
=
# Should print False
Python API Reference
The Python API mirrors the C API closely, with some Pythonic improvements:
-
Algorithm - Enum class for algorithm selection
SECP256K1_SCHNORRML_DSA_44(CRYSTALS-Dilithium)SLH_DSA_SHA2_128S(SPHINCS+)
-
KeyPair - Class to hold a public/secret key pair
algorithm- The algorithm usedpublic_key- The public key as bytessecret_key- The secret key as bytes
-
Signature - Class to hold a signature
algorithm- The algorithm usedsignature- The signature as bytes
-
Functions
public_key_size(algorithm)- Get the public key size for an algorithmsecret_key_size(algorithm)- Get the secret key size for an algorithmsignature_size(algorithm)- Get the signature size for an algorithmkeygen(algorithm, random_data)- Generate a key pair (32 bytes forSECP256K1_SCHNORR, 128 for PQC)sign(algorithm, secret_key, message)- Sign a messageverify(algorithm, public_key, message, signature)- Verify a signature
NodeJS TypeScript API Usage
NodeJS TypeScript bindings for all three algorithms in JavaScript/TypeScript projects.
Installation
# Install the Node.js package
Prerequisites
- Node.js 16 or higher
- The libbitcoinpqc C library must be built and installed
Example Usage
import { Algorithm, generateKeyPair, sign, verify } from 'bitcoinpqc';
import crypto from 'crypto';
// Generate random data for key generation
const randomData = crypto.randomBytes(128);
// Generate a key pair using ML-DSA-44 (CRYSTALS-Dilithium)
const keypair = generateKeyPair(Algorithm.ML_DSA_44, randomData);
// Create a message to sign
const message = Buffer.from('Message to sign');
// Sign the message deterministically
const signature = sign(keypair.secretKey, message);
// Verify the signature
verify(keypair.publicKey, message, signature);
// If verification fails, it will throw a PqcError
// You can also verify using the raw signature bytes
verify(keypair.publicKey, message, signature.bytes);
NodeJS TypeScript API Reference
The TypeScript API provides a clean, modern interface:
-
Algorithm - Enum for algorithm selection
SECP256K1_SCHNORRML_DSA_44(CRYSTALS-Dilithium)SLH_DSA_SHA2_128S(SPHINCS+)
-
Classes
PublicKey- Public key wrapperSecretKey- Secret key wrapper with secure handlingKeyPair- Container for public/secret key pairsSignature- Signature wrapper
-
Functions
publicKeySize(algorithm)- Get the public key size for an algorithmsecretKeySize(algorithm)- Get the secret key size for an algorithmsignatureSize(algorithm)- Get the signature size for an algorithmgenerateKeyPair(algorithm, randomData)- Generate a key pair (32 bytes of entropy forSECP256K1_SCHNORR, 128 bytes for PQC)sign(secretKey, message)- Sign a messageverify(publicKey, message, signature)- Verify a signature
For more details, see the NodeJS TypeScript bindings README.
WASM API Usage
Browser and Node.js WASM builds are published as @jbride/bitcoinpqc-wasm. The Emscripten high-level API covers all three algorithms with the same entropy rules as the native bindings.
See wasm/README.md for the full API reference and browser testing notes.
Acknowledgments
- The original NIST PQC competition teams for their reference implementations
- The NIST PQC standardization process for advancing post-quantum cryptography
- The Bitcoin QuBit soft fork contributors and BIP-360 contributors