|
@@ -0,0 +1,116 @@
|
|
|
+/*! A module for the protocol for the user to redeem an open invitation
|
|
|
+with the BA (bridge authority) to receive their initial Lox
|
|
|
+credential. The credential will have attributes:
|
|
|
+
|
|
|
+- id: jointly chosen by the user and BA
|
|
|
+- bucket: set by the BA
|
|
|
+- trust_level: 0
|
|
|
+- level_since: today
|
|
|
+- invites_remaining: 0
|
|
|
+- invites_issued: 0
|
|
|
+
|
|
|
+*/
|
|
|
+
|
|
|
+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::{BridgeAuth, IssuerPubKey};
|
|
|
+use super::{CMZ_A, CMZ_A_TABLE, CMZ_B, CMZ_B_TABLE};
|
|
|
+
|
|
|
+/// The request message for this protocol
|
|
|
+pub struct Request {
|
|
|
+ invite: [u8; super::OPENINV_LENGTH],
|
|
|
+ D: RistrettoPoint,
|
|
|
+ EncIdClient: (RistrettoPoint, RistrettoPoint),
|
|
|
+ piUserBlinding: CompactProof,
|
|
|
+}
|
|
|
+
|
|
|
+#[derive(Debug)]
|
|
|
+/// The client state for this protocol
|
|
|
+pub struct State {
|
|
|
+ d: Scalar,
|
|
|
+ D: RistrettoPoint,
|
|
|
+ EncIdClient: (RistrettoPoint, RistrettoPoint),
|
|
|
+ id_client: Scalar,
|
|
|
+}
|
|
|
+
|
|
|
+/// The response message for this protocol
|
|
|
+pub struct Response {
|
|
|
+ P: RistrettoPoint,
|
|
|
+ EncQ: (RistrettoPoint, RistrettoPoint),
|
|
|
+ id_server: Scalar,
|
|
|
+ TId: RistrettoPoint,
|
|
|
+ bucket: Scalar,
|
|
|
+ level_since: Scalar,
|
|
|
+ P_noopmigration: RistrettoPoint,
|
|
|
+ EncQ_noopmigration: (RistrettoPoint, RistrettoPoint),
|
|
|
+ TId_noopmigration: RistrettoPoint,
|
|
|
+}
|
|
|
+
|
|
|
+// The userblinding ZKP
|
|
|
+define_proof! {
|
|
|
+ userblinding,
|
|
|
+ "Open Invitation User Blinding",
|
|
|
+ (d, eid_client, id_client),
|
|
|
+ (EncIdClient0, EncIdClient1, D),
|
|
|
+ (B) :
|
|
|
+ EncIdClient0 = (eid_client*B),
|
|
|
+ EncIdClient1 = (id_client*B + eid_client*D),
|
|
|
+ D = (d*B)
|
|
|
+}
|
|
|
+
|
|
|
+/// Submit an open invitation issued by the BridgeDb to receive your
|
|
|
+/// first Lox credential
|
|
|
+pub fn request(invite: &[u8; super::OPENINV_LENGTH]) -> (Request, State) {
|
|
|
+ let B: &RistrettoPoint = &CMZ_B;
|
|
|
+ let Btable: &RistrettoBasepointTable = &CMZ_B_TABLE;
|
|
|
+
|
|
|
+ // Pick an ElGamal keypair
|
|
|
+ let mut rng = rand::thread_rng();
|
|
|
+ let d = Scalar::random(&mut rng);
|
|
|
+ let D = &d * Btable;
|
|
|
+
|
|
|
+ // Pick a random client component of the id
|
|
|
+ let id_client = Scalar::random(&mut rng);
|
|
|
+
|
|
|
+ // Encrypt it (times the basepoint B) to the ElGamal public key D we
|
|
|
+ // just created
|
|
|
+ let eid_client = Scalar::random(&mut rng);
|
|
|
+ let EncIdClient = (&eid_client * Btable, &id_client * Btable + eid_client * D);
|
|
|
+
|
|
|
+ // Construct the proof of correct user blinding
|
|
|
+ let mut transcript = Transcript::new(b"open invite user blinding");
|
|
|
+ let piUserBlinding = userblinding::prove_compact(
|
|
|
+ &mut transcript,
|
|
|
+ userblinding::ProveAssignments {
|
|
|
+ B: &B,
|
|
|
+ EncIdClient0: &EncIdClient.0,
|
|
|
+ EncIdClient1: &EncIdClient.1,
|
|
|
+ D: &D,
|
|
|
+ d: &d,
|
|
|
+ eid_client: &eid_client,
|
|
|
+ id_client: &id_client,
|
|
|
+ },
|
|
|
+ )
|
|
|
+ .0;
|
|
|
+ (
|
|
|
+ Request {
|
|
|
+ invite: *invite,
|
|
|
+ D,
|
|
|
+ EncIdClient,
|
|
|
+ piUserBlinding,
|
|
|
+ },
|
|
|
+ State {
|
|
|
+ d,
|
|
|
+ D,
|
|
|
+ EncIdClient,
|
|
|
+ id_client,
|
|
|
+ },
|
|
|
+ )
|
|
|
+}
|