cardano-crypto 1.0.8

Pure Rust implementation of Cardano cryptographic primitives (VRF, KES, DSIGN, Hash) with 100% compatibility with cardano-node
Documentation
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
//! Verifiable Random Functions (VRF)
//!
//! This module provides VRF implementations following IETF specifications:
//! - **Draft-03** (ECVRF-ED25519-SHA512-Elligator2) - 80-byte proofs, Cardano standard
//! - **Draft-13** (ECVRF-ED25519-SHA512-TAI) - 128-byte proofs, batch-compatible
//!
//! Both variants maintain byte-level compatibility with Cardano's libsodium VRF implementation.
//!
//! # Examples
//!
//! ## VRF Draft-03 (Cardano Standard)
//!
//! ```
//! use cardano_crypto::vrf::VrfDraft03;
//!
//! // Generate keypair
//! let seed = [42u8; 32];
//! let (secret_key, public_key) = VrfDraft03::keypair_from_seed(&seed);
//!
//! // Prove
//! let message = b"Cardano block slot 12345";
//! let proof = VrfDraft03::prove(&secret_key, message).unwrap();
//!
//! // Verify and get output
//! let output = VrfDraft03::verify(&public_key, &proof, message).unwrap();
//! assert_eq!(output.len(), 64);
//! ```
//!
//! ## VRF Draft-13
//!
//! ```
//! use cardano_crypto::vrf::VrfDraft13;
//!
//! let seed = [42u8; 32];
//! let (secret_key, public_key) = VrfDraft13::keypair_from_seed(&seed);
//!
//! let message = b"Random seed input";
//! let proof = VrfDraft13::prove(&secret_key, message).unwrap();
//! let output = VrfDraft13::verify(&public_key, &proof, message).unwrap();
//! ```

#[cfg(feature = "alloc")]
use alloc::{format, vec::Vec};

pub mod cardano_compat;
pub mod draft03;
pub mod draft13;
pub mod test_vectors;

// Re-export main types
pub use draft03::{
    VrfDraft03, OUTPUT_SIZE, PROOF_SIZE as DRAFT03_PROOF_SIZE, PUBLIC_KEY_SIZE, SECRET_KEY_SIZE,
    SEED_SIZE,
};

pub use draft13::{VrfDraft13, PROOF_SIZE as DRAFT13_PROOF_SIZE};

// Re-export Cardano compatibility functions for advanced usage
pub use cardano_compat::{
    cardano_clear_cofactor, cardano_hash_to_curve, cardano_vrf_prove, cardano_vrf_verify,
};

// ============================================================================
// VRF Algorithm trait (matching Cardano's VRFAlgorithm class)
// ============================================================================

