Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

62 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Pyde logo

pyde-crypto

The cryptography that keeps Pyde secure.


pyde-crypto is the cryptography crate underlying Pyde, a post-quantum, MEV-resistant Layer 1 blockchain. It ships the core primitives the chain signs and hashes with: FALCON-512 signatures and Poseidon2 hashing over the Goldilocks field, plus the Hash256 output type shared across both.

Pyde's front-running defense is a keyless commit-reveal scheme implemented in the node — senders publish a hash commitment first and the plaintext transaction second — built on the FALCON signatures and hashing this crate provides. There is no threshold-decryption or trusted-committee key material anywhere in the crate.

The crate has no elliptic-curve dependencies anywhere in its API surface and is no_std + alloc, so it can be embedded in WASM, embedded hardware, and any environment that doesn't ship a libc. It contains no first-party unsafe code.

You can use it standalone for any Rust project that needs post-quantum signatures or a ZK-friendly algebraic hash — it does not require running a Pyde node, doesn't pull in a network stack, and doesn't open any I/O.

Table of contents

Install

[dependencies]
pyde-crypto = "0.1.0-testnet.1"

Or as a path dependency during development, when the crate lives alongside its consumers in a polyrepo layout:

[dependencies]
pyde-crypto = { path = "../pyde-crypto" }

no_std + alloc is supported out of the box — default-features are already off-by-design.

Quickstart

use pyde_crypto::falcon::{falcon_keygen, falcon_sign, falcon_verify};
use pyde_crypto::poseidon2::poseidon2_hash;

// FALCON-512 signature. keygen and sign return `Result` (the lattice
// sampler can fail on bad entropy), so unwrap or propagate.
let (pk, sk) = falcon_keygen().expect("keygen");
let msg = b"hello pyde";
let sig = falcon_sign(&sk, msg).expect("sign");
assert!(falcon_verify(&pk, msg, &sig));

// Poseidon2 hash (ZK-circuit-friendly, Goldilocks field, 256-bit output)
let digest = poseidon2_hash(msg);

That's the working surface for nearly every consumer.

Modules

falcon — signatures

Type: FALCON-512 (FN-DSA-512, the FIPS 206 draft), an NTRU-lattice post-quantum signature scheme. ~666-byte signatures (average), 897-byte public keys, 1281-byte secret keys.

Use for: every user transaction, every consensus vertex, every state-root attestation, every beacon signature, the commit-reveal front-running defense, and every peer-handshake binding.

use pyde_crypto::falcon::{
    FalconPublicKey, FalconSecretKey, FalconSignature,
    falcon_keygen, falcon_sign, falcon_verify, falcon_verify_all,
};

let (pk, sk) = falcon_keygen().expect("keygen");
let sig = falcon_sign(&sk, b"msg").expect("sign");
assert!(falcon_verify(&pk, b"msg", &sig));

// Verify a list of signatures. This is a short-circuiting `forall`
// over `falcon_verify` — NOT an algebraic batch scheme that amortizes
// work across signatures. Algebraic batching is post-mainnet hardening.
let items: Vec<(&FalconPublicKey, &[u8], &FalconSignature)> =
    vec![(&pk, b"msg" as &[u8], &sig)];
assert!(falcon_verify_all(&items));

Determinism: signing is deterministic. The Gaussian sampler is seeded from the message plus a domain-separation tag (b"pyde-falcon-v1"), so the same (sk, msg) always produces the same sig.

Secret-key zeroization: FalconSecretKey derives Zeroize + ZeroizeOnDrop. Cloning preserves zeroization (each clone independently zeros on its own drop).

poseidon2 — algebraic hash

Type: Poseidon2 sponge over the Goldilocks field (p = 2^64 − 2^32 + 1). 8-element state, 4-element rate, 8 external + 22 internal rounds, x^7 S-box, 256-bit output.

Use for: state-root commitment, address derivation, contract storage-key derivation, transaction hashing, and the poseidon2 WASM host function. Roughly 1000× cheaper inside an algebraic constraint system than Keccak — so the right choice anywhere a hash might be exposed to a future ZK proof.

use pyde_crypto::poseidon2::{poseidon2_hash, poseidon2_pair, poseidon2_many};

let h  = poseidon2_hash(b"variable-length input");
let h2 = poseidon2_pair(h, h);              // Merkle-node-style
let h3 = poseidon2_many(&[h, h2]);          // sponge over a slice of hashes

Domain-separation by length-prefixing is built into the encoding — variable-length inputs cannot collide with fixed-length inputs.

hash — the Hash256 output type

Type: Hash256, a 32-byte hash-output newtype. This is the shared return type for poseidon2_* and the canonical 256-bit digest type used across Pyde's state and consensus code. It carries no hashing algorithm of its own — high-volume native Blake3 hashing lives in the node, which stores its results in this type.

use pyde_crypto::hash::Hash256;

let h = Hash256::from_slice(&[0u8; 32]).expect("exactly 32 bytes");
assert_eq!(h.to_bytes().len(), 32);
println!("{h}"); // 0x0000…0000

from_slice returns None for any length other than 32 — it never silently pads or truncates, so a malformed digest surfaces at the call site instead of comparing equal to a real hash by accident.

Security model

Key handling. FalconSecretKey derives Zeroize and ZeroizeOnDrop from the zeroize crate, so dropping a key overwrites the bytes in place rather than leaving them in deallocated heap pages where a later allocation, swap-to-disk page, or core dump could read them.

unsafe surface. This crate contains no first-party unsafe code. The only FFI lives inside the upstream falcon-rs and Plonky3 (p3-*) dependencies, behind their own safe APIs.

Domain separation. Every cross-cryptographic-context hash input is domain-separated by a string prefix (e.g., b"pyde-falcon-v1"), and poseidon2 length-prefixes variable-length inputs. Cross-context confusion attacks are blocked by construction.

Versioning + compatibility

  • Pre-1.0. API may change between minor releases.
  • falcon-rs and the Plonky3 (p3-*) crates are pre-1.0 upstreams; behaviour-changing patch bumps are guarded by the Known-Answer Tests in src/kat.rs, which pin (input, output) vectors for every primitive so a silent drift fails cargo test before shipping.
  • MSRV: recent stable Rust (no specific minimum pinned).

Performance

Order-of-magnitude figures on commodity x86_64 (Apple Silicon similar). These are illustrative; run cargo bench for numbers on your hardware.

Primitive Operation ~Time
FALCON-512 Verify ~80 μs
FALCON-512 Sign ~300 μs (key prep amortized over many signs)
Poseidon2 Hash (32 bytes) ~5 μs

Building, testing, benchmarking

cargo build
cargo build --release      # recommended for crypto

cargo test                 # unit tests + Known-Answer Tests

cargo bench                # poseidon2_bench, falcon_bench

Reproducible — the crate pins Cargo.lock for deterministic builds across machines, important for audit workflows.

Audit status

Pre-mainnet status: planned but not started. Pyde's launch plan commits to multiple external audits, of which this crate is one — specifically the post-quantum-cryptography pass.

Known constraints to surface to auditors:

  • falcon-rs and the Plonky3 crates are pre-1.0 upstreams.
  • falcon_verify_all is a sequential forall, not an algebraic batch verifier (algebraic batching is post-mainnet hardening).

Contributing

This crate is part of the Pyde project. Substantive, protocol-affecting changes are proposed through Pyde's improvement-proposal process; non-substantive changes (clippy fixes, test additions, doc improvements) are welcome via PR.

License

Apache-2.0. See LICENSE.

About

The cryptography that keeps Pyde secure.

Resources

Code of conduct

Contributing

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages