Ver código fonte

Handle the response of the open invitation protocol to produce the Lox credential

Ian Goldberg 3 anos atrás
pai
commit
d895dbb0a5
3 arquivos alterados com 90 adições e 4 exclusões
  1. 2 0
      src/cred.rs
  2. 4 1
      src/lib.rs
  3. 84 3
      src/open_invite.rs

+ 2 - 0
src/cred.rs

@@ -9,6 +9,7 @@ use curve25519_dalek::scalar::Scalar;
 /// A migration credential.  This credential authorizes the holder of
 /// the Lox credential with the given id to switch from bucket
 /// from_bucket to bucket to_bucket.
+#[derive(Debug)]
 pub struct Migration {
     pub P: RistrettoPoint,
     pub Q: RistrettoPoint,
@@ -26,6 +27,7 @@ pub struct Migration {
 /// authorizes the user to switch from its current bucket to the same
 /// bucket (i.e., a no-op).  This can be useful for hiding from the BA
 /// whether or not the user is performing a bucket migration.
+#[derive(Debug)]
 pub struct Lox {
     pub P: RistrettoPoint,
     pub Q: RistrettoPoint,

+ 4 - 1
src/lib.rs

@@ -274,6 +274,9 @@ mod tests {
 
         // Use it to get a Lox credential
         let (req, state) = open_invite::request(&inv);
-        let resp = ba.handle_open_invite(req);
+        let resp = ba.handle_open_invite(req).unwrap();
+        let cred =
+            open_invite::handle_response(state, resp, &ba.lox_pub, &ba.migration_pub).unwrap();
+        println!("cred = {:?}", cred);
     }
 }

+ 84 - 3
src/open_invite.rs

@@ -14,12 +14,14 @@ credential.  The credential will have attributes:
 use curve25519_dalek::ristretto::RistrettoBasepointTable;
 use curve25519_dalek::ristretto::RistrettoPoint;
 use curve25519_dalek::scalar::Scalar;
+use curve25519_dalek::traits::IsIdentity;
 
 use zkp::CompactProof;
 use zkp::ProofError;
 use zkp::Transcript;
 
 use super::bridge_table;
+use super::cred;
 use super::dup_filter::SeenType;
 use super::{BridgeAuth, IssuerPubKey};
 use super::{CMZ_A, CMZ_A_TABLE, CMZ_B, CMZ_B_TABLE};
@@ -74,7 +76,8 @@ define_proof! {
     (x0, x0tilde, xid, xbucket, xsince, s, b, tid,
      x0_nm, x0tilde_nm, xid_nm, xfrom_nm, xto_nm, s_nm, b_nm, tid_nm),
     (P, EncQ0, EncQ1, X0, Xid, Xbucket, Xsince, Pbucket, Psince, TId,
-     P_nm, EncQ0_nm, EncQ1_nm, X0_nm, Xid_nm, Xfrom_nm, Xto_nm, TId_nm,
+     P_nm, EncQ0_nm, EncQ1_nm, X0_nm, Xid_nm, Xfrom_nm, Xto_nm,
+     Pbucket_nm, TId_nm,
      D, EncId0, EncId1),
     (A, B) :
     Xid = (xid*A),
@@ -94,7 +97,7 @@ define_proof! {
     TId_nm = (b_nm*Xid_nm),
     TId_nm = (tid_nm*A),
     EncQ0_nm = (s_nm*B + tid_nm*EncId0),
-    EncQ1_nm = (s_nm*D + tid_nm*EncId1 + x0_nm*P_nm + xfrom_nm*Pbucket + xto_nm*Pbucket)
+    EncQ1_nm = (s_nm*D + tid_nm*EncId1 + x0_nm*P_nm + xfrom_nm*Pbucket_nm + xto_nm*Pbucket_nm)
 }
 
 /// Submit an open invitation issued by the BridgeDb to receive your
@@ -231,7 +234,7 @@ impl BridgeAuth {
         let QHc_noopmigration = (self.migration_priv.x[0]
             + self.migration_priv.x[2] * bucket
             + self.migration_priv.x[3] * bucket)
-            * P;
+            * P_noopmigration;
 
         // El Gamal encrypt it to the public key req.D
         let s_noopmigration = Scalar::random(&mut rng);
@@ -274,6 +277,7 @@ impl BridgeAuth {
                 Xid_nm: &self.migration_pub.X[1],
                 Xfrom_nm: &self.migration_pub.X[2],
                 Xto_nm: &self.migration_pub.X[3],
+                Pbucket_nm: &(bucket * P_noopmigration),
                 TId_nm: &TId_noopmigration,
                 D: &req.D,
                 EncId0: &EncId.0,
@@ -312,3 +316,80 @@ impl BridgeAuth {
         })
     }
 }
+
+/// Handle the reponse to the request, producing the desired Lox
+/// credential if successful.
+pub fn handle_response(
+    state: State,
+    resp: Response,
+    lox_pub: &IssuerPubKey,
+    migration_pub: &IssuerPubKey,
+) -> Result<cred::Lox, ProofError> {
+    let A: &RistrettoPoint = &CMZ_A;
+    let B: &RistrettoPoint = &CMZ_B;
+    let Btable: &RistrettoBasepointTable = &CMZ_B_TABLE;
+
+    if resp.P.is_identity() || resp.P_noopmigration.is_identity() {
+        return Err(ProofError::VerificationFailure);
+    }
+
+    // Add the server's contribution to the id to our own, both in plain
+    // and encrypted form
+    let id = state.id_client + resp.id_server;
+    let EncId = (
+        state.EncIdClient.0,
+        state.EncIdClient.1 + &resp.id_server * Btable,
+    );
+
+    // Verify the proof
+    let mut transcript = Transcript::new(b"open 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(),
+            Xsince: &lox_pub.X[4].compress(),
+            Pbucket: &(resp.bucket * resp.P).compress(),
+            Psince: &(resp.level_since * resp.P).compress(),
+            TId: &resp.TId.compress(),
+            P_nm: &resp.P_noopmigration.compress(),
+            EncQ0_nm: &resp.EncQ_noopmigration.0.compress(),
+            EncQ1_nm: &resp.EncQ_noopmigration.1.compress(),
+            X0_nm: &migration_pub.X[0].compress(),
+            Xid_nm: &migration_pub.X[1].compress(),
+            Xfrom_nm: &migration_pub.X[2].compress(),
+            Xto_nm: &migration_pub.X[3].compress(),
+            Pbucket_nm: &(resp.bucket * resp.P_noopmigration).compress(),
+            TId_nm: &resp.TId_noopmigration.compress(),
+            D: &state.D.compress(),
+            EncId0: &EncId.0.compress(),
+            EncId1: &EncId.1.compress(),
+        },
+    )?;
+
+    // Decrypt EncQ
+    let Q = resp.EncQ.1 - (state.d * resp.EncQ.0);
+
+    // Decrypt EncQ_noopmigration
+    let Q_noopmigration = resp.EncQ_noopmigration.1 - (state.d * resp.EncQ_noopmigration.0);
+
+    Ok(cred::Lox {
+        P: resp.P,
+        Q,
+        id,
+        bucket: resp.bucket,
+        trust_level: Scalar::zero(),
+        level_since: resp.level_since,
+        invites_remaining: Scalar::zero(),
+        invites_issued: Scalar::zero(),
+        P_noopmigration: resp.P_noopmigration,
+        Q_noopmigration,
+    })
+}