/// Trait for VRF algorithms
///
/// This trait provides a unified interface for VRF implementations,
/// matching the structure of Cardano's `VRFAlgorithm` type class.
///
/// # Associated Types
///
/// - `SecretKey`: VRF secret key type
/// - `VerificationKey`: VRF public key type
/// - `Proof`: VRF proof type
/// - `Output`: VRF output type (hash)
///
/// # Example
///
/// ```
/// use cardano_crypto::vrf::{VrfAlgorithm, VrfDraft03};
/// use cardano_crypto::hash::{Blake2b256, HashAlgorithm};
///
/// let seed = [42u8; 32];
/// let (sk, vk) = VrfDraft03::keypair_from_seed(&seed);
///
/// // Hash the verification key
/// let vk_hash = VrfDraft03::hash_verification_key::<Blake2b256>(&vk);
/// assert_eq!(vk_hash.len(), 32);
/// ```
pub trait VrfAlgorithm: Clone + Send + Sync + 'static {
    /// Secret key type
    type SecretKey;
    /// Verification key type
    type VerificationKey;
    /// Proof type
    type Proof;
    /// Output type
    type Output;

    /// Algorithm name
    const ALGORITHM_NAME: &'static str;
    /// Seed size in bytes
    const SEED_SIZE: usize;
    /// Secret key size in bytes
    const SECRET_KEY_SIZE: usize;
    /// Verification key size in bytes
    const VERIFICATION_KEY_SIZE: usize;
    /// Proof size in bytes
    const PROOF_SIZE: usize;
    /// Output size in bytes
    const OUTPUT_SIZE: usize;

    /// Generate keypair from seed
    fn keypair_from_seed(seed: &[u8; 32]) -> (Self::SecretKey, Self::VerificationKey);

    /// Derive verification key from secret key
    fn derive_verification_key(sk: &Self::SecretKey) -> Self::VerificationKey;

    /// Generate a VRF proof
    fn prove(sk: &Self::SecretKey, message: &[u8]) -> crate::common::CryptoResult<Self::Proof>;

    /// Verify a VRF proof and return the output
    fn verify(
        vk: &Self::VerificationKey,
        proof: &Self::Proof,
        message: &[u8],
    ) -> crate::common::CryptoResult<Self::Output>;

    /// Convert proof to output hash directly (without verification)
    fn proof_to_hash(proof: &Self::Proof) -> crate::common::CryptoResult<Self::Output>;

    /// Serialize verification key to raw bytes
    fn raw_serialize_verification_key(vk: &Self::VerificationKey) -> &[u8];

    /// Deserialize verification key from raw bytes
    fn raw_deserialize_verification_key(bytes: &[u8]) -> Option<Self::VerificationKey>;

    /// Serialize proof to raw bytes
    fn raw_serialize_proof(proof: &Self::Proof) -> &[u8];

    /// Deserialize proof from raw bytes
    fn raw_deserialize_proof(bytes: &[u8]) -> Option<Self::Proof>;

    /// Hash a verification key
    ///
    /// This corresponds to `hashVerKeyVRF` in cardano-base.
    ///
    /// # Type Parameters
    ///
    /// - `H`: The hash algorithm to use
    #[cfg(feature = "alloc")]
    fn hash_verification_key<H: crate::hash::HashAlgorithm>(vk: &Self::VerificationKey) -> Vec<u8> {
        let raw = Self::raw_serialize_verification_key(vk);
        H::hash(raw)
    }
}

// ============================================================================
// OutputVRF - VRF output wrapper matching Cardano's OutputVRF
// ============================================================================

/// VRF output wrapper
///
/// Matches Cardano's `OutputVRF v` type from cardano-crypto-class.
/// The output is the result of a VRF evaluation and can be converted
/// to a natural number for use in leader election.
///
/// # Examples
///
/// ```
/// use cardano_crypto::vrf::{VrfDraft03, OutputVrf};
///
/// let seed = [42u8; 32];
/// let (secret_key, public_key) = VrfDraft03::keypair_from_seed(&seed);
/// let message = b"test";
/// let proof = VrfDraft03::prove(&secret_key, message).unwrap();
/// let output_bytes = VrfDraft03::verify(&public_key, &proof, message).unwrap();
///
/// let output = OutputVrf::new(output_bytes);
/// assert_eq!(output.as_bytes().len(), 64);
/// ```
#[derive(Clone, PartialEq, Eq)]
pub struct OutputVrf([u8; OUTPUT_SIZE]);

impl core::fmt::Debug for OutputVrf {
    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
        write!(f, "OutputVrf(<{} bytes>)", self.0.len())
    }
}

impl OutputVrf {
    /// Create an OutputVrf from raw bytes
    pub fn new(bytes: [u8; OUTPUT_SIZE]) -> Self {
        Self(bytes)
    }

    /// Create from a slice (returns None if wrong length)
    pub fn from_slice(bytes: &[u8]) -> Option<Self> {
        if bytes.len() != OUTPUT_SIZE {
            return None;
        }
        let mut arr = [0u8; OUTPUT_SIZE];
        arr.copy_from_slice(bytes);
        Some(Self(arr))
    }

    /// Get the raw output bytes
    pub fn as_bytes(&self) -> &[u8; OUTPUT_SIZE] {
        &self.0
    }

    /// Convert VRF output to a natural number (big-endian)
    ///
    /// This matches Cardano's `getOutputVRFNatural` function used in
    /// leader election to compare against the stake threshold.
    ///
    /// # Example
    ///
    /// ```
    /// use cardano_crypto::vrf::OutputVrf;
    ///
    /// let output = OutputVrf::new([0u8; 64]);
    /// let natural = output.to_natural();
    /// // natural is a big integer representation
    /// ```
    #[cfg(feature = "alloc")]
    pub fn to_natural(&self) -> alloc::vec::Vec<u8> {
        // Return bytes in big-endian order (already in big-endian from SHA-512)
        self.0.to_vec()
    }

