Browse Source

The response message of the issue invitation protocol

Ian Goldberg 3 years ago
parent
commit
d0684bb5d6
3 changed files with 357 additions and 7 deletions
  1. 354 4
      src/proto/issue_invite.rs
  2. 2 3
      src/proto/level_up.rs
  3. 1 0
      src/tests.rs

+ 354 - 4
src/proto/issue_invite.rs

@@ -56,7 +56,7 @@ use zkp::Transcript;
 
 use super::super::cred;
 use super::super::dup_filter::SeenType;
-use super::super::{pt_dbl, scalar_dbl, scalar_u32};
+use super::super::scalar_u32;
 use super::super::{BridgeAuth, IssuerPubKey};
 use super::super::{CMZ_A, CMZ_A_TABLE, CMZ_B, CMZ_B_TABLE};
 
@@ -129,8 +129,15 @@ pub struct Response {
     TSince: RistrettoPoint,
     TInvRemain: RistrettoPoint,
     TBlockages: RistrettoPoint,
+
+    // The fields for the new Invitation credential
+    P_inv: RistrettoPoint,
+    EncQ_inv: (RistrettoPoint, RistrettoPoint),
     inv_id_server: Scalar,
-    TInvId: RistrettoPoint,
+    TId_inv: RistrettoPoint,
+    date_inv: Scalar,
+    TBucket_inv: RistrettoPoint,
+    TBlockages_inv: RistrettoPoint,
 
     // The ZKP
     piBlindIssue: CompactProof,
@@ -183,6 +190,67 @@ define_proof! {
     EncInvIdClient1 = (inv_id_client*B + einv_id_client*D)
 }
 
+define_proof! {
+    blindissue,
+    "Issue Invite Issuing",
+    (x0, x0tilde, xid, xbucket, xlevel, xsince, xinvremain, xblockages,
+     s, b, tid, tbucket, tlevel, tsince, tinvremain, tblockages,
+     x0_inv, x0tilde_inv, xid_inv, xdate_inv, xbucket_inv,
+     xblockages_inv,
+     s_inv, b_inv, tid_inv, tbucket_inv, tblockages_inv),
+    (P, EncQ0, EncQ1, X0, Xid, Xbucket, Xlevel, Xsince, Xinvremain,
+     Xblockages, TId, TBucket, TLevel, TSince, TInvRemain, TBlockages,
+     P_inv, EncQ_inv0, EncQ_inv1, X0_inv, Xid_inv, Xdate_inv,
+     Xbucket_inv, Xblockages_inv, Pdate_inv, TId_inv, TBucket_inv,
+     TBlockages_inv,
+     D, EncId0, EncId1, EncBucket0, EncBucket1, EncLevel0, EncLevel1,
+     EncSince0, EncSince1, EncInvRemain0, EncInvRemain1,
+     EncBlockages0, EncBlockages1,
+     EncInvId0, EncInvId1),
+    (A, B):
+    Xid = (xid*A),
+    Xbucket = (xbucket*A),
+    Xlevel = (xlevel*A),
+    Xsince = (xsince*A),
+    Xinvremain = (xinvremain*A),
+    Xblockages = (xblockages*A),
+    X0 = (x0*B + x0tilde*A),
+    P = (b*B),
+    TId = (b*Xid),
+    TId = (tid*A),
+    TBucket = (b*Xbucket),
+    TBucket = (tbucket*A),
+    TLevel = (b*Xlevel),
+    TLevel = (tlevel*A),
+    TSince = (b*Xsince),
+    TSince = (tsince*A),
+    TInvRemain = (b*Xinvremain),
+    TInvRemain = (tinvremain*A),
+    TBlockages = (b*Xblockages),
+    TBlockages = (tblockages*A),
+    EncQ0 = (s*B + tid*EncId0 + tbucket*EncBucket0 + tlevel*EncLevel0
+        + tsince*EncSince0 + tinvremain*EncInvRemain0 + tblockages*EncBlockages0),
+    EncQ1 = (s*D + tid*EncId1 + tbucket*EncBucket1 + tlevel*EncLevel1
+        + tsince*EncSince1 + tinvremain*EncInvRemain1 + tblockages*EncBlockages1
+        + x0*P),
+    Xid_inv = (xid_inv*A),
+    Xdate_inv = (xdate_inv*A),
+    Xbucket_inv = (xbucket_inv*A),
+    Xblockages_inv = (xblockages_inv*A),
+    X0_inv = (x0_inv*B + x0tilde_inv*A),
+    P_inv = (b_inv*B),
+    TId_inv = (b_inv*Xid_inv),
+    TId_inv = (tid_inv*A),
+    TBucket_inv = (b_inv*Xbucket_inv),
+    TBucket_inv = (tbucket_inv*A),
+    TBlockages_inv = (b_inv*Xblockages_inv),
+    TBlockages_inv = (tblockages_inv*A),
+    EncQ_inv0 = (s_inv*B + tid_inv*EncInvId0 + tbucket_inv*EncBucket0
+        + tblockages_inv*EncBlockages0),
+    EncQ_inv1 = (s_inv*D + tid_inv*EncInvId1 + tbucket_inv*EncBucket1
+        + tblockages_inv*EncBlockages1 + x0_inv*P_inv + xdate_inv*Pdate_inv)
+}
+
 pub fn request(
     lox_cred: &cred::Lox,
     reach_cred: &cred::BucketReachability,
@@ -231,7 +299,7 @@ pub fn request(
     let zinvremain = Scalar::random(&mut rng);
     let zblockages = Scalar::random(&mut rng);
     let CBucket = lox_cred.bucket * P + &zbucket * Atable;
-    let CLevel = lox_cred.bucket * P + &zlevel * Atable;
+    let CLevel = lox_cred.trust_level * P + &zlevel * Atable;
     let CSince = lox_cred.level_since * P + &zsince * Atable;
     let CInvRemain = lox_cred.invites_remaining * P + &zinvremain * Atable;
     let CBlockages = lox_cred.blockages * P + &zblockages * Atable;
@@ -320,7 +388,7 @@ pub fn request(
     let einv_id_client = Scalar::random(&mut rng);
     let EncInvIdClient = (
         &einv_id_client * Btable,
-        &id_client * Btable + einv_id_client * D,
+        &inv_id_client * Btable + einv_id_client * D,
     );
 
     // The proof that invites_remaining is not zero.  We prove this by
@@ -441,3 +509,285 @@ pub fn request(
         },
     ))
 }
+
+impl BridgeAuth {
+    /// Receive an issue invite request
+    pub fn handle_issue_invite(&mut self, req: Request) -> Result<Response, ProofError> {
+        let A: &RistrettoPoint = &CMZ_A;
+        let B: &RistrettoPoint = &CMZ_B;
+        let Atable: &RistrettoBasepointTable = &CMZ_A_TABLE;
+        let Btable: &RistrettoBasepointTable = &CMZ_B_TABLE;
+
+        if req.P.is_identity() || req.P_reach.is_identity() {
+            return Err(ProofError::VerificationFailure);
+        }
+
+        let today: Scalar = self.today().into();
+
+        // Recompute the "error factors" 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[3] * req.CLevel
+            + self.lox_priv.x[4] * req.CSince
+            + self.lox_priv.x[5] * req.CInvRemain
+            + self.lox_priv.x[6] * req.CBlockages
+            - req.CQ;
+
+        let Vprime_reach = (self.reachability_priv.x[0] + self.reachability_priv.x[1] * today)
+            * req.P_reach
+            + self.reachability_priv.x[2] * req.CBucket_reach
+            - req.CQ_reach;
+
+        // Verify the ZKP
+        let mut transcript = Transcript::new(b"issue invite request");
+        requestproof::verify_compact(
+            &req.piUser,
+            &mut transcript,
+            requestproof::VerifyAssignments {
+                A: &A.compress(),
+                B: &B.compress(),
+                P: &req.P.compress(),
+                CBucket: &req.CBucket.compress(),
+                CLevel: &req.CLevel.compress(),
+                CSince: &req.CSince.compress(),
+                CInvRemain: &req.CInvRemain.compress(),
+                CBlockages: &req.CBlockages.compress(),
+                V: &Vprime.compress(),
+                Xbucket: &self.lox_pub.X[2].compress(),
+                Xlevel: &self.lox_pub.X[3].compress(),
+                Xsince: &self.lox_pub.X[4].compress(),
+                Xinvremain: &self.lox_pub.X[5].compress(),
+                Xblockages: &self.lox_pub.X[6].compress(),
+                P_reach: &req.P_reach.compress(),
+                CBucket_reach: &req.CBucket_reach.compress(),
+                V_reach: &Vprime_reach.compress(),
+                Xbucket_reach: &self.reachability_pub.X[2].compress(),
+                D: &req.D.compress(),
+                EncIdClient0: &req.EncIdClient.0.compress(),
+                EncIdClient1: &req.EncIdClient.1.compress(),
+                EncBucket0: &req.EncBucket.0.compress(),
+                EncBucket1: &req.EncBucket.1.compress(),
+                EncLevel0: &req.EncLevel.0.compress(),
+                EncLevel1: &req.EncLevel.1.compress(),
+                EncSince0: &req.EncSince.0.compress(),
+                EncSince1: &req.EncSince.1.compress(),
+                EncInvRemain0: &req.EncInvRemain.0.compress(),
+                EncInvRemain1_plus_B: &(req.EncInvRemain.1 + B).compress(),
+                EncBlockages0: &req.EncBlockages.0.compress(),
+                EncBlockages1: &req.EncBlockages.1.compress(),
+                EncInvIdClient0: &req.EncInvIdClient.0.compress(),
+                EncInvIdClient1: &req.EncInvIdClient.1.compress(),
+            },
+        )?;
+
+        // Ensure the id has not been seen before, and add it to the
+        // seen list.
+        if self.id_filter.filter(&req.id) == SeenType::Seen {
+            return Err(ProofError::VerificationFailure);
+        }
+
+        // Blind issuing of the new Lox credential
+
+        // Choose a random server id component to add to the client's
+        // (blinded) id component
+        let mut rng = rand::thread_rng();
+        let id_server = Scalar::random(&mut rng);
+        let EncId = (req.EncIdClient.0, req.EncIdClient.1 + &id_server * Btable);
+
+        // Compute the MAC on the visible attributes (none here)
+        let b = Scalar::random(&mut rng);
+        let P = &b * Btable;
+        let QHc = self.lox_priv.x[0] * P;
+
+        // El Gamal encrypt it to the public key req.D
+        let s = Scalar::random(&mut rng);
+        let EncQHc = (&s * Btable, QHc + s * req.D);
+
+        // Homomorphically compute the part of the MAC corresponding to
+        // the blinded attributes
+        let tid = self.lox_priv.x[1] * b;
+        let TId = &tid * Atable;
+        let EncQId = (tid * EncId.0, tid * EncId.1);
+        let tbucket = self.lox_priv.x[2] * b;
+        let TBucket = &tbucket * Atable;
+        let EncQBucket = (tbucket * req.EncBucket.0, tbucket * req.EncBucket.1);
+        let tlevel = self.lox_priv.x[3] * b;
+        let TLevel = &tlevel * Atable;
+        let EncQLevel = (tlevel * req.EncLevel.0, tlevel * req.EncLevel.1);
+        let tsince = self.lox_priv.x[4] * b;
+        let TSince = &tsince * Atable;
+        let EncQSince = (tsince * req.EncSince.0, tsince * req.EncSince.1);
+        let tinvremain = self.lox_priv.x[5] * b;
+        let TInvRemain = &tinvremain * Atable;
+        let EncQInvRemain = (
+            tinvremain * req.EncInvRemain.0,
+            tinvremain * req.EncInvRemain.1,
+        );
+        let tblockages = self.lox_priv.x[6] * b;
+        let TBlockages = &tblockages * Atable;
+        let EncQBlockages = (
+            tblockages * req.EncBlockages.0,
+            tblockages * req.EncBlockages.1,
+        );
+
+        let EncQ = (
+            EncQHc.0
+                + EncQId.0
+                + EncQBucket.0
+                + EncQLevel.0
+                + EncQSince.0
+                + EncQInvRemain.0
+                + EncQBlockages.0,
+            EncQHc.1
+                + EncQId.1
+                + EncQBucket.1
+                + EncQLevel.1
+                + EncQSince.1
+                + EncQInvRemain.1
+                + EncQBlockages.1,
+        );
+
+        // Blind issuing of the new Invitation credential
+
+        // Choose a random server id component to add to the client's
+        // (blinded) id component
+        let inv_id_server = Scalar::random(&mut rng);
+        let EncInvId = (
+            req.EncInvIdClient.0,
+            req.EncInvIdClient.1 + &inv_id_server * Btable,
+        );
+
+        // 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;
+
+        // El Gamal encrypt it to the public key req.D
+        let s_inv = Scalar::random(&mut rng);
+        let EncQHc_inv = (&s_inv * Btable, QHc_inv + s_inv * req.D);
+
+        // Homomorphically compute the part of the MAC corresponding to
+        // the blinded attributes
+        let tinvid = self.invitation_priv.x[1] * b_inv;
+        let TId_inv = &tinvid * Atable;
+        let EncQInvId = (tinvid * EncInvId.0, tinvid * EncInvId.1);
+        let tinvbucket = self.invitation_priv.x[3] * b_inv;
+        let TBucket_inv = &tinvbucket * Atable;
+        // The bucket and blockages encrypted attributes are reused from
+        // the Lox credential
+        let EncQInvBucket = (tinvbucket * req.EncBucket.0, tinvbucket * req.EncBucket.1);
+        let tinvblockages = self.invitation_priv.x[4] * b_inv;
+        let TBlockages_inv = &tinvblockages * Atable;
+        let EncQInvBlockages = (
+            tinvblockages * req.EncBlockages.0,
+            tinvblockages * req.EncBlockages.1,
+        );
+
+        let EncQ_inv = (
+            EncQHc_inv.0 + EncQInvId.0 + EncQInvBucket.0 + EncQInvBlockages.0,
+            EncQHc_inv.1 + EncQInvId.1 + EncQInvBucket.1 + EncQInvBlockages.1,
+        );
+
+        let mut transcript = Transcript::new(b"issue invite issuing");
+        let piBlindIssue = blindissue::prove_compact(
+            &mut transcript,
+            blindissue::ProveAssignments {
+                A: &A,
+                B: &B,
+                P: &P,
+                EncQ0: &EncQ.0,
+                EncQ1: &EncQ.1,
+                X0: &self.lox_pub.X[0],
+                Xid: &self.lox_pub.X[1],
+                Xbucket: &self.lox_pub.X[2],
+                Xlevel: &self.lox_pub.X[3],
+                Xsince: &self.lox_pub.X[4],
+                Xinvremain: &self.lox_pub.X[5],
+                Xblockages: &self.lox_pub.X[6],
+                TId: &TId,
+                TBucket: &TBucket,
+                TLevel: &TLevel,
+                TSince: &TSince,
+                TInvRemain: &TInvRemain,
+                TBlockages: &TBlockages,
+                P_inv: &P_inv,
+                EncQ_inv0: &EncQ_inv.0,
+                EncQ_inv1: &EncQ_inv.1,
+                X0_inv: &self.invitation_pub.X[0],
+                Xid_inv: &self.invitation_pub.X[1],
+                Xdate_inv: &self.invitation_pub.X[2],
+                Xbucket_inv: &self.invitation_pub.X[3],
+                Xblockages_inv: &self.invitation_pub.X[4],
+                Pdate_inv: &(today * P_inv),
+                TId_inv: &TId_inv,
+                TBucket_inv: &TBucket_inv,
+                TBlockages_inv: &TBlockages_inv,
+                D: &req.D,
+                EncId0: &EncId.0,
+                EncId1: &EncId.1,
+                EncBucket0: &req.EncBucket.0,
+                EncBucket1: &req.EncBucket.1,
+                EncLevel0: &req.EncLevel.0,
+                EncLevel1: &req.EncLevel.1,
+                EncSince0: &req.EncSince.0,
+                EncSince1: &req.EncSince.1,
+                EncInvRemain0: &req.EncInvRemain.0,
+                EncInvRemain1: &req.EncInvRemain.1,
+                EncBlockages0: &req.EncBlockages.0,
+                EncBlockages1: &req.EncBlockages.1,
+                EncInvId0: &EncInvId.0,
+                EncInvId1: &EncInvId.1,
+                x0: &self.lox_priv.x[0],
+                x0tilde: &self.lox_priv.x0tilde,
+                xid: &self.lox_priv.x[1],
+                xbucket: &self.lox_priv.x[2],
+                xlevel: &self.lox_priv.x[3],
+                xsince: &self.lox_priv.x[4],
+                xinvremain: &self.lox_priv.x[5],
+                xblockages: &self.lox_priv.x[6],
+                s: &s,
+                b: &b,
+                tid: &tid,
+                tbucket: &tbucket,
+                tlevel: &tlevel,
+                tsince: &tsince,
+                tinvremain: &tinvremain,
+                tblockages: &tblockages,
+                x0_inv: &self.invitation_priv.x[0],
+                x0tilde_inv: &self.invitation_priv.x0tilde,
+                xid_inv: &self.invitation_priv.x[1],
+                xdate_inv: &self.invitation_priv.x[2],
+                xbucket_inv: &self.invitation_priv.x[3],
+                xblockages_inv: &self.invitation_priv.x[4],
+                s_inv: &s_inv,
+                b_inv: &b_inv,
+                tid_inv: &tinvid,
+                tbucket_inv: &tinvbucket,
+                tblockages_inv: &tinvblockages,
+            },
+        )
+        .0;
+
+        Ok(Response {
+            P,
+            EncQ,
+            id_server,
+            TId,
+            TBucket,
+            TLevel,
+            TSince,
+            TInvRemain,
+            TBlockages,
+            P_inv,
+            EncQ_inv,
+            inv_id_server,
+            TId_inv,
+            date_inv: today,
+            TBucket_inv,
+            TBlockages_inv,
+            piBlindIssue,
+        })
+    }
+}

+ 2 - 3
src/proto/level_up.rs

@@ -243,9 +243,8 @@ define_proof! {
      D, EncId0, EncId1, EncBucket0, EncBucket1, EncBlockages0, EncBlockages1),
     (A, B):
     Xid = (xid*A),
-    Xid = (xid*A),
-    Xlevel = (xlevel*A),
     Xbucket = (xbucket*A),
+    Xlevel = (xlevel*A),
     Xsince = (xsince*A),
     Xinvremain = (xinvremain*A),
     Xblockages = (xblockages*A),
@@ -700,7 +699,7 @@ impl BridgeAuth {
         let Atable: &RistrettoBasepointTable = &CMZ_A_TABLE;
         let Btable: &RistrettoBasepointTable = &CMZ_B_TABLE;
 
-        if req.P.is_identity() {
+        if req.P.is_identity() || req.P_reach.is_identity() {
             return Err(ProofError::VerificationFailure);
         }
 

+ 1 - 0
src/tests.rs

@@ -231,4 +231,5 @@ fn test_issue_inv() {
         ba.today(),
     )
     .unwrap();
+    let resp = ba.handle_issue_invite(req).unwrap();
 }