瀏覽代碼

research/ecvrf: Simplify and use paper notation.

parazyd 3 年之前
父節點
當前提交
16b519f521
共有 1 個文件被更改,包括 60 次插入68 次删除
  1. 60 68
      script/research/ecvrf/src/main.rs

+ 60 - 68
script/research/ecvrf/src/main.rs

@@ -1,7 +1,6 @@
 /* This file is part of DarkFi (https://dark.fi)
 /* This file is part of DarkFi (https://dark.fi)
  *
  *
  * Copyright (C) 2020-2023 Dyne.org foundation
  * Copyright (C) 2020-2023 Dyne.org foundation
- * Copyright (C) 2021 Silur <https://github.com/Silur/ECVRF/>
  *
  *
  * This program is free software: you can redistribute it and/or modify
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU Affero General Public License as
  * it under the terms of the GNU Affero General Public License as
@@ -17,12 +16,14 @@
  * along with this program.  If not, see <https://www.gnu.org/licenses/>.
  * along with this program.  If not, see <https://www.gnu.org/licenses/>.
  */
  */
 
 
+//! https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-vrf-04#section-5
+#![allow(non_snake_case)]
+
 use darkfi_sdk::{
 use darkfi_sdk::{
     crypto::{
     crypto::{
         constants::NullifierK,
         constants::NullifierK,
-        pasta_prelude::{CurveExt, Field},
+        pasta_prelude::{CurveExt, Field, Group},
         util::mod_r_p,
         util::mod_r_p,
-        Keypair, PublicKey, SecretKey,
     },
     },
     pasta::{
     pasta::{
         group::{ff::FromUniformBytes, GroupEncoding},
         group::{ff::FromUniformBytes, GroupEncoding},
@@ -30,93 +31,84 @@ use darkfi_sdk::{
     },
     },
 };
 };
 use halo2_gadgets::ecc::chip::FixedPoint;
 use halo2_gadgets::ecc::chip::FixedPoint;
+use lazy_static::lazy_static;
 use rand::rngs::OsRng;
 use rand::rngs::OsRng;
 
 
+lazy_static! {
+    /// The `B` generator
+    static ref B: pallas::Affine = NullifierK.generator();
+}
+
+const VRF_DOMAIN: &str = "ECVRF";
+
+#[derive(Copy, Clone, Debug)]
 struct VrfProof {
 struct VrfProof {
     gamma: pallas::Point,
     gamma: pallas::Point,
-    c: [u8; 32],
+    c: blake3::Hash,
     s: pallas::Scalar,
     s: pallas::Scalar,
 }
 }
 
 
-fn keygen() -> Keypair {
-    Keypair::random(&mut OsRng)
-}
+fn prove(x: pallas::Base, alpha_string: &[u8]) -> VrfProof {
+    let Y = *B * mod_r_p(x);
 
 
-/// The output of a VRF function is the VRF hash and the proof to verify
-/// we generated this hash with the supplied key.
-fn prove(input: &[u8], secret_key: &SecretKey) -> ([u8; 32], VrfProof) {
-    let h = pallas::Point::hash_to_curve("ecvrf")(input);
-    let gamma = h * mod_r_p(secret_key.inner());
-    let k = pallas::Scalar::random(&mut OsRng);
+    let pallas_hasher = pallas::Point::hash_to_curve(VRF_DOMAIN);
+    let H = pallas_hasher(&Y.to_bytes()) + pallas_hasher(alpha_string);
 
 
-    // TODO: Valid to use this as basepoint?
-    let g = NullifierK.generator();
+    let gamma = H * mod_r_p(x);
+    let k = pallas::Scalar::random(&mut OsRng);
 
 
     let mut hasher = blake3::Hasher::new();
     let mut hasher = blake3::Hasher::new();
-    // TODO: Basepoint?
-    hasher.update(&g.to_bytes());
-    hasher.update(&h.to_bytes());
-    hasher.update(&(g * mod_r_p(secret_key.inner())).to_bytes());
-    hasher.update(&(h * mod_r_p(secret_key.inner())).to_bytes());
-    hasher.update(&(g * k).to_bytes());
-    hasher.update(&(h * k).to_bytes());
-
-    let mut c = [0_u8; 64];
-    let binding = hasher.finalize();
-    let hres = binding.as_bytes();
-    for i in 0..hres.len() {
-        c[i] = hres[i];
-    }
+    hasher.update(&H.to_bytes());
+    hasher.update(&gamma.to_bytes());
+    hasher.update(&(*B * k).to_bytes());
+    hasher.update(&(H * k).to_bytes());
+    let c = hasher.finalize();
 
 
-    let c_scalar = pallas::Scalar::from_uniform_bytes(&c);
-    let s = k - c_scalar * mod_r_p(secret_key.inner());
-    let beta = blake3::hash(&gamma.to_bytes());
+    let mut c_scalar = [0u8; 64];
+    c_scalar[..blake3::OUT_LEN].copy_from_slice(c.as_bytes());
+    let c_scalar = pallas::Scalar::from_uniform_bytes(&c_scalar);
 
 
-    (beta.into(), VrfProof { gamma, c: c[..32].try_into().unwrap(), s })
-}
+    let s = k + c_scalar * mod_r_p(x);
 
 
-fn verify(input: &[u8], pubkey: &PublicKey, output: &[u8; 32], proof: &VrfProof) -> bool {
-    let mut c = [0_u8; 64];
-    for i in 0..proof.c.len() {
-        c[i] = proof.c[i];
-    }
+    VrfProof { gamma, c, s }
+}
 
 
-    // TODO: Valid to use this as basepoint?
-    let g = NullifierK.generator();
+fn verify(Y: pallas::Point, proof: VrfProof, alpha_string: &[u8]) -> bool {
+    let pallas_hasher = pallas::Point::hash_to_curve(VRF_DOMAIN);
+    let H = pallas_hasher(&Y.to_bytes()) + pallas_hasher(alpha_string);
 
 
+    let mut c = [0u8; 64];
+    c[..blake3::OUT_LEN].copy_from_slice(proof.c.as_bytes());
     let c_scalar = pallas::Scalar::from_uniform_bytes(&c);
     let c_scalar = pallas::Scalar::from_uniform_bytes(&c);
-    let u = pubkey.inner() * c_scalar + g * proof.s;
-    let h = pallas::Point::hash_to_curve("ecvrf")(input);
-    let v = proof.gamma * c_scalar + h * proof.s;
+
+    let U = *B * proof.s - Y * c_scalar;
+    let V = H * proof.s - proof.gamma * c_scalar;
 
 
     let mut hasher = blake3::Hasher::new();
     let mut hasher = blake3::Hasher::new();
-    // TODO: Basepoint?
-    hasher.update(&g.to_bytes());
-    hasher.update(&h.to_bytes());
-    hasher.update(&pubkey.inner().to_bytes());
+    hasher.update(&H.to_bytes());
     hasher.update(&proof.gamma.to_bytes());
     hasher.update(&proof.gamma.to_bytes());
-    hasher.update(&u.to_bytes());
-    hasher.update(&v.to_bytes());
+    hasher.update(&U.to_bytes());
+    hasher.update(&V.to_bytes());
 
 
-    let mut local_c = [0_u8; 32];
-    let binding = hasher.finalize();
-    let hres = binding.as_bytes();
-    for i in 0..hres.len() {
-        local_c[i] = hres[i];
-    }
-
-    blake3::hash(&proof.gamma.to_bytes()).as_bytes() == output && local_c == proof.c
+    hasher.finalize() == proof.c
 }
 }
 
 
 fn main() {
 fn main() {
-    let keypair = keygen();
-    let input = vec![0xde, 0xad, 0xbe, 0xef];
-    let (output, proof) = prove(&input, &keypair.secret);
-    assert!(verify(&input, &keypair.public, &output, &proof));
-
-    let forge_public = PublicKey::from_secret(SecretKey::random(&mut OsRng));
-    assert!(!verify(&input, &forge_public, &output, &proof));
-
-    let input = vec![0xde, 0xad, 0xbe, 0xed];
-    assert!(!verify(&input, &keypair.public, &output, &proof));
+    // VRF secret key
+    let secret_key = pallas::Base::random(&mut OsRng);
+    // VRF public key
+    let public_key = *B * mod_r_p(secret_key);
+    // VRF input
+    let input = [0xde, 0xad, 0xbe, 0xef];
+
+    let proof = prove(secret_key, &input);
+    assert!(verify(public_key, proof, &input));
+
+    // Forged public key
+    let forged_public_key = pallas::Point::random(&mut OsRng);
+    assert!(!verify(forged_public_key, proof, &input));
+
+    // Forged input
+    let forged_input = [0xde, 0xad, 0xba, 0xbe];
+    assert!(!verify(public_key, proof, &forged_input));
 }
 }