Преглед изворни кода

Check the proof in the request message of the trust promotion protocol

Ian Goldberg пре 3 година
родитељ
комит
94f8786f67
5 измењених фајлова са 145 додато и 23 уклоњено
  1. 1 1
      Cargo.toml
  2. 21 0
      src/lib.rs
  3. 4 1
      src/tests.rs
  4. 119 13
      src/trust_promotion.rs
  5. 0 8
      tests/tests.rs

+ 1 - 1
Cargo.toml

@@ -7,7 +7,7 @@ edition = "2018"
 [dependencies]
 curve25519-dalek = { package = "curve25519-dalek-ng", version = "3", default-features = false, features = ["serde", "std"] }
 ed25519-dalek = "1"
-zkp = "0.8"
+zkp = { version = "0.8", features = ["debug-transcript"] }
 bincode = "1"
 rand = "0.7"
 serde = "1"

+ 21 - 0
src/lib.rs

@@ -234,11 +234,13 @@ impl BridgeAuth {
         }
     }
 
+    #[cfg(test)]
     /// For testing only: manually advance the day by 1 day
     pub fn advance_day(&mut self) {
         self.time_offset += time::Duration::days(1);
     }
 
+    #[cfg(test)]
     /// For testing only: manually advance the day by the given number
     /// of days
     pub fn advance_days(&mut self, days: u16) {
@@ -253,6 +255,20 @@ impl BridgeAuth {
             .try_into()
             .unwrap()
     }
+
+    #[cfg(test)]
+    /// Verify the MAC on a Lox credential
+    pub fn verify_lox(&self, cred: &cred::Lox) -> bool {
+        let Q = (self.lox_priv.x[0]
+            + cred.id * self.lox_priv.x[1]
+            + cred.bucket * self.lox_priv.x[2]
+            + cred.trust_level * self.lox_priv.x[3]
+            + cred.level_since * self.lox_priv.x[4]
+            + cred.invites_remaining * self.lox_priv.x[5]
+            + cred.invites_issued * self.lox_priv.x[6])
+            * cred.P;
+        return Q == cred.Q;
+    }
 }
 
 /// Try to extract a u64 from a Scalar
@@ -270,6 +286,11 @@ pub fn scalar_dbl(s: &Scalar) -> Scalar {
     s + s
 }
 
+/// Double a RistrettoPoint
+pub fn pt_dbl(P: &RistrettoPoint) -> RistrettoPoint {
+    P + P
+}
+
 // The protocol modules
 pub mod open_invite;
 

+ 4 - 1
src/tests.rs

@@ -42,6 +42,7 @@ fn test_open_invite() {
     let bucket = ba.bridge_table.decrypt_bucket_id(id, &key).unwrap();
     println!("cred = {:?}", cred);
     println!("bucket = {:?}", bucket);
+    assert!(ba.verify_lox(&cred));
 }
 
 #[test]
@@ -82,9 +83,11 @@ fn test_trust_promotion() {
     let (req, state) = open_invite::request(&inv);
     let resp = ba.handle_open_invite(req).unwrap();
     let cred = open_invite::handle_response(state, resp, &ba.lox_pub, &ba.migration_pub).unwrap();
+    assert!(ba.verify_lox(&cred));
 
     // Time passes
-    ba.advance_days(40);
+    ba.advance_days(47);
 
     let (promreq, promstate) = trust_promotion::request(&cred, &ba.lox_pub, ba.today()).unwrap();
+    let resp = ba.handle_trust_promotion(promreq).unwrap();
 }

+ 119 - 13
src/trust_promotion.rs

@@ -37,8 +37,8 @@ use zkp::ProofError;
 use zkp::Transcript;
 
 use super::cred;
-use super::IssuerPubKey;
-use super::{scalar_dbl, scalar_u64};
+use super::{pt_dbl, scalar_dbl, scalar_u64};
+use super::{BridgeAuth, IssuerPubKey};
 use super::{CMZ_A, CMZ_A_TABLE, CMZ_B, CMZ_B_TABLE};
 
 /// The minimum number of days a user has to be at trust level 0
