diff --git a/crates/lox-library/Cargo.toml b/crates/lox-library/Cargo.toml index ea88540..0a53f27 100644 --- a/crates/lox-library/Cargo.toml +++ b/crates/lox-library/Cargo.toml @@ -7,8 +7,8 @@ edition = "2018" [dependencies] curve25519-dalek = { package = "curve25519-dalek-ng", version = "3", default-features = false, features = ["serde", "std"] } ed25519-dalek = "1" -# zkp = { version = "0.8", features = ["debug-transcript"] } -zkp = "0.8" +zkp = { version = "0.8", features = ["debug-transcript"] } +# zkp = "0.8" bincode = "1" rand = "0.7" serde = "1" diff --git a/crates/lox-library/src/proto/issue_invite.rs b/crates/lox-library/src/proto/issue_invite.rs index faee7e4..699b660 100644 --- a/crates/lox-library/src/proto/issue_invite.rs +++ b/crates/lox-library/src/proto/issue_invite.rs @@ -282,7 +282,7 @@ pub fn request( return Err(ProofError::VerificationFailure); } // The new invites_remaining - let new_invites_remaining = &lox_cred.invites_remaining - Scalar::one(); + let new_invites_remaining = lox_cred.invites_remaining - Scalar::one(); // Blind showing the Lox credential @@ -662,7 +662,7 @@ impl BridgeAuth { // Compute the MAC on the visible attributes let b_inv = Scalar::random(&mut rng); let P_inv = &b_inv * Btable; - let QHc_inv = (self.invitation_priv.x[0] + self.invitation_priv.x[2] * today) * P; + let QHc_inv = (self.invitation_priv.x[0] + self.invitation_priv.x[2] * today) * P_inv; // El Gamal encrypt it to the public key req.D let s_inv = Scalar::random(&mut rng); @@ -791,3 +791,114 @@ impl BridgeAuth { }) } } + +/// Handle the response to the request, producing the new Lox credential +/// and Invitation credential if successful. +pub fn handle_response( + state: State, + resp: Response, + lox_pub: &IssuerPubKey, + invitation_pub: &IssuerPubKey, +) -> Result<(cred::Lox, cred::Invitation), ProofError> { + let A: &RistrettoPoint = &CMZ_A; + let B: &RistrettoPoint = &CMZ_B; + let Btable: &RistrettoBasepointTable = &CMZ_B_TABLE; + + if resp.P.is_identity() || resp.P_inv.is_identity() { + return Err(ProofError::VerificationFailure); + } + + // Add the server's contribution to the id to our own, both in plain + // and encrypted form and for both the Lox credential id and the + // Invitation credential id + let id = state.id_client + resp.id_server; + let EncId = ( + state.EncIdClient.0, + state.EncIdClient.1 + &resp.id_server * Btable, + ); + + let inv_id = state.inv_id_client + resp.inv_id_server; + let EncInvId = ( + state.EncInvIdClient.0, + state.EncInvIdClient.1 + &resp.inv_id_server * Btable, + ); + + // Verify the proof + let mut transcript = Transcript::new(b"issue invite issuing"); + blindissue::verify_compact( + &resp.piBlindIssue, + &mut transcript, + blindissue::VerifyAssignments { + A: &A.compress(), + B: &B.compress(), + P: &resp.P.compress(), + EncQ0: &resp.EncQ.0.compress(), + EncQ1: &resp.EncQ.1.compress(), + X0: &lox_pub.X[0].compress(), + Xid: &lox_pub.X[1].compress(), + Xbucket: &lox_pub.X[2].compress(), + Xlevel: &lox_pub.X[3].compress(), + Xsince: &lox_pub.X[4].compress(), + Xinvremain: &lox_pub.X[5].compress(), + Xblockages: &lox_pub.X[6].compress(), + TId: &resp.TId.compress(), + TBucket: &resp.TBucket.compress(), + TLevel: &resp.TLevel.compress(), + TSince: &resp.TSince.compress(), + TInvRemain: &resp.TInvRemain.compress(), + TBlockages: &resp.TBlockages.compress(), + P_inv: &resp.P_inv.compress(), + EncQ_inv0: &resp.EncQ_inv.0.compress(), + EncQ_inv1: &resp.EncQ_inv.1.compress(), + X0_inv: &invitation_pub.X[0].compress(), + Xid_inv: &invitation_pub.X[1].compress(), + Xdate_inv: &invitation_pub.X[2].compress(), + Xbucket_inv: &invitation_pub.X[3].compress(), + Xblockages_inv: &invitation_pub.X[4].compress(), + Pdate_inv: &(resp.date_inv * resp.P_inv).compress(), + TId_inv: &resp.TId_inv.compress(), + TBucket_inv: &resp.TBucket_inv.compress(), + TBlockages_inv: &resp.TBlockages_inv.compress(), + D: &state.D.compress(), + EncId0: &EncId.0.compress(), + EncId1: &EncId.1.compress(), + EncBucket0: &state.EncBucket.0.compress(), + EncBucket1: &state.EncBucket.1.compress(), + EncLevel0: &state.EncLevel.0.compress(), + EncLevel1: &state.EncLevel.1.compress(), + EncSince0: &state.EncSince.0.compress(), + EncSince1: &state.EncSince.1.compress(), + EncInvRemain0: &state.EncInvRemain.0.compress(), + EncInvRemain1: &state.EncInvRemain.1.compress(), + EncBlockages0: &state.EncBlockages.0.compress(), + EncBlockages1: &state.EncBlockages.1.compress(), + EncInvId0: &EncInvId.0.compress(), + EncInvId1: &EncInvId.1.compress(), + }, + )?; + + // Decrypt EncQ and EncQ_inv + let Q = resp.EncQ.1 - (state.d * resp.EncQ.0); + let Q_inv = resp.EncQ_inv.1 - (state.d * resp.EncQ_inv.0); + + Ok(( + cred::Lox { + P: resp.P, + Q, + id, + bucket: state.bucket, + trust_level: state.level, + level_since: state.since, + invites_remaining: state.invremain, + blockages: state.blockages, + }, + cred::Invitation { + P: resp.P_inv, + Q: Q_inv, + inv_id, + date: resp.date_inv, + bucket: state.bucket, + blockages: state.blockages, + }, + )) +} diff --git a/crates/lox-library/src/tests.rs b/crates/lox-library/src/tests.rs index 6bd1b79..183ec2d 100644 --- a/crates/lox-library/src/tests.rs +++ b/crates/lox-library/src/tests.rs @@ -232,4 +232,10 @@ fn test_issue_inv() { ) .unwrap(); let resp = ba.handle_issue_invite(req).unwrap(); + let (cred3, invite) = + issue_invite::handle_response(state, resp, &ba.lox_pub, &ba.invitation_pub).unwrap(); + assert!(ba.verify_lox(&cred3)); + assert!(ba.verify_invitation(&invite)); + println!("cred3 = {:?}", cred3); + println!("invite = {:?}", invite); }