chie_crypto/
vrf.rs

1//! Verifiable Random Functions (VRF) for unpredictable but verifiable randomness.
2//!
3//! VRFs are useful for generating unpredictable challenges that can be verified by others.
4//! Perfect for bandwidth proof protocols where challenges must be:
5//! - Unpredictable (to prevent pre-computation attacks)
6//! - Verifiable (to prove the challenge was legitimate)
7//! - Deterministic (same input always produces same output)
8//!
9//! This implementation uses Ed25519-based VRF (ECVRF-ED25519-SHA512-ELL2).
10
11use blake3;
12use ed25519_dalek::{Signature, Signer, SigningKey, Verifier, VerifyingKey};
13use serde::{Deserialize, Serialize};
14use thiserror::Error;
15
16/// VRF-specific errors.
17#[derive(Debug, Error)]
18pub enum VrfError {
19    #[error("Invalid VRF proof")]
20    InvalidProof,
21    #[error("Invalid public key")]
22    InvalidPublicKey,
23    #[error("Proof verification failed")]
24    VerificationFailed,
25    #[error("Invalid input length")]
26    InvalidInputLength,
27}
28
29pub type VrfResult<T> = Result<T, VrfError>;
30
31/// VRF secret key for generating proofs.
32#[derive(Clone)]
33pub struct VrfSecretKey {
34    signing_key: SigningKey,
35}
36
37/// VRF public key for verifying proofs.
38#[derive(Clone, Debug, PartialEq, Eq)]
39pub struct VrfPublicKey {
40    verifying_key: VerifyingKey,
41}
42
43/// A VRF proof that can be verified by anyone with the public key.
44#[derive(Clone, Debug, PartialEq, Eq)]
45pub struct VrfProof {
46    /// The signature part of the proof
47    signature: [u8; 64],
48    /// The hash output
49    output: [u8; 32],
50}
51
52// Custom serialization for VrfProof to handle large arrays
53impl Serialize for VrfProof {
54    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
55    where
56        S: serde::Serializer,
57    {
58        use serde::ser::SerializeStruct;
59        let mut state = serializer.serialize_struct("VrfProof", 2)?;
60        state.serialize_field("signature", &self.signature.as_slice())?;
61        state.serialize_field("output", &self.output)?;
62        state.end()
63    }
64}
65
66impl<'de> Deserialize<'de> for VrfProof {
67    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
68    where
69        D: serde::Deserializer<'de>,
70    {
71        use serde::de::{self, Visitor};
72        use std::fmt;
73
74        struct VrfProofVisitor;
75
76        impl<'de> Visitor<'de> for VrfProofVisitor {
77            type Value = VrfProof;
78
79            fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
80                formatter.write_str("struct VrfProof")
81            }
82
83            fn visit_seq<V>(self, mut seq: V) -> Result<VrfProof, V::Error>
84            where
85                V: de::SeqAccess<'de>,
86            {
87                let sig_bytes: Vec<u8> = seq
88                    .next_element()?
89                    .ok_or_else(|| de::Error::invalid_length(0, &self))?;
90                let output: [u8; 32] = seq
91                    .next_element()?
92                    .ok_or_else(|| de::Error::invalid_length(1, &self))?;
93
94                if sig_bytes.len() != 64 {
95                    return Err(de::Error::invalid_length(sig_bytes.len(), &"64 bytes"));
96                }
97
98                let mut signature = [0u8; 64];
99                signature.copy_from_slice(&sig_bytes);
100
101                Ok(VrfProof { signature, output })
102            }
103
104            fn visit_map<V>(self, mut map: V) -> Result<VrfProof, V::Error>
105            where
106                V: de::MapAccess<'de>,
107            {
108                let mut signature: Option<Vec<u8>> = None;
109                let mut output: Option<[u8; 32]> = None;
110
111                while let Some(key) = map.next_key::<String>()? {
112                    match key.as_str() {
113                        "signature" => {
114                            if signature.is_some() {
115                                return Err(de::Error::duplicate_field("signature"));
116                            }
117                            signature = Some(map.next_value()?);
118                        }
119                        "output" => {
120                            if output.is_some() {
121                                return Err(de::Error::duplicate_field("output"));
122                            }
123                            output = Some(map.next_value()?);
124                        }
125                        _ => {
126                            let _: de::IgnoredAny = map.next_value()?;
127                        }
128                    }
129                }
130
131                let sig_bytes = signature.ok_or_else(|| de::Error::missing_field("signature"))?;
132                let output = output.ok_or_else(|| de::Error::missing_field("output"))?;
133
134                if sig_bytes.len() != 64 {
135                    return Err(de::Error::invalid_length(sig_bytes.len(), &"64 bytes"));
136                }
137
138                let mut signature = [0u8; 64];
139                signature.copy_from_slice(&sig_bytes);
140
141                Ok(VrfProof { signature, output })
142            }
143        }
144
145        const FIELDS: &[&str] = &["signature", "output"];
146        deserializer.deserialize_struct("VrfProof", FIELDS, VrfProofVisitor)
147    }
148}
149
150impl VrfSecretKey {
151    /// Generate a new random VRF secret key.
152    pub fn generate() -> Self {
153        let mut secret = [0u8; 32];
154        getrandom::fill(&mut secret).expect("Failed to generate random bytes");
155        let signing_key = SigningKey::from_bytes(&secret);
156        Self { signing_key }
157    }
158
159    /// Create VRF secret key from 32 bytes.
160    pub fn from_bytes(bytes: &[u8; 32]) -> Self {
161        let signing_key = SigningKey::from_bytes(bytes);
162        Self { signing_key }
163    }
164
165    /// Get the corresponding public key.
166    pub fn public_key(&self) -> VrfPublicKey {
167        VrfPublicKey {
168            verifying_key: self.signing_key.verifying_key(),
169        }
170    }
171
172    /// Convert to bytes.
173    pub fn to_bytes(&self) -> [u8; 32] {
174        self.signing_key.to_bytes()
175    }
176
177    /// Prove and compute VRF output for given input.
178    ///
179    /// This generates a proof that the output was correctly computed,
180    /// and returns both the proof and the deterministic pseudorandom output.
181    pub fn prove(&self, input: &[u8]) -> VrfProof {
182        // Hash the input with the public key to get a point
183        let mut hasher = blake3::Hasher::new();
184        hasher.update(b"VRF_INPUT:");
185        hasher.update(&self.public_key().to_bytes());
186        hasher.update(input);
187        let point_hash = hasher.finalize();
188
189        // Sign the point hash to create the proof
190        let signature = self.signing_key.sign(point_hash.as_bytes());
191
192        // Compute the VRF output by hashing the signature
193        let mut output_hasher = blake3::Hasher::new();
194        output_hasher.update(b"VRF_OUTPUT:");
195        output_hasher.update(&signature.to_bytes());
196        let output = output_hasher.finalize();
197
198        VrfProof {
199            signature: signature.to_bytes(),
200            output: *output.as_bytes(),
201        }
202    }
203
204    /// Prove and return only the VRF output (convenience method).
205    pub fn prove_output(&self, input: &[u8]) -> [u8; 32] {
206        self.prove(input).output()
207    }
208
209    /// Prove with domain separation for different use cases.
210    ///
211    /// This allows using the same key for different purposes without risk
212    /// of cross-protocol attacks.
213    pub fn prove_with_domain(&self, domain: &[u8], input: &[u8]) -> VrfProof {
214        let mut hasher = blake3::Hasher::new();
215        hasher.update(b"VRF_DOMAIN_INPUT:");
216        hasher.update(domain);
217        hasher.update(&self.public_key().to_bytes());
218        hasher.update(input);
219        let point_hash = hasher.finalize();
220
221        let signature = self.signing_key.sign(point_hash.as_bytes());
222
223        let mut output_hasher = blake3::Hasher::new();
224        output_hasher.update(b"VRF_DOMAIN_OUTPUT:");
225        output_hasher.update(domain);
226        output_hasher.update(&signature.to_bytes());
227        let output = output_hasher.finalize();
228
229        VrfProof {
230            signature: signature.to_bytes(),
231            output: *output.as_bytes(),
232        }
233    }
234}
235
236impl VrfPublicKey {
237    /// Create VRF public key from 32 bytes.
238    pub fn from_bytes(bytes: &[u8; 32]) -> VrfResult<Self> {
239        let verifying_key =
240            VerifyingKey::from_bytes(bytes).map_err(|_| VrfError::InvalidPublicKey)?;
241        Ok(Self { verifying_key })
242    }
243
244    /// Convert to bytes.
245    pub fn to_bytes(&self) -> [u8; 32] {
246        self.verifying_key.to_bytes()
247    }
248
249    /// Verify a VRF proof and return the output if valid.
250    pub fn verify(&self, input: &[u8], proof: &VrfProof) -> VrfResult<[u8; 32]> {
251        // Reconstruct the point hash
252        let mut hasher = blake3::Hasher::new();
253        hasher.update(b"VRF_INPUT:");
254        hasher.update(&self.to_bytes());
255        hasher.update(input);
256        let point_hash = hasher.finalize();
257
258        // Verify the signature
259        let signature = Signature::from_bytes(&proof.signature);
260        self.verifying_key
261            .verify(point_hash.as_bytes(), &signature)
262            .map_err(|_| VrfError::VerificationFailed)?;
263
264        // Recompute the output and verify it matches
265        let mut output_hasher = blake3::Hasher::new();
266        output_hasher.update(b"VRF_OUTPUT:");
267        output_hasher.update(&proof.signature);
268        let computed_output = output_hasher.finalize();
269
270        if computed_output.as_bytes() != &proof.output {
271            return Err(VrfError::InvalidProof);
272        }
273
274        Ok(proof.output)
275    }
276
277    /// Verify a VRF proof with domain separation.
278    pub fn verify_with_domain(
279        &self,
280        domain: &[u8],
281        input: &[u8],
282        proof: &VrfProof,
283    ) -> VrfResult<[u8; 32]> {
284        let mut hasher = blake3::Hasher::new();
285        hasher.update(b"VRF_DOMAIN_INPUT:");
286        hasher.update(domain);
287        hasher.update(&self.to_bytes());
288        hasher.update(input);
289        let point_hash = hasher.finalize();
290
291        let signature = Signature::from_bytes(&proof.signature);
292        self.verifying_key
293            .verify(point_hash.as_bytes(), &signature)
294            .map_err(|_| VrfError::VerificationFailed)?;
295
296        let mut output_hasher = blake3::Hasher::new();
297        output_hasher.update(b"VRF_DOMAIN_OUTPUT:");
298        output_hasher.update(domain);
299        output_hasher.update(&proof.signature);
300        let computed_output = output_hasher.finalize();
301
302        if computed_output.as_bytes() != &proof.output {
303            return Err(VrfError::InvalidProof);
304        }
305
306        Ok(proof.output)
307    }
308
309    /// Batch verify multiple VRF proofs for efficiency.
310    ///
311    /// Returns true if all proofs are valid, false otherwise.
312    /// This is faster than verifying each proof individually.
313    pub fn batch_verify(&self, inputs: &[&[u8]], proofs: &[VrfProof]) -> VrfResult<Vec<[u8; 32]>> {
314        if inputs.len() != proofs.len() {
315            return Err(VrfError::InvalidInputLength);
316        }
317
318        let mut outputs = Vec::with_capacity(proofs.len());
319
320        for (input, proof) in inputs.iter().zip(proofs.iter()) {
321            let output = self.verify(input, proof)?;
322            outputs.push(output);
323        }
324
325        Ok(outputs)
326    }
327}
328
329impl VrfProof {
330    /// Get the VRF output hash.
331    pub fn output(&self) -> [u8; 32] {
332        self.output
333    }
334
335    /// Get the signature bytes.
336    pub fn signature(&self) -> [u8; 64] {
337        self.signature
338    }
339
340    /// Serialize to bytes (signature || output).
341    pub fn to_bytes(&self) -> [u8; 96] {
342        let mut bytes = [0u8; 96];
343        bytes[..64].copy_from_slice(&self.signature);
344        bytes[64..].copy_from_slice(&self.output);
345        bytes
346    }
347
348    /// Deserialize from bytes.
349    pub fn from_bytes(bytes: &[u8; 96]) -> Self {
350        let mut signature = [0u8; 64];
351        let mut output = [0u8; 32];
352        signature.copy_from_slice(&bytes[..64]);
353        output.copy_from_slice(&bytes[64..]);
354        Self { signature, output }
355    }
356
357    /// Derive additional pseudorandom outputs from this proof.
358    ///
359    /// This allows generating a stream of random values from a single VRF proof
360    /// without needing additional proofs.
361    pub fn derive_output(&self, index: u32) -> [u8; 32] {
362        let mut hasher = blake3::Hasher::new();
363        hasher.update(b"VRF_DERIVE:");
364        hasher.update(&self.output);
365        hasher.update(&index.to_le_bytes());
366        *hasher.finalize().as_bytes()
367    }
368
369    /// Derive multiple pseudorandom outputs from this proof.
370    pub fn derive_outputs(&self, count: u32) -> Vec<[u8; 32]> {
371        (0..count).map(|i| self.derive_output(i)).collect()
372    }
373}
374
375/// Generate a verifiable random challenge for bandwidth proofs.
376///
377/// This is a high-level convenience function that combines node ID, chunk ID,
378/// and timestamp to generate a unique, unpredictable, but verifiable challenge.
379pub fn generate_bandwidth_challenge(
380    secret_key: &VrfSecretKey,
381    node_id: &[u8],
382    chunk_id: &[u8],
383    timestamp: u64,
384) -> VrfProof {
385    let mut input = Vec::with_capacity(node_id.len() + chunk_id.len() + 8);
386    input.extend_from_slice(node_id);
387    input.extend_from_slice(chunk_id);
388    input.extend_from_slice(&timestamp.to_le_bytes());
389
390    secret_key.prove(&input)
391}
392
393/// Verify a bandwidth challenge proof.
394pub fn verify_bandwidth_challenge(
395    public_key: &VrfPublicKey,
396    node_id: &[u8],
397    chunk_id: &[u8],
398    timestamp: u64,
399    proof: &VrfProof,
400) -> VrfResult<[u8; 32]> {
401    let mut input = Vec::with_capacity(node_id.len() + chunk_id.len() + 8);
402    input.extend_from_slice(node_id);
403    input.extend_from_slice(chunk_id);
404    input.extend_from_slice(&timestamp.to_le_bytes());
405
406    public_key.verify(&input, proof)
407}
408
409#[cfg(test)]
410mod tests {
411    use super::*;
412
413    #[test]
414    fn test_vrf_basic() {
415        let sk = VrfSecretKey::generate();
416        let pk = sk.public_key();
417
418        let input = b"test input";
419        let proof = sk.prove(input);
420
421        // Verification should succeed
422        let output = pk.verify(input, &proof).unwrap();
423        assert_eq!(output, proof.output());
424    }
425
426    #[test]
427    fn test_vrf_deterministic() {
428        let sk = VrfSecretKey::generate();
429        let input = b"test input";
430
431        let proof1 = sk.prove(input);
432        let proof2 = sk.prove(input);
433
434        // Same input should produce same output
435        assert_eq!(proof1.output(), proof2.output());
436        assert_eq!(proof1.signature(), proof2.signature());
437    }
438
439    #[test]
440    fn test_vrf_different_inputs() {
441        let sk = VrfSecretKey::generate();
442        let pk = sk.public_key();
443
444        let input1 = b"input1";
445        let input2 = b"input2";
446
447        let proof1 = sk.prove(input1);
448        let proof2 = sk.prove(input2);
449
450        // Different inputs should produce different outputs
451        assert_ne!(proof1.output(), proof2.output());
452
453        // Both should verify correctly
454        pk.verify(input1, &proof1).unwrap();
455        pk.verify(input2, &proof2).unwrap();
456
457        // Cross-verification should fail
458        assert!(pk.verify(input1, &proof2).is_err());
459        assert!(pk.verify(input2, &proof1).is_err());
460    }
461
462    #[test]
463    fn test_vrf_wrong_public_key() {
464        let sk1 = VrfSecretKey::generate();
465        let sk2 = VrfSecretKey::generate();
466        let pk2 = sk2.public_key();
467
468        let input = b"test input";
469        let proof = sk1.prove(input);
470
471        // Verification with wrong public key should fail
472        assert!(pk2.verify(input, &proof).is_err());
473    }
474
475    #[test]
476    fn test_vrf_serialization() {
477        let sk = VrfSecretKey::generate();
478        let pk = sk.public_key();
479
480        let input = b"test input";
481        let proof = sk.prove(input);
482
483        // Serialize and deserialize proof
484        let proof_bytes = proof.to_bytes();
485        let proof2 = VrfProof::from_bytes(&proof_bytes);
486
487        assert_eq!(proof.output(), proof2.output());
488        assert_eq!(proof.signature(), proof2.signature());
489
490        // Should still verify
491        pk.verify(input, &proof2).unwrap();
492    }
493
494    #[test]
495    fn test_vrf_key_serialization() {
496        let sk = VrfSecretKey::generate();
497        let pk = sk.public_key();
498
499        // Serialize and deserialize keys
500        let sk_bytes = sk.to_bytes();
501        let sk2 = VrfSecretKey::from_bytes(&sk_bytes);
502
503        let pk_bytes = pk.to_bytes();
504        let pk2 = VrfPublicKey::from_bytes(&pk_bytes).unwrap();
505
506        // Should produce same results
507        let input = b"test input";
508        let proof1 = sk.prove(input);
509        let proof2 = sk2.prove(input);
510
511        assert_eq!(proof1.output(), proof2.output());
512
513        pk2.verify(input, &proof1).unwrap();
514    }
515
516    #[test]
517    fn test_bandwidth_challenge() {
518        let sk = VrfSecretKey::generate();
519        let pk = sk.public_key();
520
521        let node_id = b"node123";
522        let chunk_id = b"chunk456";
523        let timestamp = 1234567890u64;
524
525        let proof = generate_bandwidth_challenge(&sk, node_id, chunk_id, timestamp);
526
527        // Verification should succeed
528        let output = verify_bandwidth_challenge(&pk, node_id, chunk_id, timestamp, &proof).unwrap();
529        assert_eq!(output, proof.output());
530
531        // Different timestamp should fail
532        assert!(verify_bandwidth_challenge(&pk, node_id, chunk_id, timestamp + 1, &proof).is_err());
533    }
534
535    #[test]
536    fn test_unpredictability() {
537        let sk = VrfSecretKey::generate();
538
539        // Generate multiple outputs
540        let outputs: Vec<[u8; 32]> = (0u64..10)
541            .map(|i| sk.prove_output(&i.to_le_bytes()))
542            .collect();
543
544        // All outputs should be different
545        for i in 0..outputs.len() {
546            for j in i + 1..outputs.len() {
547                assert_ne!(outputs[i], outputs[j]);
548            }
549        }
550    }
551
552    #[test]
553    fn test_domain_separation() {
554        let sk = VrfSecretKey::generate();
555        let pk = sk.public_key();
556
557        let domain1 = b"domain1";
558        let domain2 = b"domain2";
559        let input = b"test input";
560
561        let proof1 = sk.prove_with_domain(domain1, input);
562        let proof2 = sk.prove_with_domain(domain2, input);
563
564        // Different domains should produce different outputs
565        assert_ne!(proof1.output(), proof2.output());
566
567        // Each should verify with correct domain
568        pk.verify_with_domain(domain1, input, &proof1).unwrap();
569        pk.verify_with_domain(domain2, input, &proof2).unwrap();
570
571        // Cross-domain verification should fail
572        assert!(pk.verify_with_domain(domain1, input, &proof2).is_err());
573        assert!(pk.verify_with_domain(domain2, input, &proof1).is_err());
574    }
575
576    #[test]
577    fn test_batch_verify() {
578        let sk = VrfSecretKey::generate();
579        let pk = sk.public_key();
580
581        let inputs: Vec<Vec<u8>> = (0..5).map(|i| format!("input{}", i).into_bytes()).collect();
582        let input_refs: Vec<&[u8]> = inputs.iter().map(|v| v.as_slice()).collect();
583
584        let proofs: Vec<VrfProof> = input_refs.iter().map(|input| sk.prove(input)).collect();
585
586        // Batch verification should succeed
587        let outputs = pk.batch_verify(&input_refs, &proofs).unwrap();
588        assert_eq!(outputs.len(), 5);
589
590        // Each output should match individual verification
591        for (i, (input, proof)) in input_refs.iter().zip(proofs.iter()).enumerate() {
592            let individual_output = pk.verify(input, proof).unwrap();
593            assert_eq!(outputs[i], individual_output);
594        }
595    }
596
597    #[test]
598    fn test_batch_verify_mismatched_lengths() {
599        let sk = VrfSecretKey::generate();
600        let pk = sk.public_key();
601
602        let inputs: Vec<&[u8]> = vec![b"input1", b"input2", b"input3"];
603        let proofs: Vec<VrfProof> = vec![sk.prove(b"input1"), sk.prove(b"input2")];
604
605        // Mismatched lengths should error
606        assert!(pk.batch_verify(&inputs, &proofs).is_err());
607    }
608
609    #[test]
610    fn test_derive_outputs() {
611        let sk = VrfSecretKey::generate();
612        let input = b"test input";
613        let proof = sk.prove(input);
614
615        // Derive multiple outputs
616        let derived = proof.derive_outputs(10);
617        assert_eq!(derived.len(), 10);
618
619        // All derived outputs should be different
620        for i in 0..derived.len() {
621            for j in i + 1..derived.len() {
622                assert_ne!(derived[i], derived[j]);
623            }
624        }
625
626        // Deriving the same index should give same result
627        let output1 = proof.derive_output(5);
628        let output2 = proof.derive_output(5);
629        assert_eq!(output1, output2);
630        assert_eq!(output1, derived[5]);
631    }
632
633    #[test]
634    fn test_proof_serialization_serde() {
635        let sk = VrfSecretKey::generate();
636        let input = b"test input";
637        let proof = sk.prove(input);
638
639        // Serialize with bincode
640        let serialized = crate::codec::encode(&proof).unwrap();
641        let deserialized: VrfProof = crate::codec::decode(&serialized).unwrap();
642
643        assert_eq!(proof.output(), deserialized.output());
644        assert_eq!(proof.signature(), deserialized.signature());
645    }
646}