Commit 30279d3d authored by onyinyang's avatar onyinyang 🔒
Browse files

Implement uCMZ for trust_promotion

parent da6562fe
Loading
Loading
Loading
Loading
+1 −0
Changes for crates/lox-distributor/src/request_handler.rs: 1 added line, 0 removed lines.
Original line number Diff line number Diff line
@@ -483,6 +483,7 @@ mod tests {
        let trust_result = match proto::trust_promotion::request(
            &lox_cred.lox_credential,
            &pubkeys_obj.lox_pub,
            &pubkeys_obj.migrationkey_pub,
            test_today(31),
        ) {
            Ok(trust_result) => trust_result,
+4 −4
Changes for crates/lox-library/src/migration_table.rs: 4 added lines, 4 removed lines.
Original line number Diff line number Diff line
@@ -33,7 +33,7 @@ use super::cred::Migration;
#[cfg(feature = "bridgeauth")]
use super::IssuerPrivKey;
#[cfg(feature = "bridgeauth")]
use super::CMZ_B_TABLE;
use super::CMZ_A_TABLE;

/// Each (plaintext) entry in the returned migration table is serialized
/// into this many bytes
@@ -94,7 +94,7 @@ pub fn encrypt_cred(
    migration_priv: &IssuerPrivKey,
    migrationkey_priv: &IssuerPrivKey,
) -> ([u8; 16], [u8; ENC_MIGRATION_BYTES]) {
    let Btable: &RistrettoBasepointTable = &CMZ_B_TABLE;
    let Atable: &RistrettoBasepointTable = &CMZ_A_TABLE;

    let mut rng = rand::rngs::OsRng;

@@ -106,14 +106,14 @@ pub fn encrypt_cred(

    // Compute a MAC (P, Q) on the Migration credential
    let b = Scalar::random(&mut rng);
    let P = &b * Btable;
    let P = &b * Atable;
    let Q = &(b
        * (migration_priv.x[0]
            + migration_priv.x[1] * id
            + migration_priv.x[2] * from_bucket
            + migration_priv.x[3] * to_bucket
            + migration_priv.x[4] * migration_type))
        * Btable;
        * Atable;

    // Serialize (to_bucket, P, Q)
    let mut credbytes: [u8; MIGRATION_BYTES] = [0; MIGRATION_BYTES];
+29 −57
Changes for crates/lox-library/src/proto/trust_promotion.rs: 29 added lines, 57 removed lines.
Original line number Diff line number Diff line
@@ -51,7 +51,7 @@ use super::super::pt_dbl;
use super::super::BridgeAuth;
use super::super::IssuerPubKey;
use super::super::{scalar_dbl, scalar_u32};
use super::super::{CMZ_A, CMZ_A_TABLE, CMZ_B, CMZ_B_TABLE};
use super::super::{CMZ_A, CMZ_A_TABLE};

use super::errors::CredentialError;

@@ -75,10 +75,6 @@ pub struct Request {
    CSince: RistrettoPoint,
    CQ: RistrettoPoint,

    // Fields for user blinding of the Migration Key credential
    D: RistrettoPoint,
    EncBucket: (RistrettoPoint, RistrettoPoint),

    // Fields for the inequality proof (level_since +
    // UNTRUSTED_INTERVAL <= today)
    CG1: RistrettoPoint,
@@ -99,15 +95,16 @@ pub struct Request {
    CG7sq: RistrettoPoint,
    CG8sq: RistrettoPoint,

    // Commitment to the the Migration Key credential to be issued
    CommitMigKeyBlind: RistrettoPoint,

    // The combined ZKP
    piUser: CompactProof,
}

#[derive(Debug, Serialize, Deserialize)]
pub struct State {
    d: Scalar,
    D: RistrettoPoint,
    EncBucket: (RistrettoPoint, RistrettoPoint),
    s_mig: Scalar,
    id: Scalar,
    bucket: Scalar,
}
@@ -117,7 +114,7 @@ pub struct State {
pub struct Response {
    // The encrypted MAC for the Migration Key credential
    Pk: RistrettoPoint,
    EncQk: (RistrettoPoint, RistrettoPoint),
    BlindMigKeyQk: RistrettoPoint,

    // A table of encrypted Migration credentials; the encryption keys
    // are formed from the possible values of Qk (the decrypted form of
@@ -130,24 +127,22 @@ define_proof! {
    requestproof,
    "Trust Promotion Request",
    (bucket, since, zbucket, zsince, negzQ,
     d, ebucket,
     s_mig,
     g0, g1, g2, g3, g4, g5, g6, g7, g8,
     zg0, zg1, zg2, zg3, zg4, zg5, zg6, zg7, zg8,
     wg0, wg1, wg2, wg3, wg4, wg5, wg6, wg7, wg8,
     yg0, yg1, yg2, yg3, yg4, yg5, yg6, yg7, yg8),
    (P, CBucket, CSince, V, Xbucket, Xsince,
     D, EncBucket0, EncBucket1,
    (P, CBucket, CSince, V, Xbucket, Xsince, Xmig_bucket,
    CommitMigKeyBlind,
     CG0, CG1, CG2, CG3, CG4, CG5, CG6, CG7, CG8,
     CG0sq, CG1sq, CG2sq, CG3sq, CG4sq, CG5sq, CG6sq, CG7sq, CG8sq),
    (A, B):
    (A):
    // Blind showing of the Lox credential
    CBucket = (bucket*P + zbucket*A),
    CSince = (since*P + zsince*A),
    V = (zbucket*Xbucket + zsince*Xsince + negzQ*A),
    // User blinding of the Migration Key credential
    D = (d*B),
    EncBucket0 = (ebucket*B),
    EncBucket1 = (bucket*B + ebucket*D),
   CommitMigKeyBlind = (s_mig*A + bucket*Xmig_bucket),
    // Prove CSince encodes a value at least UNTRUSTED_INTERVAL
    // days ago (and technically at most UNTRUSTED_INTERVAL+511 days
    // ago): first prove each of g0, ..., g8 is a bit by proving that
@@ -170,12 +165,11 @@ define_proof! {
pub fn request(
    lox_cred: &cred::Lox,
    lox_pub: &IssuerPubKey,
    migkey_pub: &IssuerPubKey,
    today: u32,
) -> Result<(Request, State), CredentialError> {
    let A: &RistrettoPoint = &CMZ_A;
    let B: &RistrettoPoint = &CMZ_B;
    let Atable: &RistrettoBasepointTable = &CMZ_A_TABLE;
    let Btable: &RistrettoBasepointTable = &CMZ_B_TABLE;

    // Ensure the credential can be correctly shown: it must be the case
    // that level_since + UNTRUSTED_INTERVAL <= today.
@@ -223,15 +217,11 @@ pub fn request(
    let V = zbucket * lox_pub.X[2] + zsince * lox_pub.X[4] + &negzQ * Atable;

    // User blinding the Migration Key credential
    let s_mig = Scalar::random(&mut rng);

    // Pick an ElGamal keypair
    let d = Scalar::random(&mut rng);
    let D = &d * Btable;

    // Encrypt the attributes to be blinded (each times the
    // basepoint B) to the public key we just created
    let ebucket = Scalar::random(&mut rng);
    let EncBucket = (&ebucket * Btable, &lox_cred.bucket * Btable + ebucket * D);
    // Commit to the migration key credential values with sum(m_i*X_i) + s * A
    // where A is our generator
    let CommitMigKeyBlind = s_mig * A + (lox_cred.bucket * migkey_pub.X[2]);

    // The range proof that 0 <= diffdays <= 511

@@ -316,16 +306,12 @@ pub fn request(
        &mut transcript,
        requestproof::ProveAssignments {
            A,
            B,
            P: &P,
            CBucket: &CBucket,
            CSince: &CSince,
            V: &V,
            Xbucket: &lox_pub.X[2],
            Xsince: &lox_pub.X[4],
            D: &D,
            EncBucket0: &EncBucket.0,
            EncBucket1: &EncBucket.1,
            CG0: &CG0,
            CG1: &CG1,
            CG2: &CG2,
@@ -349,8 +335,8 @@ pub fn request(
            zbucket: &zbucket,
            zsince: &zsince,
            negzQ: &negzQ,
            d: &d,
            ebucket: &ebucket,
            s_mig: &s_mig,
            Xmig_bucket: &migkey_pub.X[2],
            g0: &g0,
            g1: &g1,
            g2: &g2,
@@ -387,6 +373,7 @@ pub fn request(
            yg6: &yg6,
            yg7: &yg7,
            yg8: &yg8,
            CommitMigKeyBlind: &CommitMigKeyBlind,
        },
    )
    .0;
@@ -398,8 +385,6 @@ pub fn request(
            CBucket,
            CSince,
            CQ,
            D,
            EncBucket,
            CG1,
            CG2,
            CG3,
@@ -417,12 +402,11 @@ pub fn request(
            CG6sq,
            CG7sq,
            CG8sq,
            CommitMigKeyBlind,
            piUser,
        },
        State {
            d,
            D,
            EncBucket,
            s_mig,
            id: lox_cred.id,
            bucket: lox_cred.bucket,
        },
@@ -434,8 +418,7 @@ impl BridgeAuth {
    /// Receive a trust promotion request
    pub fn handle_trust_promotion(&mut self, req: Request) -> Result<Response, ProofError> {
        let A: &RistrettoPoint = &CMZ_A;
        let B: &RistrettoPoint = &CMZ_B;
        let Btable: &RistrettoBasepointTable = &CMZ_B_TABLE;
        let Atable: &RistrettoBasepointTable = &CMZ_A_TABLE;

        if req.P.is_identity() {
            return Err(ProofError::VerificationFailure);
@@ -474,16 +457,13 @@ impl BridgeAuth {
            &mut transcript,
            requestproof::VerifyAssignments {
                A: &A.compress(),
                B: &B.compress(),
                P: &req.P.compress(),
                CBucket: &req.CBucket.compress(),
                CSince: &req.CSince.compress(),
                V: &Vprime.compress(),
                Xbucket: &self.lox_pub.X[2].compress(),
                Xsince: &self.lox_pub.X[4].compress(),
                D: &req.D.compress(),
                EncBucket0: &req.EncBucket.0.compress(),
                EncBucket1: &req.EncBucket.1.compress(),
                Xmig_bucket: &self.migrationkey_pub.X[2].compress(),
                CG0: &CG0prime.compress(),
                CG1: &req.CG1.compress(),
                CG2: &req.CG2.compress(),
@@ -502,6 +482,7 @@ impl BridgeAuth {
                CG6sq: &req.CG6sq.compress(),
                CG7sq: &req.CG7sq.compress(),
                CG8sq: &req.CG8sq.compress(),
                CommitMigKeyBlind: &req.CommitMigKeyBlind.compress(),
            },
        )?;

@@ -520,24 +501,15 @@ impl BridgeAuth {
        // Compute the MAC on the visible attributes
        let mut rng = rand::rngs::OsRng;
        let b = Scalar::random(&mut rng);
        let Pk = &b * Btable;
        let Pk = &b * Atable;
        let Pktable = RistrettoBasepointTable::create(&Pk);
        let Qid = &(self.migrationkey_priv.x[0] + self.migrationkey_priv.x[1] * req.id) * &Pktable;

        // El Gamal encrypt it to the public key req.D
        let s = Scalar::random(&mut rng);
        let EncQkid = (&s * Btable, Qid + s * req.D);

        // Homomorphically compute the part of the MAC corresponding to
        // the blinded attributes
        let tbucket = self.migrationkey_priv.x[2] * b;
        let EncQkBucket = (tbucket * req.EncBucket.0, tbucket * req.EncBucket.1);

        let EncQk = (EncQkid.0 + EncQkBucket.0, EncQkid.1 + EncQkBucket.1);
        let BlindMigKeyQk = b * req.CommitMigKeyBlind + Qid;

        Ok(Response {
            Pk,
            EncQk,
            BlindMigKeyQk,
            enc_migration_table: self.trustup_migration_table.encrypt_table(
                &req.id,
                &self.bridge_table,
@@ -559,8 +531,8 @@ pub fn handle_response(state: State, resp: Response) -> Result<cred::Migration,
        return Err(ProofError::VerificationFailure);
    }

    // Decrypt the MAC on the Migration Key credential
    let Qk = resp.EncQk.1 - (state.d * resp.EncQk.0);
    // Decrypt MAC on BlindMigKeyQ
    let Qk = resp.BlindMigKeyQk - state.s_mig * resp.Pk;

    // Use Qk to locate and decrypt the Migration credential
    match migration_table::decrypt_cred(
+14 −4
Changes for crates/lox-library/src/tests.rs: 14 added lines, 4 removed lines.
Original line number Diff line number Diff line
@@ -179,8 +179,13 @@ impl TestHarness {

    fn trust_promotion(&mut self, cred: &cred::Lox) -> (PerfStat, cred::Migration) {
        let req_start = Instant::now();
        let (promreq, promstate) =
            trust_promotion::request(cred, &self.ba.lox_pub, self.ba.today()).unwrap();
        let (promreq, promstate) = trust_promotion::request(
            cred,
            &self.ba.lox_pub,
            &&self.ba.migrationkey_pub,
            self.ba.today(),
        )
        .unwrap();
        let encoded: Vec<u8> = bincode::serialize(&promreq).unwrap();
        let req_t = req_start.elapsed();
        let req_len = encoded.len();
@@ -797,8 +802,13 @@ fn test_update_cred() {
    th.ba.rotate_lox_keys();

    // Attempt trust promotion with incorrect keys
    let (promreq, _promstate) =
        trust_promotion::request(&cred, &th.ba.lox_pub, th.ba.today()).unwrap();
    let (promreq, _promstate) = trust_promotion::request(
        &cred,
        &th.ba.lox_pub,
        &&th.ba.migrationkey_pub,
        th.ba.today(),
    )
    .unwrap();
    let encoded: Vec<u8> = bincode::serialize(&promreq).unwrap();
    let decoded = bincode::deserialize(&encoded[..]).unwrap();
    let promresp = th.ba.handle_trust_promotion(decoded);
+6 −2
Changes for crates/lox-wasm/src/lib.rs: 6 added lines, 2 removed lines.
Original line number Diff line number Diff line
@@ -117,8 +117,12 @@ pub fn trust_promotion(open_lox_cred: String, lox_pub: String) -> Result<String,
        Ok(pubkeys) => pubkeys,
        Err(e) => return Err(JsValue::from(e.to_string())),
    };
    let tp_result =
        match trust_promotion::request(&lox_cred.lox_credential, &pubkeys.lox_pub, today()) {
    let tp_result = match trust_promotion::request(
        &lox_cred.lox_credential,
        &pubkeys.lox_pub,
        &pubkeys.migrationkey_pub,
        today(),
    ) {
        Ok(tp_result) => tp_result,
        Err(e) => {
            log(&format!("Error: {:?}", e.to_string()));