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

This commit is contained in:
Ian Goldberg 2021-04-28 23:02:45 -04:00
parent 75630d3ad0
commit 2791f0bf54
3 changed files with 90 additions and 4 deletions

View File

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

View File

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

View File

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