goldilocks-crypto
⚠️ Security Warning This crate has not been audited. Do not use in production without a professional security review. Use at your own risk.
Rust implementation of ECgFp5 Schnorr signatures over the Goldilocks field — designed for ZK-friendly on-chain signature verification.
Algorithm Parameters
| Parameter | Value | Source |
|---|---|---|
| Base field | Goldilocks, p = 2⁶⁴ − 2³² + 1 |
Goldilocks prime |
| Curve | ECgFp5 — y² = x³ + 2x + 263 over GF(p⁵) |
github.com/pornin/ecgfp5 |
| Scalar field order | ≈ 2²⁵⁴ (256-bit, 4×64-bit limbs) |
ECgFp5 spec |
| Hash-to-scalar | Poseidon2 (width 12, 8 full + 22 partial rounds) | eprint.iacr.org/2023/323 |
| Signature scheme | Schnorr | — |
| Key size | 40 bytes (private), 40 bytes (public) | — |
| Signature size | 80 bytes | — |
API
| Item | Kind | Description |
|---|---|---|
ScalarField |
struct | 256-bit scalar (private key / nonce) |
Point |
struct | ECgFp5 curve point (projective coords) |
AffinePoint |
struct | ECgFp5 curve point (affine coords) |
Signature |
struct | 80-byte Schnorr signature |
KeyPair |
struct | Ergonomic keypair with sign/verify methods |
sign(sk, msg) |
fn | Sign a 40-byte message with a private key |
verify_signature(sig, msg, pk) |
fn | Verify a signature against a public key |
batch_verify(sigs, msgs, pks) |
fn | Verify multiple signatures sequentially |
validate_public_key(pk) |
fn | Check that bytes represent a valid curve point |
Usage
Add to Cargo.toml:
[]
= "0.1"
Key generation
use ;
// Random private key (cryptographically secure)
let private_key = sample_crypto;
let sk_bytes = private_key.to_bytes_le; // [u8; 40]
// Derive public key
let public_key = generator.mul;
let pk_bytes = public_key.encode.to_bytes_le; // [u8; 40]
Sign and verify
use ;
// Message must consist of canonical Goldilocks field elements
let message = ;
let signature = sign.unwrap; // Vec<u8> (80 bytes)
let is_valid = verify_signature.unwrap;
assert!;
Ergonomic KeyPair API
use KeyPair;
let kp = generate;
let msg = ;
let sig = kp.sign.unwrap;
let is_valid = kp.verify.unwrap;
assert!;
Batch verification
use batch_verify;
// signatures: Vec<Vec<u8>>, messages: Vec<[u8;40]>, public_keys: Vec<[u8;40]>
let all_valid = batch_verify.unwrap;
Dependencies
poseidon-hash— Goldilocks field, Poseidon2 hash, Fp5 extension fieldzeroize— private key material is zeroed on dropsubtle— constant-time comparisons
License
Licensed under either of Apache-2.0 or MIT at your option.