Browse Source

Handle (and test) credentials declared in different modules from where a protocol using them is declared

Ian Goldberg 4 months ago
parent
commit
de9d1efc2b
4 changed files with 152 additions and 51 deletions
  1. 45 37
      cmzcred_derive/src/lib.rs
  2. 10 2
      src/lib.rs
  3. 85 0
      tests/submodule.rs
  4. 12 12
      tests/wallet.rs

+ 45 - 37
cmzcred_derive/src/lib.rs

@@ -107,8 +107,8 @@ fn impl_cmzcred_derive(ast: &syn::DeriveInput, group_ident: &Ident) -> TokenStre
                 self
             }
 
-            fn get_pubkey(&self) -> CMZPubkey<Self::Point> {
-                self.pubkey.clone()
+            fn get_pubkey<'a> (&'a self) -> &'a CMZPubkey<Self::Point> {
+                &self.pubkey
             }
 
             fn set_privkey(&mut self, privkey: &CMZPrivkey<Self::Point>) -> &mut Self {
@@ -117,8 +117,16 @@ fn impl_cmzcred_derive(ast: &syn::DeriveInput, group_ident: &Ident) -> TokenStre
                 self
             }
 
-            fn get_privkey(&self) -> CMZPrivkey<Self::Point> {
-                self.privkey.clone()
+            fn get_privkey<'a> (&'a self) -> &'a CMZPrivkey<Self::Point> {
+                &self.privkey
+            }
+
+            fn privkey_x(&self, name: &str) -> Self::Scalar {
+                self.privkey.x[Self::attr_num(name)]
+            }
+
+            fn pubkey_X(&self, name: &str) -> Self::Point {
+                self.pubkey.X[Self::attr_num(name)]
             }
 
             fn gen_keys(rng: &mut impl RngCore, muCMZ: bool) ->