@@ -74,6 +74,15 @@ pub struct Request {
     CG6: RistrettoPoint,
     CG7: RistrettoPoint,
     CG8: RistrettoPoint,
+    CG0sq: RistrettoPoint,
+    CG1sq: RistrettoPoint,
+    CG2sq: RistrettoPoint,
+    CG3sq: RistrettoPoint,
+    CG4sq: RistrettoPoint,
+    CG5sq: RistrettoPoint,
+    CG6sq: RistrettoPoint,
+    CG7sq: RistrettoPoint,
+    CG8sq: RistrettoPoint,
 
     // The combined ZKP
     piUser: CompactProof,
@@ -223,7 +232,7 @@ pub fn request(
     // Compute zg0 to cancel things out as
     // zg0 = -(zsince + 2*zg1 + 4*zg2 + 8*zg3 + 16*zg4 + 32*zg5 + 64*zg6 + 128*zg7 + 256*zg8)
     // but use Horner's method
-    let zg0 = -scalar_dbl(
+    let zg0 = -(scalar_dbl(
         &(scalar_dbl(
             &(scalar_dbl(
                 &(scalar_dbl(
@@ -233,7 +242,7 @@ pub fn request(
                 ) + zg3),
             ) + zg2),
         ) + zg1),
-    ) + zsince;
+    ) + zsince);
 
     let yg0 = wg0 + g0 * zg0;
     let yg1 = wg1 + g1 * zg1;
@@ -255,6 +264,16 @@ pub fn request(
     let CG7 = g7 * P + &zg7 * Atable;
     let CG8 = g8 * P + &zg8 * Atable;
 
+    let CG0sq = g0 * P + &yg0 * Atable;
+    let CG1sq = g1 * P + &yg1 * Atable;
+    let CG2sq = g2 * P + &yg2 * Atable;
+    let CG3sq = g3 * P + &yg3 * Atable;
+    let CG4sq = g4 * P + &yg4 * Atable;
+    let CG5sq = g5 * P + &yg5 * Atable;
+    let CG6sq = g6 * P + &yg6 * Atable;
+    let CG7sq = g7 * P + &yg7 * Atable;
+    let CG8sq = g8 * P + &yg8 * Atable;
+
     // Construct the proof
     let mut transcript = Transcript::new(b"trust promotion request");
     let piUser = requestproof::prove_compact(
@@ -280,15 +299,15 @@ pub fn request(
             CG6: &CG6,
             CG7: &CG7,
             CG8: &CG8,
-            CG0sq: &(g0 * P + &yg0 * Atable),
-            CG1sq: &(g1 * P + &yg1 * Atable),
-            CG2sq: &(g2 * P + &yg2 * Atable),
-            CG3sq: &(g3 * P + &yg3 * Atable),
-            CG4sq: &(g4 * P + &yg4 * Atable),
-            CG5sq: &(g5 * P + &yg5 * Atable),
-            CG6sq: &(g6 * P + &yg6 * Atable),
-            CG7sq: &(g7 * P + &yg7 * Atable),
-            CG8sq: &(g8 * P + &yg8 * Atable),
+            CG0sq: &CG0sq,
+            CG1sq: &CG1sq,
+            CG2sq: &CG2sq,
+            CG3sq: &CG3sq,
+            CG4sq: &CG4sq,
+            CG5sq: &CG5sq,
+            CG6sq: &CG6sq,
+            CG7sq: &CG7sq,
+            CG8sq: &CG8sq,
             bucket: &lox_cred.bucket,
             since: &lox_cred.level_since,
             zbucket: &zbucket,
@@ -353,6 +372,15 @@ pub fn request(
             CG6,
             CG7,
             CG8,
+            CG0sq,
+            CG1sq,
+            CG2sq,
+            CG3sq,
+            CG4sq,
+            CG5sq,
+            CG6sq,
+            CG7sq,
+            CG8sq,
             piUser,
         },
         State {
@@ -364,3 +392,81 @@ pub fn request(
         },
     ))
 }
+
+impl BridgeAuth {
+    /// Receive a trust promotion request
+    pub fn handle_trust_promotion(&mut self, req: Request) -> Result<(), ProofError> {
+        let A: &RistrettoPoint = &CMZ_A;
+        let B: &RistrettoPoint = &CMZ_B;
+
+        if req.P.is_identity() {
+            return Err(ProofError::VerificationFailure);
+        }
+
+        // Recompute the "error factor" using knowledge of our own
+        // (the issuer's) private key instead of knowledge of the
+        // hidden attributes
+        let Vprime = (self.lox_priv.x[0] + self.lox_priv.x[1] * req.id) * req.P
+            + self.lox_priv.x[2] * req.CBucket
+            + self.lox_priv.x[4] * req.CSince
+            - req.CQ;
+
+        // Recompute CG0 using Horner's method
+        let today: Scalar = self.today().into();
+        let unt: Scalar = UNTRUSTED_INTERVAL.into();
+        let CG0prime = (today - unt) * req.P
+            - req.CSince
+            - pt_dbl(
+                &(pt_dbl(
+                    &(pt_dbl(
+                        &(pt_dbl(
+                            &(pt_dbl(
+                                &(pt_dbl(&(pt_dbl(&(pt_dbl(&req.CG8) + req.CG7)) + req.CG6))
+                                    + req.CG5),
+                            ) + req.CG4),
+                        ) + req.CG3),
+                    ) + req.CG2),
+                ) + req.CG1),
+            );
+
+        // Verify the ZKP
+        let mut transcript = Transcript::new(b"trust promotion request");
+        requestproof::verify_compact(
+            &req.piUser,
+            &mut transcript,
+            requestproof::VerifyAssignments {
+                A: &A.compress(),
+                B: &B.compress(),
+                P: &req.P.compress(),
+                CBucket: &req.CBucket.compress(),
+                CSince: &req.CSince.compress(),
+                V: &Vprime.compress(),
+                Xbucket: &self.lox_pub.X[2].compress(),
+                Xsince: &self.lox_pub.X[4].compress(),
+                EncBucket0: &req.EncBucket.0.compress(),
+                EncBucket1: &req.EncBucket.1.compress(),
+                D: &req.D.compress(),
+                CG0: &CG0prime.compress(),
+                CG1: &req.CG1.compress(),
+                CG2: &req.CG2.compress(),
+                CG3: &req.CG3.compress(),
+                CG4: &req.CG4.compress(),
+                CG5: &req.CG5.compress(),
+                CG6: &req.CG6.compress(),
+                CG7: &req.CG7.compress(),
+                CG8: &req.CG8.compress(),
+                CG0sq: &req.CG0sq.compress(),
+                CG1sq: &req.CG1sq.compress(),
+                CG2sq: &req.CG2sq.compress(),
+                CG3sq: &req.CG3sq.compress(),
+                CG4sq: &req.CG4sq.compress(),
+                CG5sq: &req.CG5sq.compress(),
+                CG6sq: &req.CG6sq.compress(),
+                CG7sq: &req.CG7sq.compress(),
+                CG8sq: &req.CG8sq.compress(),
+            },
+        )?;
+
+        Ok(())
+    }
+}

+ 0 - 8
tests/tests.rs

@@ -45,11 +45,3 @@ fn test_dup_filter() {
     println!("df1 = {:?}", df1);
     println!("df2 = {:?}", df2);
 }
-
-#[test]
-fn test_bridgeauth() {
-    let bdb = BridgeDb::new(20);
-    let mut ba = BridgeAuth::new(bdb.pubkey);
-    ba.advance_day();
-    ba.advance_days(30);
-}