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

This commit is contained in:
Ian Goldberg 2021-04-29 21:24:32 -04:00
parent 53652914eb
commit 2ffa2c6ab0
5 changed files with 145 additions and 23 deletions

View File

@ -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"

View File

@ -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;

View File

@ -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();
}

View File

@ -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(())
}
}

View File

@ -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);
}