brainstorming
brainstorming
You MUST use this before any creative work - creating features, building components, adding functionality, modifying behavior, or planning anything new, in software or out of it (a talk, a business, a renovation).
blockchain-cryptographyUse 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…
Independent GitHub snapshot · Automated classification · Original documentation governs
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.
"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"
Cryptographic architecture specification including:
4000 tokens
| 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 |
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)
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)
| 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 |
m/44'/coin'/account'/change/indexm/86'/coin'/account'/change/indexwithdraw prefix)ecrecover precompile over custom Solidity ECDSAeth_sign)verify_batch (batched scalar multiplication)| 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) |
| 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 | 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) |
| 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 |
ecrecover + ecrecover matchr valuesuse 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())
}
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)
}
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;
}
}
// 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...
}
}
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_"
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;
}
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
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)