@@ -694,10 +702,10 @@ fn protocol_macro(
         // µCMZ)
         handle_code_post_fill = quote! {
             #handle_code_post_fill
-            if #iss_cred_id.privkey.x.len() != #iss_cred_type::num_attrs() {
+            if #iss_cred_id.get_privkey().x.len() != #iss_cred_type::num_attrs() {
                 return Err(CMZError::PrivkeyMissing(#cred_str));
             }
-            if #iss_cred_id.privkey.muCMZ != #use_muCMZ {
+            if #iss_cred_id.get_privkey().muCMZ != #use_muCMZ {
                 return Err(CMZError::WrongProtocol(#cred_str));
             }
         };
@@ -706,10 +714,10 @@ fn protocol_macro(
         // key set and that it's for the right protocol (CMZ14 or µCMZ)
         prepare_code = quote! {
             #prepare_code
-            if #iss_cred_id.pubkey.X.len() != #iss_cred_type::num_attrs() {
+            if #iss_cred_id.get_pubkey().X.len() != #iss_cred_type::num_attrs() {
                 return Err(CMZError::PubkeyMissing(#cred_str));
             }
-            if #iss_cred_id.pubkey.Xr.is_some() != #use_muCMZ {
+            if #iss_cred_id.get_pubkey().Xr.is_some() != #use_muCMZ {
                 return Err(CMZError::WrongProtocol(#cred_str));
             }
         };
@@ -719,11 +727,11 @@ fn protocol_macro(
         clientstate_fields.push_pubkey(&pubkey_cred);
         prepare_code = quote! {
             #prepare_code
-            let #pubkey_cred = #iss_cred_id.pubkey;
+            let #pubkey_cred = #iss_cred_id.get_pubkey().clone();
         };
         finalize_code = quote! {
             #finalize_code
-            #iss_cred_id.pubkey = self.#pubkey_cred.clone();
+            #iss_cred_id.set_pubkey(&self.#pubkey_cred);
         };
 
         for (attr, &spec) in iss_cred.attrs.iter() {
@@ -754,12 +762,12 @@ fn protocol_macro(
                 // public key
                 handle_code_post_auth = quote! {
                     #handle_code_post_auth
-                    let #x_attr = #iss_cred_id.privkey.x[#iss_cred_type::attr_num(#attr_str)];
-                    let #X_attr = #iss_cred_id.pubkey.X[#iss_cred_type::attr_num(#attr_str)];
+                    let #x_attr = #iss_cred_id.privkey_x(#attr_str);
+                    let #X_attr = #iss_cred_id.pubkey_X(#attr_str);
                 };
                 finalize_code = quote! {
                     #finalize_code
-                    let #X_attr = #iss_cred_id.pubkey.X[#iss_cred_type::attr_num(#attr_str)];
+                    let #X_attr = #iss_cred_id.pubkey_X(#attr_str);
                 };
                 iss_proof_priv_scalars.push(x_attr.clone());
                 iss_proof_pub_points.push(X_attr.clone());
@@ -892,7 +900,7 @@ fn protocol_macro(
                 };
                 handle_code_post_fill = quote! {
                     #handle_code_post_fill
-                    let #X_attr = #iss_cred_id.pubkey.X[#iss_cred_type::attr_num(#attr_str)];
+                    let #X_attr = #iss_cred_id.pubkey_X(#attr_str);
                 };
                 C_statement = quote! {
                     #C_statement + #scoped_attr * #X_attr
@@ -980,7 +988,7 @@ fn protocol_macro(
                     handle_code_post_fill = quote! {
                         #handle_code_post_fill
                         #K_cred += (#scoped_attr *
-                            #iss_cred_id.pubkey.X[#iss_cred_type::attr_num(#attr_str)]);
+                            #iss_cred_id.pubkey_X(#attr_str));
                     };
                     // For a Joint attribute, we only want to use the
                     // issuer's contribution (which is in #scoped_attr),
@@ -994,7 +1002,7 @@ fn protocol_macro(
                     finalize_code = quote! {
                         #finalize_code
                         #K_cred += (#use_attr *
-                            #iss_cred_id.pubkey.X[#iss_cred_type::attr_num(#attr_str)]);
+                            #iss_cred_id.pubkey_X(#attr_str));
                     };
                 } else {
                     /* For each Reveal, Implicit, Set, or Joint attribute, add
@@ -1070,10 +1078,10 @@ fn protocol_macro(
             handle_code_post_auth = quote! {
                 let #b_cred = <Scalar as ff::Field>::random(&mut *rng);
                 let #P_cred = bp.mulB(&#b_cred);
-                let #x0_cred = #iss_cred_id.privkey.x0;
-                let #xr_cred = #iss_cred_id.privkey.xr;
-                let #X0_cred = #iss_cred_id.pubkey.X0.unwrap();
-                let mut #Q_cred = bp.mulB(&(#b_cred * #iss_cred_id.privkey.x0));
+                let #x0_cred = #iss_cred_id.get_privkey().x0;
+                let #xr_cred = #iss_cred_id.get_privkey().xr;
+                let #X0_cred = #iss_cred_id.get_pubkey().X0.unwrap();
+                let mut #Q_cred = bp.mulB(&(#b_cred * #iss_cred_id.get_privkey().x0));
                 #EQ_cred_code_pre
 
                 #handle_code_post_auth
@@ -1094,7 +1102,7 @@ fn protocol_macro(
             finalize_code = quote! {
                 #finalize_code
                 let #P_cred = reply.#P_cred;
-                let #X0_cred = #iss_cred_id.pubkey.X0.unwrap();
+                let #X0_cred = #iss_cred_id.get_pubkey().X0.unwrap();
                 #iss_cred_id.MAC.P = #P_cred;
                 #finalize_Q_code
             };
@@ -1148,7 +1156,7 @@ fn protocol_macro(
                 };
                 handle_code_post_fill = quote! {
                     let #C_cred = request.#C_cred;
-                    let mut #K_cred = #C_cred + #iss_cred_id.pubkey.Xr.unwrap();
+                    let mut #K_cred = #C_cred + #iss_cred_id.get_pubkey().Xr.unwrap();
                     #handle_code_post_fill
                 };
                 finalize_code = quote! {
@@ -1161,7 +1169,7 @@ fn protocol_macro(
                 });
             } else {
                 handle_code_post_fill = quote! {
-                    let mut #K_cred = #iss_cred_id.pubkey.Xr.unwrap();
+                    let mut #K_cred = #iss_cred_id.get_pubkey().Xr.unwrap();
                     #handle_code_post_fill
                 };
                 finalize_code = quote! {
@@ -1173,8 +1181,8 @@ fn protocol_macro(
                 #handle_code_post_auth
                 let #b_cred = <Scalar as ff::Field>::random(&mut *rng);
                 let #P_cred = bp.mulA(&#b_cred);
-                let #x0_cred = #iss_cred_id.privkey.x0;
-                let #X0_cred = #iss_cred_id.pubkey.X0.unwrap();
+                let #x0_cred = #iss_cred_id.get_privkey().x0;
+                let #X0_cred = #iss_cred_id.get_pubkey().X0.unwrap();
                 let #R_cred = #b_cred * (bp.mulA(&#x0_cred) + #K_cred);
             };
             let finalize_Q_code = if cred_hide_joint {
@@ -1189,7 +1197,7 @@ fn protocol_macro(
             finalize_code = quote! {
                 #finalize_code
                 let #P_cred = reply.#P_cred;
-                let #X0_cred = #iss_cred_id.pubkey.X0.unwrap();
+                let #X0_cred = #iss_cred_id.get_pubkey().X0.unwrap();
                 let #R_cred = reply.#R_cred;
                 #iss_cred_id.MAC.P = #P_cred;
                 #finalize_Q_code
@@ -1309,10 +1317,10 @@ fn protocol_macro(
         // µCMZ)
         handle_code_post_fill = quote! {
             #handle_code_post_fill
-            if #show_cred_id.privkey.x.len() != #show_cred_type::num_attrs() {
+            if #show_cred_id.get_privkey().x.len() != #show_cred_type::num_attrs() {
                 return Err(CMZError::PrivkeyMissing(#cred_str));
             }
-            if #show_cred_id.privkey.muCMZ != #use_muCMZ {
+            if #show_cred_id.get_privkey().muCMZ != #use_muCMZ {
                 return Err(CMZError::WrongProtocol(#cred_str));
             }
         };
@@ -1321,10 +1329,10 @@ fn protocol_macro(
         // key set and that it's for the right protocol (CMZ14 or µCMZ)
         prepare_code = quote! {
             #prepare_code
-            if #show_cred_id.pubkey.X.len() != #show_cred_type::num_attrs() {
+            if #show_cred_id.get_pubkey().X.len() != #show_cred_type::num_attrs() {
                 return Err(CMZError::PubkeyMissing(#cred_str));
             }
-            if #show_cred_id.pubkey.Xr.is_some() != #use_muCMZ {
+            if #show_cred_id.get_pubkey().Xr.is_some() != #use_muCMZ {
                 return Err(CMZError::WrongProtocol(#cred_str));
             }
         };
@@ -1366,9 +1374,9 @@ fn protocol_macro(
 
         // µCMZ has the extra xr to add in here
         let q_init = if use_muCMZ {
-            quote! { #show_cred_id.privkey.x0 + #show_cred_id.privkey.xr }
+            quote! { #show_cred_id.get_privkey().x0 + #show_cred_id.get_privkey().xr }
         } else {
-            quote! { #show_cred_id.privkey.x0 }
+            quote! { #show_cred_id.get_privkey().x0 }
         };
         handle_code_post_fill = quote! {
             #handle_code_post_fill
@@ -1409,14 +1417,14 @@ fn protocol_macro(
                     #prepare_code
                     let #z_attr = <Scalar as ff::Field>::random(&mut *rng);
                     let #C_attr = #scoped_attr * #P_cred + bp.mulA(&#z_attr);
-                    let #X_attr = #show_cred_id.pubkey.X[#show_cred_type::attr_num(#attr_str)];
+                    let #X_attr = #show_cred_id.pubkey_X(#attr_str);
                     #V_cred += #z_attr * #X_attr;
                 };
                 handle_code_post_fill = quote! {
                     #handle_code_post_fill
                     let #C_attr = request.#C_attr;
-                    let #X_attr = #show_cred_id.pubkey.X[#show_cred_type::attr_num(#attr_str)];
-                    #V_cred += #show_cred_id.privkey.x[#show_cred_type::attr_num(#attr_str)]
+                    let #X_attr = #show_cred_id.pubkey_X(#attr_str);
+                    #V_cred += #show_cred_id.privkey_x(#attr_str)
                         * #C_attr;
                 };
                 cli_proof_priv_scalars.push(scoped_attr.clone());
@@ -1449,7 +1457,7 @@ fn protocol_macro(
                 handle_code_post_fill = quote! {
                     #handle_code_post_fill
                     #q_cred += #scoped_attr *
-                        #show_cred_id.privkey.x[#show_cred_type::attr_num(#attr_str)];
+                        #show_cred_id.privkey_x(#attr_str);
                 };
             }
 
@@ -1471,7 +1479,7 @@ fn protocol_macro(
                 handle_code_post_fill = quote! {
                     #handle_code_post_fill
                     #q_cred += #scoped_attr *
-                        #show_cred_id.privkey.x[#show_cred_type::attr_num(#attr_str)];
+                        #show_cred_id.privkey_x(#attr_str);
                 };
             }
         }

+ 10 - 2
src/lib.rs

@@ -307,7 +307,7 @@ where
     /// Get a copy of the public key for this credential.  If the public
     /// key has not yet been set or computed, a pubkey with X0 == None
     /// will be returned.
-    fn get_pubkey(&self) -> CMZPubkey<Self::Point>;
+    fn get_pubkey<'a>(&'a self) -> &'a CMZPubkey<Self::Point>;
 
     /// Set the private key for this credential.  The public key will
     /// automatically be computed from the private key.
@@ -316,7 +316,15 @@ where
     /// Get a copy of the private key for this credential.  If the
     /// private key has not yet been set, a privkey with an empty x
     /// vector will be returned.
-    fn get_privkey(&self) -> CMZPrivkey<Self::Point>;
+    fn get_privkey<'a>(&'a self) -> &'a CMZPrivkey<Self::Point>;
+
+    /// Get the element of the privkey x vector associated with the
+    /// given field name
+    fn privkey_x(&self, name: &str) -> Self::Scalar;
+
+    /// Get the element of the pubkey X vector associated with the given
+    /// field name
+    fn pubkey_X(&self, name: &str) -> Self::Point;
 
     /// Generate random private and public keys for this credential
     /// type.  muCMZ should be true if this credential will be issued

+ 85 - 0
tests/submodule.rs

@@ -0,0 +1,85 @@
+#![allow(non_snake_case)]
+
+use cmz::*;
+use curve25519_dalek::ristretto::RistrettoPoint;
+use curve25519_dalek::scalar::Scalar;
+use group::Group;
+use rand_core::RngCore;
+use sha2::Sha512;
+
+pub mod cred {
+    use super::*;
+
+    CMZ! { Basic<RistrettoPoint>: x, y, z }
+}
+
+pub mod submod {
+    use super::cred::Basic;
+    use super::*;
+
+    CMZ14Protocol! { issue_proto,
+        ,
+        N: Basic { x: J, y: H, z: I },
+    }
+
+    CMZ14Protocol! { basic_proto,
+        A: Basic { x: H, y: R, z: I },
+        N: Basic { x: J, y: H, z: I },
+    }
+
+    #[test]
+    fn test_submodule() -> Result<(), CMZError> {
+        let mut rng = rand::thread_rng();
+        cmz_group_init(RistrettoPoint::hash_from_bytes::<Sha512>(
+            b"CMZ Generator A",
+        ));
+
+        let (privkey, pubkey) = Basic::cmz_gen_keys(&mut rng);
+
+        let mut basic_iss = Basic::using_pubkey(&pubkey);
+
+        basic_iss.x = Some(Scalar::ZERO);
+        basic_iss.y = Some(Scalar::ONE);
+        basic_iss.z = Some(Scalar::ONE);
+        let (ireq, istate) = issue_proto::prepare(&mut rng, basic_iss).unwrap();
+
+        let (ireply, _) = issue_proto::handle(
+            &mut rng,
+            ireq,
+            |N: &mut Basic| {
+                N.set_privkey(&privkey);
+                N.z = Some(Scalar::ONE);
+                Ok(())
+            },
+            |_N: &Basic| Ok(()),
+        )?;
+        let basic_cred = match istate.finalize(ireply) {
+            Ok(c) => c,
+            Err((err, _)) => return Err(err),
+        };
+
+        let mut basic_new = Basic::using_pubkey(&pubkey);
+        basic_new.y = Some(2u128.into());
+        basic_new.z = Some(3u128.into());
+
+        let (req, state) = basic_proto::prepare(&mut rng, &basic_cred, basic_new).unwrap();
+
+        let (reply, _) = basic_proto::handle(
+            &mut rng,
+            req,
+            |A: &mut Basic, N: &mut Basic| {
+                A.set_privkey(&privkey);
+                A.z = Some(Scalar::ONE);
+                N.set_privkey(&privkey);
+                N.z = Some(3u128.into());
+                Ok(())
+            },
+            |_A: &Basic, _N: &Basic| Ok(()),
+        )?;
+        let res = state.finalize(reply);
+        match res {
+            Ok(_) => Ok(()),
+            Err((err, _state)) => Err(err),
+        }
+    }
+}

+ 12 - 12
tests/wallet.rs

@@ -28,20 +28,20 @@ macro_rules! protos_def {
         }
 
         $proto_macro! { $wallet_spend,
-          [ W: Wallet { randid: R, balance: H },
-            I: Item { serialno: H, price: H } ],
-          N: Wallet { randid: J, balance: H },
-//          N.balance >= 0,
-          W.balance = N.balance + I.price
-        }
+                  [ W: Wallet { randid: R, balance: H },
+                    I: Item { serialno: H, price: H } ],
+                  N: Wallet { randid: J, balance: H },
+        //          N.balance >= 0,
+                  W.balance = N.balance + I.price
+                }
 
         $proto_macro! { $wallet_spend_with_fee<fee>,
-          [ W: Wallet { randid: R, balance: H },
-            I: Item { serialno: H, price: H } ],
-          N: Wallet { randid: J, balance: H },
- //         N.balance >= 0,
-          W.balance = N.balance + I.price + fee
-        }
+                 [ W: Wallet { randid: R, balance: H },
+                   I: Item { serialno: H, price: H } ],
+                 N: Wallet { randid: J, balance: H },
+        //         N.balance >= 0,
+                 W.balance = N.balance + I.price + fee
+               }
 
         #[test]
         fn $test_wallet() -> Result<(), CMZError> {