use blake3;
use ed25519_dalek::{Signature, Signer, SigningKey, Verifier, VerifyingKey};
use serde::{Deserialize, Serialize};
use thiserror::Error;
#[derive(Debug, Error)]
pub enum VrfError {
#[error("Invalid VRF proof")]
InvalidProof,
#[error("Invalid public key")]
InvalidPublicKey,
#[error("Proof verification failed")]
VerificationFailed,
#[error("Invalid input length")]
InvalidInputLength,
}
pub type VrfResult<T> = Result<T, VrfError>;
#[derive(Clone)]
pub struct VrfSecretKey {
signing_key: SigningKey,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct VrfPublicKey {
verifying_key: VerifyingKey,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct VrfProof {
signature: [u8; 64],
output: [u8; 32],
}
impl Serialize for VrfProof {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
use serde::ser::SerializeStruct;
let mut state = serializer.serialize_struct("VrfProof", 2)?;
state.serialize_field("signature", &self.signature.as_slice())?;
state.serialize_field("output", &self.output)?;
state.end()
}
}
impl<'de> Deserialize<'de> for VrfProof {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
use serde::de::{self, Visitor};
use std::fmt;
struct VrfProofVisitor;
impl<'de> Visitor<'de> for VrfProofVisitor {
type Value = VrfProof;
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.write_str("struct VrfProof")
}
fn visit_seq<V>(self, mut seq: V) -> Result<VrfProof, V::Error>
where
V: de::SeqAccess<'de>,
{
let sig_bytes: Vec<u8> = seq
.next_element()?
.ok_or_else(|| de::Error::invalid_length(0, &self))?;
let output: [u8; 32] = seq
.next_element()?
.ok_or_else(|| de::Error::invalid_length(1, &self))?;
if sig_bytes.len() != 64 {
return Err(de::Error::invalid_length(sig_bytes.len(), &"64 bytes"));
}
let mut signature = [0u8; 64];
signature.copy_from_slice(&sig_bytes);
Ok(VrfProof { signature, output })
}
fn visit_map<V>(self, mut map: V) -> Result<VrfProof, V::Error>
where
V: de::MapAccess<'de>,
{
let mut signature: Option<Vec<u8>> = None;
let mut output: Option<[u8; 32]> = None;
while let Some(key) = map.next_key::<String>()? {
match key.as_str() {
"signature" => {
if signature.is_some() {
return Err(de::Error::duplicate_field("signature"));
}
signature = Some(map.next_value()?);
}
"output" => {
if output.is_some() {
return Err(de::Error::duplicate_field("output"));
}
output = Some(map.next_value()?);
}
_ => {
let _: de::IgnoredAny = map.next_value()?;
}
}
}
let sig_bytes = signature.ok_or_else(|| de::Error::missing_field("signature"))?;
let output = output.ok_or_else(|| de::Error::missing_field("output"))?;
if sig_bytes.len() != 64 {
return Err(de::Error::invalid_length(sig_bytes.len(), &"64 bytes"));
}
let mut signature = [0u8; 64];
signature.copy_from_slice(&sig_bytes);
Ok(VrfProof { signature, output })
}
}
const FIELDS: &[&str] = &["signature", "output"];
deserializer.deserialize_struct("VrfProof", FIELDS, VrfProofVisitor)
}
}
impl VrfSecretKey {
pub fn generate() -> Self {
let mut secret = [0u8; 32];
getrandom::fill(&mut secret).expect("Failed to generate random bytes");
let signing_key = SigningKey::from_bytes(&secret);
Self { signing_key }
}
pub fn from_bytes(bytes: &[u8; 32]) -> Self {
let signing_key = SigningKey::from_bytes(bytes);
Self { signing_key }
}
pub fn public_key(&self) -> VrfPublicKey {
VrfPublicKey {
verifying_key: self.signing_key.verifying_key(),
}
}
pub fn to_bytes(&self) -> [u8; 32] {
self.signing_key.to_bytes()
}
pub fn prove(&self, input: &[u8]) -> VrfProof {
let mut hasher = blake3::Hasher::new();
hasher.update(b"VRF_INPUT:");
hasher.update(&self.public_key().to_bytes());
hasher.update(input);
let point_hash = hasher.finalize();
let signature = self.signing_key.sign(point_hash.as_bytes());
let mut output_hasher = blake3::Hasher::new();
output_hasher.update(b"VRF_OUTPUT:");
output_hasher.update(&signature.to_bytes());
let output = output_hasher.finalize();
VrfProof {
signature: signature.to_bytes(),
output: *output.as_bytes(),
}
}
pub fn prove_output(&self, input: &[u8]) -> [u8; 32] {
self.prove(input).output()
}
pub fn prove_with_domain(&self, domain: &[u8], input: &[u8]) -> VrfProof {
let mut hasher = blake3::Hasher::new();
hasher.update(b"VRF_DOMAIN_INPUT:");
hasher.update(domain);
hasher.update(&self.public_key().to_bytes());
hasher.update(input);
let point_hash = hasher.finalize();
let signature = self.signing_key.sign(point_hash.as_bytes());
let mut output_hasher = blake3::Hasher::new();
output_hasher.update(b"VRF_DOMAIN_OUTPUT:");
output_hasher.update(domain);
output_hasher.update(&signature.to_bytes());
let output = output_hasher.finalize();
VrfProof {
signature: signature.to_bytes(),
output: *output.as_bytes(),
}
}
}
impl VrfPublicKey {
pub fn from_bytes(bytes: &[u8; 32]) -> VrfResult<Self> {
let verifying_key =
VerifyingKey::from_bytes(bytes).map_err(|_| VrfError::InvalidPublicKey)?;
Ok(Self { verifying_key })
}
pub fn to_bytes(&self) -> [u8; 32] {
self.verifying_key.to_bytes()
}
pub fn verify(&self, input: &[u8], proof: &VrfProof) -> VrfResult<[u8; 32]> {
let mut hasher = blake3::Hasher::new();
hasher.update(b"VRF_INPUT:");
hasher.update(&self.to_bytes());
hasher.update(input);
let point_hash = hasher.finalize();
let signature = Signature::from_bytes(&proof.signature);
self.verifying_key
.verify(point_hash.as_bytes(), &signature)
.map_err(|_| VrfError::VerificationFailed)?;
let mut output_hasher = blake3::Hasher::new();
output_hasher.update(b"VRF_OUTPUT:");
output_hasher.update(&proof.signature);
let computed_output = output_hasher.finalize();
if computed_output.as_bytes() != &proof.output {
return Err(VrfError::InvalidProof);
}
Ok(proof.output)
}
pub fn verify_with_domain(
&self,
domain: &[u8],
input: &[u8],
proof: &VrfProof,
) -> VrfResult<[u8; 32]> {
let mut hasher = blake3::Hasher::new();
hasher.update(b"VRF_DOMAIN_INPUT:");
hasher.update(domain);
hasher.update(&self.to_bytes());
hasher.update(input);
let point_hash = hasher.finalize();
let signature = Signature::from_bytes(&proof.signature);
self.verifying_key
.verify(point_hash.as_bytes(), &signature)
.map_err(|_| VrfError::VerificationFailed)?;
let mut output_hasher = blake3::Hasher::new();
output_hasher.update(b"VRF_DOMAIN_OUTPUT:");
output_hasher.update(domain);
output_hasher.update(&proof.signature);
let computed_output = output_hasher.finalize();
if computed_output.as_bytes() != &proof.output {
return Err(VrfError::InvalidProof);
}
Ok(proof.output)
}
pub fn batch_verify(&self, inputs: &[&[u8]], proofs: &[VrfProof]) -> VrfResult<Vec<[u8; 32]>> {
if inputs.len() != proofs.len() {
return Err(VrfError::InvalidInputLength);
}
let mut outputs = Vec::with_capacity(proofs.len());
for (input, proof) in inputs.iter().zip(proofs.iter()) {
let output = self.verify(input, proof)?;
outputs.push(output);
}
Ok(outputs)
}
}
impl VrfProof {
pub fn output(&self) -> [u8; 32] {
self.output
}
pub fn signature(&self) -> [u8; 64] {
self.signature
}
pub fn to_bytes(&self) -> [u8; 96] {
let mut bytes = [0u8; 96];
bytes[..64].copy_from_slice(&self.signature);
bytes[64..].copy_from_slice(&self.output);
bytes
}
pub fn from_bytes(bytes: &[u8; 96]) -> Self {
let mut signature = [0u8; 64];
let mut output = [0u8; 32];
signature.copy_from_slice(&bytes[..64]);
output.copy_from_slice(&bytes[64..]);
Self { signature, output }
}
pub fn derive_output(&self, index: u32) -> [u8; 32] {
let mut hasher = blake3::Hasher::new();
hasher.update(b"VRF_DERIVE:");
hasher.update(&self.output);
hasher.update(&index.to_le_bytes());
*hasher.finalize().as_bytes()
}
pub fn derive_outputs(&self, count: u32) -> Vec<[u8; 32]> {
(0..count).map(|i| self.derive_output(i)).collect()
}
}
pub fn generate_bandwidth_challenge(
secret_key: &VrfSecretKey,
node_id: &[u8],
chunk_id: &[u8],
timestamp: u64,
) -> VrfProof {
let mut input = Vec::with_capacity(node_id.len() + chunk_id.len() + 8);
input.extend_from_slice(node_id);
input.extend_from_slice(chunk_id);
input.extend_from_slice(×tamp.to_le_bytes());
secret_key.prove(&input)
}
pub fn verify_bandwidth_challenge(
public_key: &VrfPublicKey,
node_id: &[u8],
chunk_id: &[u8],
timestamp: u64,
proof: &VrfProof,
) -> VrfResult<[u8; 32]> {
let mut input = Vec::with_capacity(node_id.len() + chunk_id.len() + 8);
input.extend_from_slice(node_id);
input.extend_from_slice(chunk_id);
input.extend_from_slice(×tamp.to_le_bytes());
public_key.verify(&input, proof)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_vrf_basic() {
let sk = VrfSecretKey::generate();
let pk = sk.public_key();
let input = b"test input";
let proof = sk.prove(input);
let output = pk.verify(input, &proof).unwrap();
assert_eq!(output, proof.output());
}
#[test]
fn test_vrf_deterministic() {
let sk = VrfSecretKey::generate();
let input = b"test input";
let proof1 = sk.prove(input);
let proof2 = sk.prove(input);
assert_eq!(proof1.output(), proof2.output());
assert_eq!(proof1.signature(), proof2.signature());
}
#[test]
fn test_vrf_different_inputs() {
let sk = VrfSecretKey::generate();
let pk = sk.public_key();
let input1 = b"input1";
let input2 = b"input2";
let proof1 = sk.prove(input1);
let proof2 = sk.prove(input2);
assert_ne!(proof1.output(), proof2.output());
pk.verify(input1, &proof1).unwrap();
pk.verify(input2, &proof2).unwrap();
assert!(pk.verify(input1, &proof2).is_err());
assert!(pk.verify(input2, &proof1).is_err());
}
#[test]
fn test_vrf_wrong_public_key() {
let sk1 = VrfSecretKey::generate();
let sk2 = VrfSecretKey::generate();
let pk2 = sk2.public_key();
let input = b"test input";
let proof = sk1.prove(input);
assert!(pk2.verify(input, &proof).is_err());
}
#[test]
fn test_vrf_serialization() {
let sk = VrfSecretKey::generate();
let pk = sk.public_key();
let input = b"test input";
let proof = sk.prove(input);
let proof_bytes = proof.to_bytes();
let proof2 = VrfProof::from_bytes(&proof_bytes);
assert_eq!(proof.output(), proof2.output());
assert_eq!(proof.signature(), proof2.signature());
pk.verify(input, &proof2).unwrap();
}
#[test]
fn test_vrf_key_serialization() {
let sk = VrfSecretKey::generate();
let pk = sk.public_key();
let sk_bytes = sk.to_bytes();
let sk2 = VrfSecretKey::from_bytes(&sk_bytes);
let pk_bytes = pk.to_bytes();
let pk2 = VrfPublicKey::from_bytes(&pk_bytes).unwrap();
let input = b"test input";
let proof1 = sk.prove(input);
let proof2 = sk2.prove(input);
assert_eq!(proof1.output(), proof2.output());
pk2.verify(input, &proof1).unwrap();
}
#[test]
fn test_bandwidth_challenge() {
let sk = VrfSecretKey::generate();
let pk = sk.public_key();
let node_id = b"node123";
let chunk_id = b"chunk456";
let timestamp = 1234567890u64;
let proof = generate_bandwidth_challenge(&sk, node_id, chunk_id, timestamp);
let output = verify_bandwidth_challenge(&pk, node_id, chunk_id, timestamp, &proof).unwrap();
assert_eq!(output, proof.output());
assert!(verify_bandwidth_challenge(&pk, node_id, chunk_id, timestamp + 1, &proof).is_err());
}
#[test]
fn test_unpredictability() {
let sk = VrfSecretKey::generate();
let outputs: Vec<[u8; 32]> = (0u64..10)
.map(|i| sk.prove_output(&i.to_le_bytes()))
.collect();
for i in 0..outputs.len() {
for j in i + 1..outputs.len() {
assert_ne!(outputs[i], outputs[j]);
}
}
}
#[test]
fn test_domain_separation() {
let sk = VrfSecretKey::generate();
let pk = sk.public_key();
let domain1 = b"domain1";
let domain2 = b"domain2";
let input = b"test input";
let proof1 = sk.prove_with_domain(domain1, input);
let proof2 = sk.prove_with_domain(domain2, input);
assert_ne!(proof1.output(), proof2.output());
pk.verify_with_domain(domain1, input, &proof1).unwrap();
pk.verify_with_domain(domain2, input, &proof2).unwrap();
assert!(pk.verify_with_domain(domain1, input, &proof2).is_err());
assert!(pk.verify_with_domain(domain2, input, &proof1).is_err());
}
#[test]
fn test_batch_verify() {
let sk = VrfSecretKey::generate();
let pk = sk.public_key();
let inputs: Vec<Vec<u8>> = (0..5).map(|i| format!("input{}", i).into_bytes()).collect();
let input_refs: Vec<&[u8]> = inputs.iter().map(|v| v.as_slice()).collect();
let proofs: Vec<VrfProof> = input_refs.iter().map(|input| sk.prove(input)).collect();
let outputs = pk.batch_verify(&input_refs, &proofs).unwrap();
assert_eq!(outputs.len(), 5);
for (i, (input, proof)) in input_refs.iter().zip(proofs.iter()).enumerate() {
let individual_output = pk.verify(input, proof).unwrap();
assert_eq!(outputs[i], individual_output);
}
}
#[test]
fn test_batch_verify_mismatched_lengths() {
let sk = VrfSecretKey::generate();
let pk = sk.public_key();
let inputs: Vec<&[u8]> = vec![b"input1", b"input2", b"input3"];
let proofs: Vec<VrfProof> = vec![sk.prove(b"input1"), sk.prove(b"input2")];
assert!(pk.batch_verify(&inputs, &proofs).is_err());
}
#[test]
fn test_derive_outputs() {
let sk = VrfSecretKey::generate();
let input = b"test input";
let proof = sk.prove(input);
let derived = proof.derive_outputs(10);
assert_eq!(derived.len(), 10);
for i in 0..derived.len() {
for j in i + 1..derived.len() {
assert_ne!(derived[i], derived[j]);
}
}
let output1 = proof.derive_output(5);
let output2 = proof.derive_output(5);
assert_eq!(output1, output2);
assert_eq!(output1, derived[5]);
}
#[test]
fn test_proof_serialization_serde() {
let sk = VrfSecretKey::generate();
let input = b"test input";
let proof = sk.prove(input);
let serialized = crate::codec::encode(&proof).unwrap();
let deserialized: VrfProof = crate::codec::decode(&serialized).unwrap();
assert_eq!(proof.output(), deserialized.output());
assert_eq!(proof.signature(), deserialized.signature());
}
}