Blockchain Cryptography
Purpose
Guide the selection, implementation, and optimization of cryptographic primitives specific to blockchain systems. This skill enforces correct curve selection, signature scheme choice, and key management practices across all major blockchain protocols.
Agent Protocol
Trigger
"blockchain cryptography", "elliptic curve", "secp256k1", "BN254", "BLS", "Ed25519", "hash function blockchain", "Keccak-256", "SHA-256 blockchain", "Poseidon hash", "Merkle tree", "Merkle Patricia Trie", "Sparse Merkle Tree", "Verkle Trie", "ECDSA", "Schnorr signature", "BLS signature", "threshold signature", "FROST", "multi-sig", "aggregate signature", "zero-knowledge", "zk-SNARK", "zk-STARK", "Bulletproof", "circom", "Halo2", "BIP-32", "BIP-39", "BIP-44", "BIP-340", "PSBT", "BIP-174", "HD wallet", "key derivation", "cryptographic primitive", "signature scheme", "pairing-based cryptography", "post-quantum", "ecrecover", "EIP-712", "EIP-191", "RFC 6979", "KAT", "known-answer test", "nonce reuse", "signature malleability", "MuSig2", "threshold signing", "DKLs", "CGGMP", "aggregate signature", "hash-to-curve", "ICP", "Internet Computer"
Input Context
- Cryptographic operation (signing, verification, hashing, proof generation)
- Blockchain platform (Ethereum/Bitcoin/Solana/Cosmos)
- Security level requirement (128-bit / 192-bit / 256-bit)
- Performance constraints (verification throughput, gas budget)
- Key management model (single key, HD wallet, multi-sig, threshold)
- Threat model (passive/active, quantum-resistant needed?)
Output Artifact
Cryptographic architecture specification including:
- Selected primitives with curve/parameter justifications
- Implementation approach with library recommendations
- Security analysis with known attack vectors and mitigations
- Performance benchmarks and optimization strategies
Response Format
- Cryptographic primitive: curve/hash/scheme + security level + performance characteristics
- Blockchain usage: where and how this primitive is used in real blockchain networks
- Implementation details: algorithm specifics, edge cases, optimization techniques
- Security considerations: known attacks, parameter choices, implementation pitfalls
Completion Criteria
- Cryptographic primitive selection includes security level justification with NIST/BSI references
- Implementation plan specifies library, language, and optimization targets for on-chain or off-chain use
- Security analysis identifies known attack vectors (rogue key, small subgroup, timing side-channel)
- Performance benchmarks include verification latency and signature size comparison
- Key management design covers derivation path, backup, and recovery for the specific scheme
Max Response Length
4000 tokens
Workflow
Phase 1: Primitive Selection
- Identify required cryptographic operations (signing, hashing, commitment, proof generation)
- Select elliptic curve based on blockchain platform and security requirements
- Choose signature scheme (ECDSA for EVM, EdDSA for Solana/Near, BLS for aggregation)
- Select hash functions (Keccak-256 for EVM, SHA-256 for Bitcoin, BLAKE2 for Zcash)
- Determine if pairing-based crypto is needed (BLS aggregation, zk-SNARK verification)
Phase 2: Security Parameter Validation
- Verify security level meets minimum requirements (128-bit for standard, 192-bit for high security)
- Validate subgroup membership for all curve operations
- Confirm constant-time implementation for secret-dependent operations
- Review against known attacks (invalid curve, small subgroup, timing, fault injection)
- Check compliance with applicable standards (FIPS 186-5, BIP, NIST PQC)
Phase 3: Implementation
- Select library: libsecp256k1 (ECDSA), blst (BLS), ed25519-dalek (EdDSA), circom (ZK)
- Implement key generation with proper entropy source and domain separation
- Implement signing with deterministic nonce generation (RFC 6979 for ECDSA)
- Implement verification with all validation checks (curve, subgroup, signature bounds)
- Implement key management with BIP-32/39/44 derivation path standard
Phase 4: Integration and Testing
- Integrate with the target blockchain protocol or smart contract
- Test with known-answer tests (KATs) from standards documents
- Implement fuzz testing for edge cases (zero scalars, identity, large nonces)
- Cross-verify with independent implementations
- Benchmark verification throughput and gas costs
Architecture / Decision Trees
Curve Selection
| Curve |
Field Size |
Security Level |
Blockchain Usage |
Key Type |
| secp256k1 |
256-bit |
~128-bit |
Bitcoin, Ethereum (EOA), EVM chains |
ECDSA |
| Ed25519 |
255-bit |
~128-bit |
Solana, Near, Cardano |
EdDSA |
| BLS12-381 |
381-bit |
~128-bit |
Ethereum 2.0, Chia, Filecoin |
BLS |
| BN254 |
254-bit |
~100-bit |
EVM zk precompile, Zcash sprout |
Pairing |
| P-256 (secp256r1) |
256-bit |
~128-bit |
WebAuthn, Apple/Google passes |
ECDSA |
| Curve25519 |
255-bit |
~128-bit |
X25519 key exchange, Signal protocol |
Diffie-Hellman |
| secq256k1 |
256-bit |
~125-bit |
ZK-friendly secp256k1 (EVM proofs) |
ECDSA/SNARK |
| Pallas/Vesta |
255-bit |
~128-bit |
Mina, halo2 (Pasta curves) |
PLONKish |
| BLS48 |
576-bit |
~256-bit |
High-security BLS (rare) |
BLS |
Signature Scheme Decision Tree
Decide: Signature Scheme for Blockchain Protocol
├── Need EVM compatibility?
│ ├── YES → ECDSA over secp256k1
│ │ ├── Individual signing only
│ │ ├── Library: libsecp256k1 (Bitcoin Core)
│ │ ├── Gas cost: 21,000 base + ~2,000 per ecrecover
│ │ └── Nonce: RFC 6979 deterministic (prevents reuse)
│ └── YES + aggregation → BLS over BN254 (precompile)
│ └── Gas cost: ~25,000 per pairing check
├── Need high throughput + small keys?
│ ├── YES → Ed25519
│ │ ├── Multiple signatures per block
│ │ ├── Verification: ~0.05ms per signature
│ │ └── Library: ed25519-dalek (Rust), libsodium (C)
│ └── NO → Evaluate aggregation requirements
├── Need signature aggregation?
│ ├── Single-message → BLS over BLS12-381
│ │ ├── Use: Consensus signing, validator attestation
│ │ ├── Library: blst (C/Rust), herumi BLS
│ │ └── Rogue key protection: Proof of Possession
│ ├── Multi-message → BLS with PoP or Schnorr threshold
│ │ └── Use: Cross-chain IBC, bridge validation
│ └── Threshold only → FROST over Ed25519 or BLS
│ └── Library: frost-lib (Rust)
└── Need zero-knowledge compatibility?
├── Groth16/Bulletproofs → BN254 (EVM precompile)
└── PLONK → BLS12-381 (more efficient PLONK arithmetization)
Hash Function Decision Tree
Decide: Hash Function
├── EVM chain?
│ ├── Standard hashing → Keccak-256
│ ├── Contract storage → Keccak-256 (32-byte slots)
│ └── Merkle tree → Keccak-256 or SHA-256 (for L2)
├── Bitcoin-based?
│ ├── Transaction hashing → SHA-256d (double SHA-256)
│ ├── Address hashing → RIPEMD-160(SHA-256(pubkey))
│ └── Script hashing → SHA-256
├── ZK-circuits?
│ ├── Prover-friendly → Poseidon (low constraint count)
│ ├── Standard → SHA-256 (expensive in circuits)
│ └── Commitment → Pedersen hash
└── General purpose?
├── Fast hashing → BLAKE2b/BLAKE2s
├── Standard security → SHA-256
└── Password hashing → Argon2 (not for on-chain)
EVM Cryptographic Precompile Reference
| Address |
Precompile |
Gas Cost |
Purpose |
| 0x01 |
ecrecover |
3,000 |
ECDSA public key recovery |
| 0x02 |
SHA-256 |
60 + 12/word |
SHA-256 hash |
| 0x03 |
RIPEMD-160 |
600 + 120/word |
RIPEMD-160 hash |
| 0x04 |
identity |
15 + 3/word |
Data copy |
| 0x05 |
modexp |
Variable (200-50,000+) |
Modular exponentiation |
| 0x06 |
ecadd (BN254) |
150 |
BN254 point addition |
| 0x07 |
ecmul (BN254) |
6,000 |
BN254 scalar multiplication |
| 0x08 |
ecpairing (BN254) |
45,000 base + 34,000/pair |
BN254 pairing check |
| 0x09 |
BLAKE2f |
Variable |
BLAKE2 compression |
| 0x0a |
Point evaluation (EIP-4844) |
50,000 |
KZG proof verification |
| 0x0b |
P256VERIFY (P-256) |
~3,450 |
secp256r1 signature verification |
Common Pitfalls
- Non-deterministic ECDSA nonce reuse: Reusing a nonce (k-value) across two ECDSA signatures reveals the private key. Always use RFC 6979 deterministic nonce generation.
- Missing subgroup checks: Accepting points not in the correct subgroup of the elliptic curve enables small-subgroup attacks that leak secret key bits.
- Incorrect hash-to-curve domain separation: Using the same domain separation tag across protocols enables cross-protocol signature replay attacks.
- Rogue key attacks in BLS without PoP: Aggregating BLS signatures without proof of possession allows key cancellation and signature forgery.
- Timing side-channels in scalar multiplication: Secret-dependent execution time in point multiplication leaks the private key through network timing.
- Weak entropy in key generation: Insufficient entropy in the seed for BIP-39 or key generation allows brute-force of the key space.
- Using SHA-256 in zk-circuits: SHA-256 is extremely expensive in ZK circuits (~30k constraints per invocation). Use Poseidon or Pedersen for ZK-friendly hashing.
- Integer overflow in scalar arithmetic: Overflow in curve order arithmetic can cause signature malleability or key recovery (especially in EVM precompiles).
- Invalid curve point attacks: Accepting points from an attacker that lie on a curve with different order (weaker security) than the intended curve.
- Ignoring post-quantum threat: Deploying long-lived contracts or validators without planning for post-quantum migration creates existential risk.
- ECDSA signature malleability: ECDSA signatures can be malleated (r, s) → (r, n-s) to produce a different valid signature for the same message. Use lower-s form (BIP-62/BIP-146).
- EIP-712 domain separator collision: Using the same domain separator across different contracts allows cross-contract replay of typed signatures.
- Incorrect EIP-191 version byte: Using wrong version byte (0x00 vs 0x01 vs 0x45) makes signed messages validate against different intended formats.
- Hash-to-curve using cofactor clearing incorrectly: Improper cofactor clearing in hash-to-curve can produce points in small subgroups or invalid points.
- PSBT non-witness UTXO omission: Not including full non-witness UTXO in PSBT for legacy inputs prevents hardware wallet from verifying the input.
- BIP-32 hardened derivation in non-hardened code: Hardened derivation requires the private key, but some code tries to derive hardened paths from public key alone.
- Pairing target field mismatch: Using G1×G2 pairings when G2×G1 is expected (or vice versa) produces incorrect verification.
- KRACK-like attacks in threshold signing: Some threshold protocols (GG20) have known attacks where a compromised party can extract other parties' secret shares during signing.
Best Practices
Key Management
- Always use BIP-32 hierarchical deterministic derivation for wallet key management
- BIP-39 mnemonic seeds must use 12+ words (128+ bits of entropy) and standard wordlist
- BIP-44 path structure:
m/44'/coin'/account'/change/index
- For Taproot: use BIP-86 path:
m/86'/coin'/account'/change/index
- For validator keys (Ethereum 2.0): use EIP-2333 (BLS key derivation with
withdraw prefix)
- Hardware wallet signing for all high-value key operations
- Regular key rotation schedule for validator and operator keys
- Sharded key storage with geographic distribution for critical keys
- Use SLIP-0010 for Ed25519 HD derivation (not BIP-32 which doesn't support Ed25519)
Signature Verification
- Always validate signature bounds (r, s < curve order; s is low-s for ECDSA)
- Validate public key is on curve and in correct subgroup
- Use batched verification when verifying multiple signatures
- For EVM: prefer
ecrecover precompile over custom Solidity ECDSA
- Constant-time comparison for signature validation to prevent timing attacks
- Use EIP-712 typed structured data for smart contract signatures (not raw
eth_sign)
- Verify domain separator matches the verifying contract's chain ID and address
Zero-Knowledge Implementation
- Use Groth16 for fixed-circuit proofs (most gas-efficient on EVM)
- Use PLONK for variable-circuit proofs (larger proof size, no trusted setup per circuit)
- Use Bulletproofs for range proofs and confidential transactions
- Always verify proof public inputs match the expected computation
- Reference audited implementations (circom, halo2, bellman)
- Use recursive proofs for batched verification (reduce on-chain cost)
Elliptic Curve Operations
- Always validate point-on-curve before any scalar multiplication
- Use Montgomery ladder or window method for constant-time operations
- Precompute multiples for fixed-point multiplication (GLV method for secp256k1)
- Use Shamir's trick for multi-scalar multiplication (faster than separate)
- Validate infinity point as valid (not a failure condition)
Cryptographic Audit Checklist
Implementation Security Patterns
- Use libsecp256k1 for secp256k1 (the reference implementation, constantly audited)
- Use blst for BLS12-381 (Supranational, audited, constant-time)
- For Ed25519 batch verification, use ed25519-dalek's
verify_batch (batched scalar multiplication)
- For threshold ECDSA: prefer CMP protocol (CGGMP21) over GG20 (GG20 has known flaws)
- For threshold EdDSA: FROST (Flexible Round-Optimized Schnorr Threshold) is the standard
- For BLS threshold: use the BLS IETF draft specification with PoP
- Never implement custom pairing operations—always use audited libraries (bn256, blst, mcl)
Compared With
| Aspect |
Classical (ECDSA/EdDSA) |
Pairing-Based (BLS) |
Post-Quantum (Dilithium) |
| Signature size |
~64-71 bytes |
~48-96 bytes |
~4,592 bytes |
| Verification speed |
~0.05ms |
~2ms |
~0.2ms |
| Aggregation |
Not supported |
Native bilinear |
Complex (KKW) |
| Key size |
~32-33 bytes |
~48-96 bytes |
~1,952 bytes |
| Quantum secure |
No (Shor breaks) |
No (Shor breaks) |
Yes (lattice) |
| Maturity |
Production (20+ years) |
Production (10+ years) |
Standardization (2024+) |
| Side-channel risk |
Low (constant-time) |
Medium (pairing complex) |
High (lattice ops) |
Signature Aggregation Schemes Compared
| Scheme |
Rounds |
Signers |
Aggregation Type |
Trust Model |
| BLS |
1 round |
Unlimited |
Signature + public key |
PoP required |
| MuSig2 |
2 rounds |
~100 practical |
Public key only |
Key aggregation (no PoP) |
| FROST |
2-3 rounds |
~50 practical |
Threshold |
t-of-n, identifiable abort |
| ROAST |
Round-optimized |
Unlimited |
Wraps any threshold scheme |
Robust (handles faulty signers) |
| Bellare-Neven |
3 rounds |
Unlimited |
Public key only |
No PoP, provably secure |
Hash Function Comparison for ZK Circuits
| Hash |
Constraints (per 256-bit) |
Prover Time |
Best For |
| Poseidon |
~10 |
~0.1ms |
ZK-optimized, general purpose |
| Rescue |
~12 |
~0.15ms |
ZK-optimized (Plonky2) |
| MiMC |
~5 |
~0.05ms |
Smallest constraints (weak security at low rounds) |
| SHA-256 |
~30,000 |
~10ms |
Compatibility with Bitcoin/Ethereum |
| Keccak-256 |
~25,000 |
~8ms |
EVM compatibility |
| Blake2s |
~15,000 |
~5ms |
General purpose, EVM precompile |
| Pedersen |
~2 |
~0.02ms |
Only for commitments (not collision-resistant) |
Merkle Tree Variants
| Type |
Depth |
Proof Size |
Use Case |
| Binary Merkle |
log2(n) |
32*log2(n) bytes |
General proof of inclusion |
| Merkle Patricia Trie |
Variable |
O(log n) |
Ethereum state storage |
| Sparse Merkle Tree |
256 |
256*32=8KB (can prune) |
Identity, state commitments |
| Verkle Trie (IPA) |
8 (k=256) |
~1KB for 2^24 entries |
Ethereum state (future) |
| Sparse Compact SMT |
256 |
O(log n) with pruning |
Celestia, rollup state |
Performance Considerations
- EVM ecrecover: ~2,000-3,000 gas per signature recovery on mainnet
- BN254 pairing: ~25,000 gas per pairing check (precompile at 0x08)
- BLS12-381 verification: No native precompile; ~500,000+ gas via Solidity implementation
- Ed25519 batch verification: 1.5x faster than individual on modern CPUs with SIMD
- Poseidon hash in zk-SNARKs: ~10 constraints per hash vs. ~30,000 for SHA-256
- Merkle proof verification: O(log n) hashes; 256-bit hash = 32 bytes per level
- HD wallet derivation: BIP-32 hardened key derivation ~10x slower than non-hardened
- Key generation: Ed25519 fastest (
0.1ms), BLS12-381 slowest (10ms with pairings)
- BLS signature aggregation: O(n) for n signatures, batch verification O(n) but 10x faster than individual
- MuSig2 key aggregation: O(n) for key setup, then single verification
- EIP-712 signing: ~0.5ms off-chain, ~20k gas on-chain for
ecrecover + ecrecover match
Operations & Maintenance
Key Rotation
- Validator consensus keys: Rotate monthly or immediately if compromise suspected
- Governance multi-sig keys: Rotate quarterly with hardware wallet ceremony
- Hot wallet (operational) keys: Rotate weekly or use threshold signing with M-of-N
- Cold/treasury keys: Rotate annually with GPS-located ceremony recording
- BLS validator withdrawal keys: Must not rotate without exit + re-deposit (stake linked)
Monitoring
- Signature failure rate: Spike may indicate network attack or implementation bug
- Verification latency: Degradation may indicate DoS or resource exhaustion
- Key registration events: Monitor for unauthorized key changes
- Nonce reuse detection: Scan blockchain for ECDSA signatures with identical
r values
- Pairing computation time: Track on validators for resource planning
- PSBT signing failures: Cluster by signer to identify faulty hardware wallets
Cryptographic Testing
- Run KATs on every deployment to verify implementation correctness
- Fuzz test with: zero scalars, infinity points, out-of-order field elements, large nonces
- Cross-verify: compare against independent library output (e.g., btcd vs libsecp256k1)
- Property-based tests: (sign → recover → verify) roundtrip must always pass
Rules
- Always use deterministic nonces for ECDSA signing (RFC 6979) to prevent private key leakage from nonce reuse
- Validate point-on-curve and subgroup membership for all incoming ECC operations
- Use BLS with Proof of Possession (PoP) to prevent rogue key aggregation attacks
- Never implement custom cryptographic primitives—use audited, standardized libraries
- Use domain separation tags (DST) that are unique to each protocol for hash-to-curve operations
- Prefer Keccak-256 for EVM, SHA-256 for Bitcoin, BLAKE2 for general, Poseidon for ZK
- All cryptographic comparisons must use constant-time equality checks
- Key derivation must follow BIP-32/39/44/86 hierarchical deterministic path standards
- Pairing-friendly curves: BN254 for EVM precompile, BLS12-381 for new consensus systems
- Post-quantum signatures: use CRYSTALS-Dilithium for balanced, FALCON for compact
- zk-proofs: Groth16 for fixed circuits (gas-efficient), PLONK for variable circuits (flexible)
- Every implementation must pass Known-Answer Tests (KATs) from the relevant standard
- Hash functions used in Merkle trees must have fixed output length for the entire tree
- Threshold signatures: prefer FROST over GG20 for newer implementations (simpler, audited)
- ECDSA signature malleability: use lower-s form as standardized in BIP-62/BIP-146
- Never truncate hash outputs below 160 bits for blockchain address derivation
- EIP-712 typed data signatures must include chain ID in domain separator
- Hardware wallet signing must verify the displayed message against the raw bytes being signed
- BLS signature aggregation must verify PoP before including any public key in the aggregate set
- Use SLIP-0010 for Ed25519 HD derivation (BIP-32 does not support Ed25519 natively)
- MuSig2 requires key aggregation with tweak support for Taproot output key construction
- PSBT (BIP-174) must include full non-witness UTXO for legacy transaction inputs
- Hash-to-curve implementations must follow IETF draft-irtf-cfrg-hash-to-curve v16
- Cross-chain signature verification must prevent chain ID replay using domain separation
- ZK proof verification on-chain must check all public inputs against contract state
Implementation Examples
ECDSA Signing (Rust — libsecp256k1)
use secp256k1::{Secp256k1, Message, SecretKey, PublicKey, Signature};
use sha3::{Keccak256, Digest};
fn sign_message(secret_key_bytes: &[u8; 32], message_bytes: &[u8]) -> Result<Vec<u8>, Error> {
let secp = Secp256k1::new();
let secret_key = SecretKey::from_slice(secret_key_bytes)?;
let message = Message::from_slice(&Keccak256::digest(message_bytes))?;
// Deterministic nonce per RFC 6979 (handled by libsecp256k1)
let signature: Signature = secp.sign_ecdsa(&message, &secret_key);
// Serialize as 65-byte [r || s || v] (Ethereum format)
let mut serialized = signature.serialize_compact().to_vec();
let rec_id = signature.serialize_der(); // recoverable signature
serialized.push(rec_id[0]); // v = 27/28 or 35+chain_id*2
Ok(serialized)
}
fn verify_signature(
public_key_bytes: &[u8; 64], // uncompressed x || y
message_bytes: &[u8],
signature_bytes: &[u8; 65], // r || s || v
) -> Result<bool, Error> {
let secp = Secp256k1::new();
let public_key = PublicKey::from_slice(&[0x04; public_key_bytes].concat())?;
let message = Message::from_slice(&Keccak256::digest(message_bytes))?;
let signature = Signature::from_compact(&signature_bytes[..64])?;
// Additionally: verify low-s form (BIP-62/BIP-146)
// Verify s <= n/2 (curve order / 2)
let s = signature.serialize_compact()[32..64].to_vec();
let n = "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141";
Ok(secp.verify_ecdsa(&message, &signature, &public_key).is_ok())
}
BLS Signature Aggregation (Rust — blst)
use blst::min_pk::*;
fn aggregate_and_verify(
public_keys: &[PublicKey],
message: &[u8],
signatures: &[Signature],
) -> bool {
// Step 1: Verify proof of possession for each public key
for pk in public_keys {
let pop = pk.sign_pop(); // PoP is required for rogue-key defense
if !pk.verify_pop(&pop) {
return false;
}
}
// Step 2: Aggregate public keys and signatures
let aggregated_pk: AggregatePublicKey = AggregatePublicKey::aggregate(public_keys, false);
let aggregated_sig: AggregateSignature = AggregateSignature::aggregate(signatures, false);
// Step 3: Fast aggregate verification
// This is ~10x faster than verifying N signatures individually
aggregated_sig.verify(true, message, &[], &aggregated_pk.to_public_key(), false)
}
Merkle Proof Verification (Solidity)
contract MerkleVerifier {
// Verify a Merkle inclusion proof
// leaf: hash of leaf data
// merkleRoot: expected root
// proof: sibling hashes from leaf to root
// flags: bitmask indicating left (0) or right (1) position per level
function verify(
bytes32 leaf,
bytes32 merkleRoot,
bytes32[] calldata proof,
uint256 flags
) external pure returns (bool) {
bytes32 computed = leaf;
for (uint256 i = 0; i < proof.length; i++) {
if ((flags >> i) & 1 == 0) {
// Sibling is on the right: hash(left || right)
computed = keccak256(abi.encodePacked(computed, proof[i]));
} else {
// Sibling is on the left: hash(sibling || computed)
computed = keccak256(abi.encodePacked(proof[i], computed));
}
}
return computed == merkleRoot;
}
}
EIP-712 Typed Data Signing (TypeScript + Solidity)
// Off-chain signing (TypeScript — viem + ethers)
const domain = {
name: "MyProtocol",
version: "1",
chainId: 1,
verifyingContract: "0x1234..." as const,
};
const types = {
Transfer: [
{ name: "to", type: "address" },
{ name: "amount", type: "uint256" },
{ name: "nonce", type: "uint256" },
{ name: "deadline", type: "uint256" },
],
};
const message = {
to: "0x5678...",
amount: 100n,
nonce: 0n,
deadline: 1700000000n,
};
// Sign with wallet
const signature = await wallet.signTypedData(domain, types, message);
// On-chain verification (Solidity)
contract EIP712Verifier is EIP712 {
bytes32 private constant TRANSFER_TYPEHASH = keccak256(
"Transfer(address to,uint256 amount,uint256 nonce,uint256 deadline)"
);
mapping(address => mapping(uint256 => bool)) public usedNonces;
function executeTransfer(
address to,
uint256 amount,
uint256 nonce,
uint256 deadline,
bytes calldata signature
) external {
require(block.timestamp <= deadline, "Signature expired");
require(!usedNonces[msg.sender][nonce], "Nonce used");
bytes32 structHash = keccak256(
abi.encode(TRANSFER_TYPEHASH, to, amount, nonce, deadline)
);
bytes32 digest = _hashTypedDataV4(structHash);
address signer = ECDSA.recover(digest, signature);
require(signer == msg.sender, "Invalid signer");
usedNonces[msg.sender][nonce] = true;
// Execute transfer...
}
}
Hash-to-Curve (BLS12-381 — Rust)
use blst::*;
use sha2::{Sha256, Digest};
fn hash_to_curve(message: &[u8], dst: &[u8]) -> Result<Vec<u8>, String> {
// IETF hash-to-curve (draft-irtf-cfrg-hash-to-curve v16)
// Domain separation tag MUST be unique per protocol context
let point = blst_p1_hash_to::hash_to(message, dst, &[]);
// Compressed form: 48 bytes for BLS12-381 G1
let mut compressed = [0u8; 48];
point.compress(&mut compressed);
Ok(compressed.to_vec())
}
// Example DST usage:
// Nonce signature DST: "BLS_SIG_BLS12381G2_XMD:SHA-256_SSWU_RO_POP_"
// Proof of possession DST: "BLS_POP_BLS12381G2_XMD:SHA-256_SSWU_RO_POP_"
BIP-32 HD Wallet Derivation (TypeScript)
import { secp256k1 } from '@noble/curves/secp256k1';
import { hmac } from '@noble/hashes/hmac';
import { sha512 } from '@noble/hashes/sha512';
interface HDKey {
privateKey?: Uint8Array;
publicKey: Uint8Array;
chainCode: Uint8Array;
depth: number;
index: number;
parentFingerprint: number;
}
function ckdPriv(parent: HDKey, index: number): HDKey {
const isHardened = index >= 0x80000000;
// Hardened: serP(parent.publicKey) || ser32(index)
// Non-hardened: serP(parent.publicKey) || ser32(index)
const data = isHardened
? new Uint8Array([0x00, ...parent.privateKey!, ...toBytes32(index)])
: new Uint8Array([...parent.publicKey, ...toBytes32(index)]);
const I = hmac(sha512, parent.chainCode, data);
const IL = I.slice(0, 32);
const IR = I.slice(32, 64);
// IL + parent private key (mod n)
const childPriv = secp256k1.utils.addPrivateKeys(
hexlify(parent.privateKey!),
hexlify(IL)
);
return {
privateKey: hexToBytes(childPriv),
publicKey: secp256k1.getPublicKey(childPriv, true),
chainCode: IR,
depth: parent.depth + 1,
index,
parentFingerprint: fingerprint(parent.publicKey),
};
}
// Derivation path: m/44'/60'/0'/0/0 (Ethereum account)
function derivePath(master: HDKey, path: string): HDKey {
const parts = path.replace(/^m\//, '').split('/');
let key = master;
for (const part of parts) {
const isHardened = part.endsWith("'");
const index = parseInt(part) + (isHardened ? 0x80000000 : 0);
key = ckdPriv(key, index);
}
return key;
}
Post-Quantum Migration Path Strategy
Phase 1 (2024-2026): Hybrid signatures
- Combine ECDSA + Dilithium in transaction authentication
- Both signatures must validate for the transaction to be valid
- Library: liboqs (C/Rust), pqcrypto-dilithium (Rust)
Phase 2 (2027-2032): NIST PQC standardization
- CRYSTALS-Dilithium for general signatures (balanced size/speed)
- FALCON for compact signatures (smaller proofs, slower verification)
- SPHINCS+ for stateless hash-based (largest, but most trusted)
Phase 3 (2032+): Full quantum transition
- Longer blocks (PQC signatures: 2-5KB vs 64-96 bytes classical)
- Different UTXO/lock script models for quantum-safe addresses
- Merkle-tree-based signature aggregation (reduce per-tx overhead)
Key concern: Harvest now, decrypt later attacks
- Encrypting on-chain data that will be decrypted with quantum computers
- High-value contracts (bridges, DAO treasuries) should use hybrid encryption
References
- references/blockchain-cryptography-advanced.md — Blockchain Cryptography Advanced Topics
- references/blockchain-cryptography-fundamentals.md — Blockchain Cryptography Fundamentals
- references/elliptic-curve-crypto.md — Elliptic Curve Cryptography for Blockchain
- references/hash-functions.md — Hash Functions in Blockchain
- references/key-derivation-management.md — Key Derivation and Management
- references/merkle-trees.md — Merkle Trees in Blockchain
- references/pairing-based-cryptography.md — Pairing-Based Cryptography
- references/post-quantum-blockchain-crypto.md — Post-Quantum Blockchain Cryptography
- references/signature-schemes.md — Signature Schemes in Blockchain
- references/zero-knowledge-deep.md — Zero-Knowledge Proofs in Blockchain
Handoff
blockchain-cryptography → blockchain-core (for protocol-level crypto integration)
blockchain-cryptography → blockchain-security (for cryptographic audit methodology)
blockchain-cryptography → blockchain-application (for zk-proof integration in contracts)
1---2name: blockchain-cryptography3description: Use this skill when asked about cryptographic primitives in blockchain, elliptic curve cryptography, hash functions, Merkle trees, digital signatures, zero-knowledge proofs, key derivation, BIP standards, and blockchain-specific crypto implementations. Languages: C++, Rust, Go, Python. Covers secp256k1, BN254, BLS12-381, Ed25519, SHA-256, Keccak-256, BLAKE2, Poseidon, Merkle trees (binary, Patricia, sparse, Verkle), ECDSA, Schnorr, BLS, threshold signatures (FROST, GG20), zk-SNARKs/STARKs/Bulletproofs, HD wallets (BIP-32/39/44), PSBT (BIP-174), and signature aggregation. Do NOT use for: general blockchain protocols (use blockchain-core), smart contract development (use blockchain-application), or standard web security cryptography outside blockchain.4license: MIT5---67# Blockchain Cryptography89## Purpose10Guide the selection, implementation, and optimization of cryptographic primitives specific to blockchain systems. This skill enforces correct curve selection, signature scheme choice, and key management practices across all major blockchain protocols.1112## Agent Protocol1314### Trigger15"blockchain cryptography", "elliptic curve", "secp256k1", "BN254", "BLS", "Ed25519", "hash function blockchain", "Keccak-256", "SHA-256 blockchain", "Poseidon hash", "Merkle tree", "Merkle Patricia Trie", "Sparse Merkle Tree", "Verkle Trie", "ECDSA", "Schnorr signature", "BLS signature", "threshold signature", "FROST", "multi-sig", "aggregate signature", "zero-knowledge", "zk-SNARK", "zk-STARK", "Bulletproof", "circom", "Halo2", "BIP-32", "BIP-39", "BIP-44", "BIP-340", "PSBT", "BIP-174", "HD wallet", "key derivation", "cryptographic primitive", "signature scheme", "pairing-based cryptography", "post-quantum", "ecrecover", "EIP-712", "EIP-191", "RFC 6979", "KAT", "known-answer test", "nonce reuse", "signature malleability", "MuSig2", "threshold signing", "DKLs", "CGGMP", "aggregate signature", "hash-to-curve", "ICP", "Internet Computer"1617### Input Context18- Cryptographic operation (signing, verification, hashing, proof generation)19- Blockchain platform (Ethereum/Bitcoin/Solana/Cosmos)20- Security level requirement (128-bit / 192-bit / 256-bit)21- Performance constraints (verification throughput, gas budget)22- Key management model (single key, HD wallet, multi-sig, threshold)23- Threat model (passive/active, quantum-resistant needed?)2425### Output Artifact26Cryptographic architecture specification including:27- Selected primitives with curve/parameter justifications28- Implementation approach with library recommendations29- Security analysis with known attack vectors and mitigations30- Performance benchmarks and optimization strategies3132### Response Format331. **Cryptographic primitive**: curve/hash/scheme + security level + performance characteristics342. **Blockchain usage**: where and how this primitive is used in real blockchain networks353. **Implementation details**: algorithm specifics, edge cases, optimization techniques364. **Security considerations**: known attacks, parameter choices, implementation pitfalls3738### Completion Criteria39- Cryptographic primitive selection includes security level justification with NIST/BSI references40- Implementation plan specifies library, language, and optimization targets for on-chain or off-chain use41- Security analysis identifies known attack vectors (rogue key, small subgroup, timing side-channel)42- Performance benchmarks include verification latency and signature size comparison43- Key management design covers derivation path, backup, and recovery for the specific scheme4445### Max Response Length464000 tokens4748## Workflow4950### Phase 1: Primitive Selection511. Identify required cryptographic operations (signing, hashing, commitment, proof generation)522. Select elliptic curve based on blockchain platform and security requirements533. Choose signature scheme (ECDSA for EVM, EdDSA for Solana/Near, BLS for aggregation)544. Select hash functions (Keccak-256 for EVM, SHA-256 for Bitcoin, BLAKE2 for Zcash)555. Determine if pairing-based crypto is needed (BLS aggregation, zk-SNARK verification)5657### Phase 2: Security Parameter Validation586. Verify security level meets minimum requirements (128-bit for standard, 192-bit for high security)597. Validate subgroup membership for all curve operations608. Confirm constant-time implementation for secret-dependent operations619. Review against known attacks (invalid curve, small subgroup, timing, fault injection)6210. Check compliance with applicable standards (FIPS 186-5, BIP, NIST PQC)6364### Phase 3: Implementation6511. Select library: libsecp256k1 (ECDSA), blst (BLS), ed25519-dalek (EdDSA), circom (ZK)6612. Implement key generation with proper entropy source and domain separation6713. Implement signing with deterministic nonce generation (RFC 6979 for ECDSA)6814. Implement verification with all validation checks (curve, subgroup, signature bounds)6915. Implement key management with BIP-32/39/44 derivation path standard7071### Phase 4: Integration and Testing7216. Integrate with the target blockchain protocol or smart contract7317. Test with known-answer tests (KATs) from standards documents7418. Implement fuzz testing for edge cases (zero scalars, identity, large nonces)7519. Cross-verify with independent implementations7620. Benchmark verification throughput and gas costs7778## Architecture / Decision Trees7980### Curve Selection8182| Curve | Field Size | Security Level | Blockchain Usage | Key Type |83|---|---|---|---|---|84| secp256k1 | 256-bit | ~128-bit | Bitcoin, Ethereum (EOA), EVM chains | ECDSA |85| Ed25519 | 255-bit | ~128-bit | Solana, Near, Cardano | EdDSA |86| BLS12-381 | 381-bit | ~128-bit | Ethereum 2.0, Chia, Filecoin | BLS |87| BN254 | 254-bit | ~100-bit | EVM zk precompile, Zcash sprout | Pairing |88| P-256 (secp256r1) | 256-bit | ~128-bit | WebAuthn, Apple/Google passes | ECDSA |89| Curve25519 | 255-bit | ~128-bit | X25519 key exchange, Signal protocol | Diffie-Hellman |90| secq256k1 | 256-bit | ~125-bit | ZK-friendly secp256k1 (EVM proofs) | ECDSA/SNARK |91| Pallas/Vesta | 255-bit | ~128-bit | Mina, halo2 (Pasta curves) | PLONKish |92| BLS48 | 576-bit | ~256-bit | High-security BLS (rare) | BLS |9394### Signature Scheme Decision Tree9596```97Decide: Signature Scheme for Blockchain Protocol98├── Need EVM compatibility?99│ ├── YES → ECDSA over secp256k1100│ │ ├── Individual signing only101│ │ ├── Library: libsecp256k1 (Bitcoin Core)102│ │ ├── Gas cost: 21,000 base + ~2,000 per ecrecover103│ │ └── Nonce: RFC 6979 deterministic (prevents reuse)104│ └── YES + aggregation → BLS over BN254 (precompile)105│ └── Gas cost: ~25,000 per pairing check106├── Need high throughput + small keys?107│ ├── YES → Ed25519108│ │ ├── Multiple signatures per block109│ │ ├── Verification: ~0.05ms per signature110│ │ └── Library: ed25519-dalek (Rust), libsodium (C)111│ └── NO → Evaluate aggregation requirements112├── Need signature aggregation?113│ ├── Single-message → BLS over BLS12-381114│ │ ├── Use: Consensus signing, validator attestation115│ │ ├── Library: blst (C/Rust), herumi BLS116│ │ └── Rogue key protection: Proof of Possession117│ ├── Multi-message → BLS with PoP or Schnorr threshold118│ │ └── Use: Cross-chain IBC, bridge validation119│ └── Threshold only → FROST over Ed25519 or BLS120│ └── Library: frost-lib (Rust)121└── Need zero-knowledge compatibility?122 ├── Groth16/Bulletproofs → BN254 (EVM precompile)123 └── PLONK → BLS12-381 (more efficient PLONK arithmetization)124```125126### Hash Function Decision Tree127128```129Decide: Hash Function130├── EVM chain?131│ ├── Standard hashing → Keccak-256132│ ├── Contract storage → Keccak-256 (32-byte slots)133│ └── Merkle tree → Keccak-256 or SHA-256 (for L2)134├── Bitcoin-based?135│ ├── Transaction hashing → SHA-256d (double SHA-256)136│ ├── Address hashing → RIPEMD-160(SHA-256(pubkey))137│ └── Script hashing → SHA-256138├── ZK-circuits?139│ ├── Prover-friendly → Poseidon (low constraint count)140│ ├── Standard → SHA-256 (expensive in circuits)141│ └── Commitment → Pedersen hash142└── General purpose?143 ├── Fast hashing → BLAKE2b/BLAKE2s144 ├── Standard security → SHA-256145 └── Password hashing → Argon2 (not for on-chain)146```147148### EVM Cryptographic Precompile Reference149150| Address | Precompile | Gas Cost | Purpose |151|---|---|---|---|152| 0x01 | ecrecover | 3,000 | ECDSA public key recovery |153| 0x02 | SHA-256 | 60 + 12/word | SHA-256 hash |154| 0x03 | RIPEMD-160 | 600 + 120/word | RIPEMD-160 hash |155| 0x04 | identity | 15 + 3/word | Data copy |156| 0x05 | modexp | Variable (200-50,000+) | Modular exponentiation |157| 0x06 | ecadd (BN254) | 150 | BN254 point addition |158| 0x07 | ecmul (BN254) | 6,000 | BN254 scalar multiplication |159| 0x08 | ecpairing (BN254) | 45,000 base + 34,000/pair | BN254 pairing check |160| 0x09 | BLAKE2f | Variable | BLAKE2 compression |161| 0x0a | Point evaluation (EIP-4844) | 50,000 | KZG proof verification |162| 0x0b | P256VERIFY (P-256) | ~3,450 | secp256r1 signature verification |163164## Common Pitfalls1651661. **Non-deterministic ECDSA nonce reuse**: Reusing a nonce (k-value) across two ECDSA signatures reveals the private key. Always use RFC 6979 deterministic nonce generation.1672. **Missing subgroup checks**: Accepting points not in the correct subgroup of the elliptic curve enables small-subgroup attacks that leak secret key bits.1683. **Incorrect hash-to-curve domain separation**: Using the same domain separation tag across protocols enables cross-protocol signature replay attacks.1694. **Rogue key attacks in BLS without PoP**: Aggregating BLS signatures without proof of possession allows key cancellation and signature forgery.1705. **Timing side-channels in scalar multiplication**: Secret-dependent execution time in point multiplication leaks the private key through network timing.1716. **Weak entropy in key generation**: Insufficient entropy in the seed for BIP-39 or key generation allows brute-force of the key space.1727. **Using SHA-256 in zk-circuits**: SHA-256 is extremely expensive in ZK circuits (~30k constraints per invocation). Use Poseidon or Pedersen for ZK-friendly hashing.1738. **Integer overflow in scalar arithmetic**: Overflow in curve order arithmetic can cause signature malleability or key recovery (especially in EVM precompiles).1749. **Invalid curve point attacks**: Accepting points from an attacker that lie on a curve with different order (weaker security) than the intended curve.17510. **Ignoring post-quantum threat**: Deploying long-lived contracts or validators without planning for post-quantum migration creates existential risk.17611. **ECDSA signature malleability**: ECDSA signatures can be malleated (r, s) → (r, n-s) to produce a different valid signature for the same message. Use lower-s form (BIP-62/BIP-146).17712. **EIP-712 domain separator collision**: Using the same domain separator across different contracts allows cross-contract replay of typed signatures.17813. **Incorrect EIP-191 version byte**: Using wrong version byte (0x00 vs 0x01 vs 0x45) makes signed messages validate against different intended formats.17914. **Hash-to-curve using cofactor clearing incorrectly**: Improper cofactor clearing in hash-to-curve can produce points in small subgroups or invalid points.18015. **PSBT non-witness UTXO omission**: Not including full non-witness UTXO in PSBT for legacy inputs prevents hardware wallet from verifying the input.18116. **BIP-32 hardened derivation in non-hardened code**: Hardened derivation requires the private key, but some code tries to derive hardened paths from public key alone.18217. **Pairing target field mismatch**: Using G1×G2 pairings when G2×G1 is expected (or vice versa) produces incorrect verification.18318. **KRACK-like attacks in threshold signing**: Some threshold protocols (GG20) have known attacks where a compromised party can extract other parties' secret shares during signing.184185## Best Practices186187### Key Management188- Always use BIP-32 hierarchical deterministic derivation for wallet key management189- BIP-39 mnemonic seeds must use 12+ words (128+ bits of entropy) and standard wordlist190- BIP-44 path structure: `m/44'/coin'/account'/change/index`191- For Taproot: use BIP-86 path: `m/86'/coin'/account'/change/index`192- For validator keys (Ethereum 2.0): use EIP-2333 (BLS key derivation with `withdraw` prefix)193- Hardware wallet signing for all high-value key operations194- Regular key rotation schedule for validator and operator keys195- Sharded key storage with geographic distribution for critical keys196- Use SLIP-0010 for Ed25519 HD derivation (not BIP-32 which doesn't support Ed25519)197198### Signature Verification199- Always validate signature bounds (r, s < curve order; s is low-s for ECDSA)200- Validate public key is on curve and in correct subgroup201- Use batched verification when verifying multiple signatures202- For EVM: prefer `ecrecover` precompile over custom Solidity ECDSA203- Constant-time comparison for signature validation to prevent timing attacks204- Use EIP-712 typed structured data for smart contract signatures (not raw `eth_sign`)205- Verify domain separator matches the verifying contract's chain ID and address206207### Zero-Knowledge Implementation208- Use Groth16 for fixed-circuit proofs (most gas-efficient on EVM)209- Use PLONK for variable-circuit proofs (larger proof size, no trusted setup per circuit)210- Use Bulletproofs for range proofs and confidential transactions211- Always verify proof public inputs match the expected computation212- Reference audited implementations (circom, halo2, bellman)213- Use recursive proofs for batched verification (reduce on-chain cost)214215### Elliptic Curve Operations216- Always validate point-on-curve before any scalar multiplication217- Use Montgomery ladder or window method for constant-time operations218- Precompute multiples for fixed-point multiplication (GLV method for secp256k1)219- Use Shamir's trick for multi-scalar multiplication (faster than separate)220- Validate infinity point as valid (not a failure condition)221222### Cryptographic Audit Checklist223- [ ] Known-Answer Tests (KATs) pass against NIST/BSI/standard test vectors224- [ ] No secret-dependent branching (constant-time) in any operation using private key data225- [ ] ECDSA nonces generated deterministically per RFC 6979226- [ ] All points validated on-curve and in-correct-subgroup before operations227- [ ] BLS proof of possession verified before including public key in aggregation228- [ ] Domain separation tags are unique per protocol context229- [ ] Hash-to-curve uses approved method (IETF hash-to-curve v16+)230- [ ] BIP-32/BIP-39 implementation verified against standard test vectors231- [ ] ECDSA signatures use lower-s form (canonical encoding)232- [ ] EIP-712 domain separators include chain ID to prevent cross-chain replay233- [ ] Post-quantum awareness documented (with migration path)234235### Implementation Security Patterns236- Use libsecp256k1 for secp256k1 (the reference implementation, constantly audited)237- Use blst for BLS12-381 (Supranational, audited, constant-time)238- For Ed25519 batch verification, use ed25519-dalek's `verify_batch` (batched scalar multiplication)239- For threshold ECDSA: prefer CMP protocol (CGGMP21) over GG20 (GG20 has known flaws)240- For threshold EdDSA: FROST (Flexible Round-Optimized Schnorr Threshold) is the standard241- For BLS threshold: use the BLS IETF draft specification with PoP242- Never implement custom pairing operations—always use audited libraries (bn256, blst, mcl)243244## Compared With245246| Aspect | Classical (ECDSA/EdDSA) | Pairing-Based (BLS) | Post-Quantum (Dilithium) |247|---|---|---|---|248| Signature size | ~64-71 bytes | ~48-96 bytes | ~4,592 bytes |249| Verification speed | ~0.05ms | ~2ms | ~0.2ms |250| Aggregation | Not supported | Native bilinear | Complex (KKW) |251| Key size | ~32-33 bytes | ~48-96 bytes | ~1,952 bytes |252| Quantum secure | No (Shor breaks) | No (Shor breaks) | Yes (lattice) |253| Maturity | Production (20+ years) | Production (10+ years) | Standardization (2024+) |254| Side-channel risk | Low (constant-time) | Medium (pairing complex) | High (lattice ops) |255256## Signature Aggregation Schemes Compared257258| Scheme | Rounds | Signers | Aggregation Type | Trust Model |259|---|---|---|---|---|260| BLS | 1 round | Unlimited | Signature + public key | PoP required |261| MuSig2 | 2 rounds | ~100 practical | Public key only | Key aggregation (no PoP) |262| FROST | 2-3 rounds | ~50 practical | Threshold | t-of-n, identifiable abort |263| ROAST | Round-optimized | Unlimited | Wraps any threshold scheme | Robust (handles faulty signers) |264| Bellare-Neven | 3 rounds | Unlimited | Public key only | No PoP, provably secure |265266## Hash Function Comparison for ZK Circuits267268| Hash | Constraints (per 256-bit) | Prover Time | Best For |269|---|---|---|---|270| Poseidon | ~10 | ~0.1ms | ZK-optimized, general purpose |271| Rescue | ~12 | ~0.15ms | ZK-optimized (Plonky2) |272| MiMC | ~5 | ~0.05ms | Smallest constraints (weak security at low rounds) |273| SHA-256 | ~30,000 | ~10ms | Compatibility with Bitcoin/Ethereum |274| Keccak-256 | ~25,000 | ~8ms | EVM compatibility |275| Blake2s | ~15,000 | ~5ms | General purpose, EVM precompile |276| Pedersen | ~2 | ~0.02ms | Only for commitments (not collision-resistant) |277278## Merkle Tree Variants279280| Type | Depth | Proof Size | Use Case |281|---|---|---|---|282| Binary Merkle | log2(n) | 32*log2(n) bytes | General proof of inclusion |283| Merkle Patricia Trie | Variable | O(log n) | Ethereum state storage |284| Sparse Merkle Tree | 256 | 256*32=8KB (can prune) | Identity, state commitments |285| Verkle Trie (IPA) | 8 (k=256) | ~1KB for 2^24 entries | Ethereum state (future) |286| Sparse Compact SMT | 256 | O(log n) with pruning | Celestia, rollup state |287288## Performance Considerations289290- **EVM ecrecover**: ~2,000-3,000 gas per signature recovery on mainnet291- **BN254 pairing**: ~25,000 gas per pairing check (precompile at 0x08)292- **BLS12-381 verification**: No native precompile; ~500,000+ gas via Solidity implementation293- **Ed25519 batch verification**: 1.5x faster than individual on modern CPUs with SIMD294- **Poseidon hash in zk-SNARKs**: ~10 constraints per hash vs. ~30,000 for SHA-256295- **Merkle proof verification**: O(log n) hashes; 256-bit hash = 32 bytes per level296- **HD wallet derivation**: BIP-32 hardened key derivation ~10x slower than non-hardened297- **Key generation**: Ed25519 fastest (~0.1ms), BLS12-381 slowest (~10ms with pairings)298- **BLS signature aggregation**: O(n) for n signatures, batch verification O(n) but 10x faster than individual299- **MuSig2 key aggregation**: O(n) for key setup, then single verification300- **EIP-712 signing**: ~0.5ms off-chain, ~20k gas on-chain for `ecrecover` + `ecrecover` match301302## Operations & Maintenance303304### Key Rotation305- Validator consensus keys: Rotate monthly or immediately if compromise suspected306- Governance multi-sig keys: Rotate quarterly with hardware wallet ceremony307- Hot wallet (operational) keys: Rotate weekly or use threshold signing with M-of-N308- Cold/treasury keys: Rotate annually with GPS-located ceremony recording309- BLS validator withdrawal keys: Must not rotate without exit + re-deposit (stake linked)310311### Monitoring312- **Signature failure rate**: Spike may indicate network attack or implementation bug313- **Verification latency**: Degradation may indicate DoS or resource exhaustion314- **Key registration events**: Monitor for unauthorized key changes315- **Nonce reuse detection**: Scan blockchain for ECDSA signatures with identical `r` values316- **Pairing computation time**: Track on validators for resource planning317- **PSBT signing failures**: Cluster by signer to identify faulty hardware wallets318319### Cryptographic Testing320- Run KATs on every deployment to verify implementation correctness321- Fuzz test with: zero scalars, infinity points, out-of-order field elements, large nonces322- Cross-verify: compare against independent library output (e.g., btcd vs libsecp256k1)323- Property-based tests: (sign → recover → verify) roundtrip must always pass324325## Rules3263271. Always use deterministic nonces for ECDSA signing (RFC 6979) to prevent private key leakage from nonce reuse3282. Validate point-on-curve and subgroup membership for all incoming ECC operations3293. Use BLS with Proof of Possession (PoP) to prevent rogue key aggregation attacks3304. Never implement custom cryptographic primitives—use audited, standardized libraries3315. Use domain separation tags (DST) that are unique to each protocol for hash-to-curve operations3326. Prefer Keccak-256 for EVM, SHA-256 for Bitcoin, BLAKE2 for general, Poseidon for ZK3337. All cryptographic comparisons must use constant-time equality checks3348. Key derivation must follow BIP-32/39/44/86 hierarchical deterministic path standards3359. Pairing-friendly curves: BN254 for EVM precompile, BLS12-381 for new consensus systems33610. Post-quantum signatures: use CRYSTALS-Dilithium for balanced, FALCON for compact33711. zk-proofs: Groth16 for fixed circuits (gas-efficient), PLONK for variable circuits (flexible)33812. Every implementation must pass Known-Answer Tests (KATs) from the relevant standard33913. Hash functions used in Merkle trees must have fixed output length for the entire tree34014. Threshold signatures: prefer FROST over GG20 for newer implementations (simpler, audited)34115. ECDSA signature malleability: use lower-s form as standardized in BIP-62/BIP-14634216. Never truncate hash outputs below 160 bits for blockchain address derivation34317. EIP-712 typed data signatures must include chain ID in domain separator34418. Hardware wallet signing must verify the displayed message against the raw bytes being signed34519. BLS signature aggregation must verify PoP before including any public key in the aggregate set34620. Use SLIP-0010 for Ed25519 HD derivation (BIP-32 does not support Ed25519 natively)34721. MuSig2 requires key aggregation with tweak support for Taproot output key construction34822. PSBT (BIP-174) must include full non-witness UTXO for legacy transaction inputs34923. Hash-to-curve implementations must follow IETF draft-irtf-cfrg-hash-to-curve v1635024. Cross-chain signature verification must prevent chain ID replay using domain separation35125. ZK proof verification on-chain must check all public inputs against contract state352353## Implementation Examples354355### ECDSA Signing (Rust — libsecp256k1)356```rust357use secp256k1::{Secp256k1, Message, SecretKey, PublicKey, Signature};358use sha3::{Keccak256, Digest};359360fn sign_message(secret_key_bytes: &[u8; 32], message_bytes: &[u8]) -> Result<Vec<u8>, Error> {361 let secp = Secp256k1::new();362 let secret_key = SecretKey::from_slice(secret_key_bytes)?;363 let message = Message::from_slice(&Keccak256::digest(message_bytes))?;364365 // Deterministic nonce per RFC 6979 (handled by libsecp256k1)366 let signature: Signature = secp.sign_ecdsa(&message, &secret_key);367368 // Serialize as 65-byte [r || s || v] (Ethereum format)369 let mut serialized = signature.serialize_compact().to_vec();370 let rec_id = signature.serialize_der(); // recoverable signature371 serialized.push(rec_id[0]); // v = 27/28 or 35+chain_id*2372373 Ok(serialized)374}375376fn verify_signature(377 public_key_bytes: &[u8; 64], // uncompressed x || y378 message_bytes: &[u8],379 signature_bytes: &[u8; 65], // r || s || v380) -> Result<bool, Error> {381 let secp = Secp256k1::new();382 let public_key = PublicKey::from_slice(&[0x04; public_key_bytes].concat())?;383 let message = Message::from_slice(&Keccak256::digest(message_bytes))?;384 let signature = Signature::from_compact(&signature_bytes[..64])?;385386 // Additionally: verify low-s form (BIP-62/BIP-146)387 // Verify s <= n/2 (curve order / 2)388 let s = signature.serialize_compact()[32..64].to_vec();389 let n = "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141";390391 Ok(secp.verify_ecdsa(&message, &signature, &public_key).is_ok())392}393```394395### BLS Signature Aggregation (Rust — blst)396```rust397use blst::min_pk::*;398399fn aggregate_and_verify(400 public_keys: &[PublicKey],401 message: &[u8],402 signatures: &[Signature],403) -> bool {404 // Step 1: Verify proof of possession for each public key405 for pk in public_keys {406 let pop = pk.sign_pop(); // PoP is required for rogue-key defense407 if !pk.verify_pop(&pop) {408 return false;409 }410 }411412 // Step 2: Aggregate public keys and signatures413 let aggregated_pk: AggregatePublicKey = AggregatePublicKey::aggregate(public_keys, false);414 let aggregated_sig: AggregateSignature = AggregateSignature::aggregate(signatures, false);415416 // Step 3: Fast aggregate verification417 // This is ~10x faster than verifying N signatures individually418 aggregated_sig.verify(true, message, &[], &aggregated_pk.to_public_key(), false)419}420```421422### Merkle Proof Verification (Solidity)423```solidity424contract MerkleVerifier {425 // Verify a Merkle inclusion proof426 // leaf: hash of leaf data427 // merkleRoot: expected root428 // proof: sibling hashes from leaf to root429 // flags: bitmask indicating left (0) or right (1) position per level430 function verify(431 bytes32 leaf,432 bytes32 merkleRoot,433 bytes32[] calldata proof,434 uint256 flags435 ) external pure returns (bool) {436 bytes32 computed = leaf;437438 for (uint256 i = 0; i < proof.length; i++) {439 if ((flags >> i) & 1 == 0) {440 // Sibling is on the right: hash(left || right)441 computed = keccak256(abi.encodePacked(computed, proof[i]));442 } else {443 // Sibling is on the left: hash(sibling || computed)444 computed = keccak256(abi.encodePacked(proof[i], computed));445 }446 }447448 return computed == merkleRoot;449 }450}451```452453### EIP-712 Typed Data Signing (TypeScript + Solidity)454```typescript455// Off-chain signing (TypeScript — viem + ethers)456const domain = {457 name: "MyProtocol",458 version: "1",459 chainId: 1,460 verifyingContract: "0x1234..." as const,461};462463const types = {464 Transfer: [465 { name: "to", type: "address" },466 { name: "amount", type: "uint256" },467 { name: "nonce", type: "uint256" },468 { name: "deadline", type: "uint256" },469 ],470};471472const message = {473 to: "0x5678...",474 amount: 100n,475 nonce: 0n,476 deadline: 1700000000n,477};478479// Sign with wallet480const signature = await wallet.signTypedData(domain, types, message);481```482483```solidity484// On-chain verification (Solidity)485contract EIP712Verifier is EIP712 {486 bytes32 private constant TRANSFER_TYPEHASH = keccak256(487 "Transfer(address to,uint256 amount,uint256 nonce,uint256 deadline)"488 );489490 mapping(address => mapping(uint256 => bool)) public usedNonces;491492 function executeTransfer(493 address to,494 uint256 amount,495 uint256 nonce,496 uint256 deadline,497 bytes calldata signature498 ) external {499 require(block.timestamp <= deadline, "Signature expired");500 require(!usedNonces[msg.sender][nonce], "Nonce used");501502 bytes32 structHash = keccak256(503 abi.encode(TRANSFER_TYPEHASH, to, amount, nonce, deadline)504 );505 bytes32 digest = _hashTypedDataV4(structHash);506507 address signer = ECDSA.recover(digest, signature);508 require(signer == msg.sender, "Invalid signer");509510 usedNonces[msg.sender][nonce] = true;511 // Execute transfer...512 }513}514```515516### Hash-to-Curve (BLS12-381 — Rust)517```rust518use blst::*;519use sha2::{Sha256, Digest};520521fn hash_to_curve(message: &[u8], dst: &[u8]) -> Result<Vec<u8>, String> {522 // IETF hash-to-curve (draft-irtf-cfrg-hash-to-curve v16)523 // Domain separation tag MUST be unique per protocol context524 let point = blst_p1_hash_to::hash_to(message, dst, &[]);525526 // Compressed form: 48 bytes for BLS12-381 G1527 let mut compressed = [0u8; 48];528 point.compress(&mut compressed);529 Ok(compressed.to_vec())530}531532// Example DST usage:533// Nonce signature DST: "BLS_SIG_BLS12381G2_XMD:SHA-256_SSWU_RO_POP_"534// Proof of possession DST: "BLS_POP_BLS12381G2_XMD:SHA-256_SSWU_RO_POP_"535```536537### BIP-32 HD Wallet Derivation (TypeScript)538```typescript539import { secp256k1 } from '@noble/curves/secp256k1';540import { hmac } from '@noble/hashes/hmac';541import { sha512 } from '@noble/hashes/sha512';542543interface HDKey {544 privateKey?: Uint8Array;545 publicKey: Uint8Array;546 chainCode: Uint8Array;547 depth: number;548 index: number;549 parentFingerprint: number;550}551552function ckdPriv(parent: HDKey, index: number): HDKey {553 const isHardened = index >= 0x80000000;554555 // Hardened: serP(parent.publicKey) || ser32(index)556 // Non-hardened: serP(parent.publicKey) || ser32(index)557 const data = isHardened558 ? new Uint8Array([0x00, ...parent.privateKey!, ...toBytes32(index)])559 : new Uint8Array([...parent.publicKey, ...toBytes32(index)]);560561 const I = hmac(sha512, parent.chainCode, data);562 const IL = I.slice(0, 32);563 const IR = I.slice(32, 64);564565 // IL + parent private key (mod n)566 const childPriv = secp256k1.utils.addPrivateKeys(567 hexlify(parent.privateKey!),568 hexlify(IL)569 );570571 return {572 privateKey: hexToBytes(childPriv),573 publicKey: secp256k1.getPublicKey(childPriv, true),574 chainCode: IR,575 depth: parent.depth + 1,576 index,577 parentFingerprint: fingerprint(parent.publicKey),578 };579}580581// Derivation path: m/44'/60'/0'/0/0 (Ethereum account)582function derivePath(master: HDKey, path: string): HDKey {583 const parts = path.replace(/^m\//, '').split('/');584 let key = master;585 for (const part of parts) {586 const isHardened = part.endsWith("'");587 const index = parseInt(part) + (isHardened ? 0x80000000 : 0);588 key = ckdPriv(key, index);589 }590 return key;591}592```593594### Post-Quantum Migration Path Strategy595```596Phase 1 (2024-2026): Hybrid signatures597 - Combine ECDSA + Dilithium in transaction authentication598 - Both signatures must validate for the transaction to be valid599 - Library: liboqs (C/Rust), pqcrypto-dilithium (Rust)600601Phase 2 (2027-2032): NIST PQC standardization602 - CRYSTALS-Dilithium for general signatures (balanced size/speed)603 - FALCON for compact signatures (smaller proofs, slower verification)604 - SPHINCS+ for stateless hash-based (largest, but most trusted)605606Phase 3 (2032+): Full quantum transition607 - Longer blocks (PQC signatures: 2-5KB vs 64-96 bytes classical)608 - Different UTXO/lock script models for quantum-safe addresses609 - Merkle-tree-based signature aggregation (reduce per-tx overhead)610611Key concern: Harvest now, decrypt later attacks612 - Encrypting on-chain data that will be decrypted with quantum computers613 - High-value contracts (bridges, DAO treasuries) should use hybrid encryption614```615616## References617- references/blockchain-cryptography-advanced.md — Blockchain Cryptography Advanced Topics618- references/blockchain-cryptography-fundamentals.md — Blockchain Cryptography Fundamentals619- references/elliptic-curve-crypto.md — Elliptic Curve Cryptography for Blockchain620- references/hash-functions.md — Hash Functions in Blockchain621- references/key-derivation-management.md — Key Derivation and Management622- references/merkle-trees.md — Merkle Trees in Blockchain623- references/pairing-based-cryptography.md — Pairing-Based Cryptography624- references/post-quantum-blockchain-crypto.md — Post-Quantum Blockchain Cryptography625- references/signature-schemes.md — Signature Schemes in Blockchain626- references/zero-knowledge-deep.md — Zero-Knowledge Proofs in Blockchain627628## Handoff629blockchain-cryptography → blockchain-core (for protocol-level crypto integration)630blockchain-cryptography → blockchain-security (for cryptographic audit methodology)631blockchain-cryptography → blockchain-application (for zk-proof integration in contracts)