From 2ffa2c6ab082d6c91f7e9373ff60d051391df50d Mon Sep 17 00:00:00 2001 From: Ian Goldberg Date: Thu, 29 Apr 2021 21:24:32 -0400 Subject: [PATCH] Check the proof in the request message of the trust promotion protocol --- crates/lox-library/Cargo.toml | 2 +- crates/lox-library/src/lib.rs | 21 ++++ crates/lox-library/src/tests.rs | 5 +- crates/lox-library/src/trust_promotion.rs | 132 +++++++++++++++++++--- crates/lox-library/tests/tests.rs | 8 -- 5 files changed, 145 insertions(+), 23 deletions(-) diff --git a/crates/lox-library/Cargo.toml b/crates/lox-library/Cargo.toml index 9a2ffcb..a8cca5a 100644 --- a/crates/lox-library/Cargo.toml +++ b/crates/lox-library/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" diff --git a/crates/lox-library/src/lib.rs b/crates/lox-library/src/lib.rs index a143361..f6ca7f7 100644 --- a/crates/lox-library/src/lib.rs +++ b/crates/lox-library/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; diff --git a/crates/lox-library/src/tests.rs b/crates/lox-library/src/tests.rs index 2bc74c2..2c09007 100644 --- a/crates/lox-library/src/tests.rs +++ b/crates/lox-library/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(); } diff --git a/crates/lox-library/src/trust_promotion.rs b/crates/lox-library/src/trust_promotion.rs index df1049f..2fc9074 100644 --- a/crates/lox-library/src/trust_promotion.rs +++ b/crates/lox-library/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(()) + } +} diff --git a/crates/lox-library/tests/tests.rs b/crates/lox-library/tests/tests.rs index bc2c799..163bac5 100644 --- a/crates/lox-library/tests/tests.rs +++ b/crates/lox-library/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); -}