    /// Convert to u128 (truncated, using first 16 bytes)
    ///
    /// Useful for quick comparisons where full precision isn't needed.
    pub fn to_u128(&self) -> u128 {
        let mut bytes = [0u8; 16];
        bytes.copy_from_slice(&self.0[..16]);
        u128::from_be_bytes(bytes)
    }
}

// ============================================================================
// CertifiedVRF - VRF output with proof (certificate)
// ============================================================================

/// A VRF output certified by its proof
///
/// Matches Cardano's `CertifiedVRF v a` type from cardano-crypto-class.
/// Bundles the VRF output with its proof (certificate) for verification.
///
/// # Examples
///
/// ```
/// use cardano_crypto::vrf::{VrfDraft03, CertifiedVrf};
///
/// let seed = [42u8; 32];
/// let (secret_key, public_key) = VrfDraft03::keypair_from_seed(&seed);
/// let message = b"test input";
///
/// // Generate certified VRF output
/// let certified = CertifiedVrf::eval(&secret_key, message).unwrap();
///
/// // Verify the certified output
/// assert!(certified.verify(&public_key, message).is_ok());
/// ```
#[derive(Clone, PartialEq, Eq)]
pub struct CertifiedVrf {
    /// The VRF output (hash)
    pub output: OutputVrf,
    /// The VRF proof (certificate)
    pub proof: [u8; DRAFT03_PROOF_SIZE],
}

impl core::fmt::Debug for CertifiedVrf {
    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
        f.debug_struct("CertifiedVrf")
            .field("output", &self.output)
            .field("proof", &format!("<{} bytes>", self.proof.len()))
            .finish()
    }
}

impl CertifiedVrf {
    /// Evaluate VRF and return certified output
    ///
    /// This corresponds to `evalCertified` in cardano-crypto-class.
    ///
    /// # Parameters
    ///
    /// * `secret_key` - The VRF secret key (64 bytes)
    /// * `message` - The input message to hash
    ///
    /// # Returns
    ///
    /// A `CertifiedVrf` containing both the output and proof
    pub fn eval(
        secret_key: &[u8; SECRET_KEY_SIZE],
        message: &[u8],
    ) -> crate::common::CryptoResult<Self> {
        let proof = VrfDraft03::prove(secret_key, message)?;
        let output_bytes = VrfDraft03::proof_to_hash(&proof)?;

        Ok(Self {
            output: OutputVrf::new(output_bytes),
            proof,
        })
    }

    /// Verify the certified VRF output
    ///
    /// This corresponds to `verifyCertified` in cardano-crypto-class.
    ///
    /// # Parameters
    ///
    /// * `public_key` - The VRF public key
    /// * `message` - The original input message
    ///
    /// # Returns
    ///
    /// * `Ok(())` if verification succeeds
    /// * `Err(...)` if verification fails
    pub fn verify(
        &self,
        public_key: &[u8; PUBLIC_KEY_SIZE],
        message: &[u8],
    ) -> crate::common::CryptoResult<()> {
        let output = VrfDraft03::verify(public_key, &self.proof, message)?;

        if output != *self.output.as_bytes() {
            return Err(crate::common::CryptoError::VerificationFailed);
        }

        Ok(())
    }

    /// Get the VRF output
    pub fn get_output(&self) -> &OutputVrf {
        &self.output
    }

    /// Get the VRF proof (certificate)
    pub fn get_proof(&self) -> &[u8; DRAFT03_PROOF_SIZE] {
        &self.proof
    }
}

// ============================================================================
// Cardano-node compatible type aliases
// ============================================================================

/// VRF signing key type (matches cardano-node's `VrfSigningKey`)
///
/// This is a 64-byte array containing the seed and public key.
pub type VrfSigningKey = [u8; SECRET_KEY_SIZE];

