1use ed25519_dalek::{Signature, Signer, SigningKey, VerifyingKey};
10use rand::rngs::OsRng;
11use sha3::{Digest, Sha3_512};
12
13pub struct VrfKeypair {
14 signing_key: SigningKey,
15}
16
17#[derive(Clone, Debug)]
18pub struct VrfProof {
19 pub proof_bytes: [u8; 64], pub output: [u8; 32], }
22
23impl VrfKeypair {
24 pub fn generate() -> Self {
25 Self { signing_key: SigningKey::generate(&mut OsRng) }
26 }
27
28 pub fn from_seed(seed: [u8; 32]) -> Self {
29 Self { signing_key: SigningKey::from_bytes(&seed) }
30 }
31
32 pub fn public_key(&self) -> [u8; 32] {
33 self.signing_key.verifying_key().to_bytes()
34 }
35
36 pub fn evaluate(&self, input: &[u8]) -> VrfProof {
38 let h = domain_hash(input);
39 let sig = self.signing_key.sign(&h);
40 let proof_bytes = sig.to_bytes();
41 let output = output_hash(&proof_bytes);
42 VrfProof { proof_bytes, output }
43 }
44}
45
46pub fn vrf_verify(pubkey: &[u8; 32], input: &[u8], proof: &VrfProof) -> bool {
48 let vk = match VerifyingKey::from_bytes(pubkey) {
49 Ok(k) => k,
50 Err(_) => return false,
51 };
52 let h = domain_hash(input);
53 let sig = Signature::from_bytes(&proof.proof_bytes);
54 if vk.verify_strict(&h, &sig).is_err() {
55 return false;
56 }
57 proof.output == output_hash(&proof.proof_bytes)
59}
60
61fn domain_hash(input: &[u8]) -> Vec<u8> {
62 let mut h = Sha3_512::new();
63 h.update(b"ling-vrf-v1:");
64 h.update(input);
65 h.finalize().to_vec()
66}
67
68fn output_hash(sig: &[u8; 64]) -> [u8; 32] {
69 let mut h = Sha3_512::new();
70 h.update(b"ling-vrf-out-v1:");
71 h.update(sig);
72 let out = h.finalize();
73 out[..32].try_into().unwrap()
74}