/// VRF verification key type (matches cardano-node's `VrfVerificationKey`)
///
/// This is a 32-byte compressed Edwards curve point.
pub type VrfVerificationKey = [u8; PUBLIC_KEY_SIZE];

/// VRF proof type
///
/// This is an 80-byte proof for Draft-03.
pub type VrfProof = [u8; DRAFT03_PROOF_SIZE];

/// VRF key pair (matches cardano-node's `KeyPair VrfKey`)
///
/// Contains both the signing key and verification key.
///
/// # Example
///
/// ```
/// use cardano_crypto::vrf::{VrfDraft03, VrfKeyPair};
///
/// let seed = [42u8; 32];
/// let keypair = VrfKeyPair::generate(&seed);
///
/// let message = b"test";
/// let proof = VrfDraft03::prove(&keypair.signing_key, message).unwrap();
/// let output = VrfDraft03::verify(&keypair.verification_key, &proof, message).unwrap();
/// ```
#[derive(Clone, PartialEq, Eq)]
pub struct VrfKeyPair {
    /// The VRF signing (secret) key
    pub signing_key: VrfSigningKey,
    /// The VRF verification (public) key
    pub verification_key: VrfVerificationKey,
}

impl core::fmt::Debug for VrfKeyPair {
    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
        f.debug_struct("VrfKeyPair")
            .field("signing_key", &"<redacted>")
            .field(
                "verification_key",
                &format!("<{} bytes>", self.verification_key.len()),
            )
            .finish()
    }
}

impl VrfKeyPair {
    /// Generate a VRF key pair from a seed
    pub fn generate(seed: &[u8; SEED_SIZE]) -> Self {
        let (signing_key, verification_key) = VrfDraft03::keypair_from_seed(seed);
        Self {
            signing_key,
            verification_key,
        }
    }

    /// Create from existing keys
    pub fn from_keys(signing_key: VrfSigningKey, verification_key: VrfVerificationKey) -> Self {
        Self {
            signing_key,
            verification_key,
        }
    }
}

// ============================================================================
// CBOR Trait Implementations for VRF Types
// ============================================================================

#[cfg(feature = "cbor")]
mod cbor_impl {
    use super::*;
    use crate::cbor::{
        decode_bytes, encode_bytes, encoded_size_bytes, CborError, FromCbor, ToCbor,
    };

    impl ToCbor for OutputVrf {
        #[cfg(feature = "alloc")]
        fn to_cbor(&self) -> Vec<u8> {
            encode_bytes(&self.0)
        }

        fn encoded_size(&self) -> usize {
            encoded_size_bytes(OUTPUT_SIZE)
        }
    }

    impl FromCbor for OutputVrf {
        fn from_cbor(bytes: &[u8]) -> Result<Self, CborError> {
            let decoded = decode_bytes(bytes)?;
            Self::from_slice(&decoded).ok_or(CborError::InvalidLength)
        }
    }

    impl ToCbor for CertifiedVrf {
        #[cfg(feature = "alloc")]
        fn to_cbor(&self) -> Vec<u8> {
            // Encode as CBOR bytes containing the proof
            // The output can be recomputed from the proof
            encode_bytes(&self.proof)
        }

        fn encoded_size(&self) -> usize {
            encoded_size_bytes(DRAFT03_PROOF_SIZE)
        }
    }

    impl FromCbor for CertifiedVrf {
        fn from_cbor(bytes: &[u8]) -> Result<Self, CborError> {
            let decoded = decode_bytes(bytes)?;
            if decoded.len() != DRAFT03_PROOF_SIZE {
                return Err(CborError::InvalidLength);
            }
            let mut proof = [0u8; DRAFT03_PROOF_SIZE];
            proof.copy_from_slice(&decoded);

            // Compute output from proof
            let output_bytes =
                VrfDraft03::proof_to_hash(&proof).map_err(|_| CborError::DeserializationFailed)?;

            Ok(Self {
                output: OutputVrf::new(output_bytes),
                proof,
            })
        }
    }

    // Note: VrfVerificationKey, VrfSigningKey, and VrfProof are type aliases for [u8; N],
    // so they use the implementations in cbor/mod.rs for [u8; 32], [u8; 64], and [u8; 80].
}