Browse Source

Generate the issuer proof statement for CMZ14

Ian Goldberg 5 months ago
parent
commit
237c5f8281
1 changed files with 136 additions and 27 deletions
  1. 136 27
      cmzcred_derive/src/lib.rs

+ 136 - 27
cmzcred_derive/src/lib.rs

@@ -546,6 +546,7 @@ fn protocol_macro(
     // The structure of the issuer's ZKP
     let mut iss_proof_rand_scalars = Vec::<Ident>::default();
     let mut iss_proof_priv_scalars = Vec::<Ident>::default();
+    let mut iss_proof_pub_scalars = Vec::<Ident>::default();
     let mut iss_proof_pub_points = Vec::<Ident>::default();
     let mut iss_proof_const_points = Vec::<Ident>::default();
     // Use quote! {} to enforce the correct type for
@@ -591,6 +592,7 @@ fn protocol_macro(
 
     let A_ident = format_ident!("A_generator");
     let B_ident = format_ident!("B_generator");
+    let D_ident = format_ident!("D");
 
     prepare_code = quote! {
         #prepare_code
@@ -639,6 +641,11 @@ fn protocol_macro(
 
         // The encrypted form of the hidden part of the MAC
         let EQ_cred = format_ident!("EQ_iss_cred_{}", iss_cred.id);
+        let EQ0_cred = format_ident!("EQ0_iss_cred_{}", iss_cred.id);
+        let EQ1_cred = format_ident!("EQ1_iss_cred_{}", iss_cred.id);
+        // The ZKP statements that prove the format of EQ_cred
+        let mut eq0_statement = quote! {};
+        let mut eq1_statement = quote! {};
 
         // Only for µCMZ, not CMZ14:
 
@@ -697,10 +704,34 @@ fn protocol_macro(
             // The scoped attribute name
             let scoped_attr = format_ident!("iss_{}attr_{}_{}", spec.abbr(), iss_cred.id, attr);
 
+            // The private and public key for this attribute
+            let x_attr = format_ident!("x_{}", scoped_attr);
+            let X_attr = format_ident!("X_{}", scoped_attr);
+
             if spec == IssueSpec::Hide || spec == IssueSpec::Joint {
                 cred_hide_joint = true;
             }
 
+            if !use_muCMZ {
+                // For CMZ14, we prove that the encrypted MAC is
+                // consistent with all components of the credential's
+                // 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)];
+                };
+                finalize_code = quote! {
+                    #finalize_code
+                    let #X_attr = #iss_cred_id.pubkey.X[#iss_cred_type::attr_num(#attr_str)];
+                };
+                iss_proof_priv_scalars.push(x_attr.clone());
+                iss_proof_pub_points.push(X_attr.clone());
+                iss_proof_statements.push(quote! {
+                    #X_attr = #x_attr * #A_ident,
+                });
+            }
+
             if spec == IssueSpec::Hide {
                 /* For each Hide attribute, the attribute (passed in the
                    prepare) goes in the ClientState, and from there to
@@ -749,11 +780,33 @@ fn protocol_macro(
                    in the Request, attr in the ClientState, and attr,
                    r_attr, and E_attr in the CliProof.  Add
                    b*x_attr*E_attr to E_Q in handle, for the b chosen on
-                   a per-issued-credential basis below.
+                   a per-issued-credential basis below.  Include x_attr,
+                   X_attr, and t_attr = b*x_attr in IssProof and T_attr
+                   = b*X_attr = t_attr*A in Reply and IssProof.
                 */
                 let enc_attr = format_ident!("E_{}", scoped_attr);
+                let enc0_attr = format_ident!("E0_{}", scoped_attr);
+                let enc1_attr = format_ident!("E1_{}", scoped_attr);
                 let r_attr = format_ident!("r_{}", scoped_attr);
+                let t_attr = format_ident!("t_{}", scoped_attr);
+                let T_attr = format_ident!("T_{}", scoped_attr);
                 request_fields.push_encpoint(&enc_attr.to_string());
+                clientstate_fields.push_encpoint(&enc_attr.to_string());
+                reply_fields.push_point(&T_attr.to_string());
+                iss_proof_priv_scalars.push(t_attr.clone());
+                iss_proof_pub_points.push(T_attr.clone());
+                iss_proof_pub_points.push(enc0_attr.clone());
+                iss_proof_pub_points.push(enc1_attr.clone());
+                iss_proof_statements.push(quote! {
+                    #T_attr = #t_attr * #A_ident,
+                    #T_attr = #b_cred * #X_attr,
+                });
+                eq0_statement = quote! {
+                    #eq0_statement + #t_attr * #enc0_attr
+                };
+                eq1_statement = quote! {
+                    #eq1_statement + #t_attr * #enc1_attr
+                };
                 prepare_code = quote! {
                     #prepare_code
                     let #r_attr = <Scalar as ff::Field>::random(&mut *rng);
@@ -761,14 +814,22 @@ fn protocol_macro(
                         bp.mulB(&#scoped_attr) +
                         #r_attr * D);
                 };
-                let bx_attr = format_ident!("bx_{}", scoped_attr);
                 handle_code_post_auth = quote! {
                     #handle_code_post_auth
 
-                    let #bx_attr = #b_cred * #iss_cred_id.privkey.x[#iss_cred_type::attr_num(#attr_str)];
-                    #EQ_cred.0 += #bx_attr * request.#enc_attr.0;
-                    #EQ_cred.1 += #bx_attr * request.#enc_attr.1;
-                }
+                    let #t_attr = #b_cred * #x_attr;
+                    let #enc0_attr = request.#enc_attr.0;
+                    let #enc1_attr = request.#enc_attr.1;
+                    #EQ_cred.0 += #t_attr * #enc0_attr;
+                    #EQ_cred.1 += #t_attr * #enc1_attr;
+                    let #T_attr = bp.mulA(&#t_attr);
+                };
+                finalize_code = quote! {
+                    #finalize_code
+                    let #T_attr = reply.#T_attr;
+                    let #enc0_attr = self.#enc_attr.0;
+                    let #enc1_attr = self.#enc_attr.1;
+                };
             }
 
             if use_muCMZ && (spec == IssueSpec::Hide || spec == IssueSpec::Joint) {
@@ -872,25 +933,34 @@ fn protocol_macro(
                     */
                     handle_code_post_auth = quote! {
                         #handle_code_post_auth
-                        #Q_cred += (#scoped_attr *
-                            #iss_cred_id.privkey.x[#iss_cred_type::attr_num(#attr_str)])
-                            * #P_cred;
+                        #Q_cred += (#scoped_attr * #x_attr) * #P_cred;
+                    };
+                    finalize_code = quote! {
+                        #finalize_code
+                        let #scoped_attr = #iss_cred_id.#attr.unwrap();
+                    };
+                    eq1_statement = quote! {
+                        #eq1_statement + #x_attr * ( #scoped_attr * #P_cred )
                     };
+                    iss_proof_pub_scalars.push(scoped_attr.clone());
                 }
             }
         }
 
         if !use_muCMZ {
             /* For all Hide and Joint attributes of a single credential to be
-               issued (for CMZ14): the issuer chooses a random b, computes
-               P = b*B, E_Q = (0,b*x_0*B) + \sum_{hide,joint} b*x_attr*E_attr
-               + (0,\sum_{implicit,reveal,set,joint} b*x_attr*attr*B)
-               (note that E_Q and each E_attr are all pairs of Points; the
-               scalar multiplication is componentwise).  Include P, E_Q in
-               Reply. For each such attribute, include t_attr = b*x_attr and
-               T_attr = b*X_attr = t_attr*A in Reply and IssProof.  The client
-               will compute Q = E_Q[1] - d*E_Q[0].
+               issued (for CMZ14): the issuer chooses random b and s, computes
+               P = b*B, E_Q = (s*B,s*D+b*x_0*B) + \sum_{hide,joint}
+               b*x_attr*E_attr + (0,\sum_{implicit,reveal,set,joint}
+               b*x_attr*attr*B) (note that E_Q and each E_attr are all
+               pairs of Points; the scalar multiplication is
+               componentwise).  Include P, E_Q in Reply. The client will
+               compute Q = E_Q[1] - d*E_Q[0].
             */
+            let s_cred = format_ident!("s_iss_cred_{}", iss_cred.id);
+            let x0_cred = format_ident!("x0_iss_cred_{}", iss_cred.id);
+            let xr_cred = format_ident!("xr_cred{}", iss_cred.id);
+            let X0_cred = format_ident!("X0_iss_cred_{}", iss_cred.id);
             reply_fields.push_point(&P_cred.to_string());
             if cred_hide_joint {
                 reply_fields.push_encpoint(&EQ_cred.to_string());
@@ -899,7 +969,9 @@ fn protocol_macro(
             }
             let EQ_cred_code_pre = if cred_hide_joint {
                 quote! {
-                    let mut #EQ_cred = (Point::identity(), Point::identity());
+                    let #s_cred = <Scalar as ff::Field>::random(&mut *rng);
+                    let D = request.D;
+                    let mut #EQ_cred = (bp.mulB(&#s_cred), #s_cred * D);
                 }
             } else {
                 quote! {}
@@ -907,13 +979,26 @@ fn protocol_macro(
             let EQ_cred_code_post = if cred_hide_joint {
                 quote! {
                     #EQ_cred.1 += #Q_cred;
+                    let #EQ0_cred = #EQ_cred.0;
+                    let #EQ1_cred = #EQ_cred.1;
                 }
             } else {
                 quote! {}
             };
+            if cred_hide_joint {
+                iss_proof_pub_points.push(EQ0_cred.clone());
+                iss_proof_pub_points.push(EQ1_cred.clone());
+                iss_proof_statements.push(quote! {
+                    #EQ0_cred = #s_cred * #B_ident #eq0_statement,
+                    #EQ1_cred = #s_cred * #D_ident + #x0_cred * #P_cred #eq1_statement,
+                });
+            }
             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));
                 #EQ_cred_code_pre
 
@@ -923,7 +1008,9 @@ fn protocol_macro(
             };
             let finalize_Q_code = if cred_hide_joint {
                 quote! {
-                    #iss_cred_id.MAC.Q = reply.#EQ_cred.1 - self.d * reply.#EQ_cred.0;
+                    let #EQ0_cred = reply.#EQ_cred.0;
+                    let #EQ1_cred = reply.#EQ_cred.1;
+                    #iss_cred_id.MAC.Q = #EQ1_cred - self.d * #EQ0_cred;
                 }
             } else {
                 quote! {
@@ -933,9 +1020,23 @@ fn protocol_macro(
             finalize_code = quote! {
                 #finalize_code
                 let #P_cred = reply.#P_cred;
+                let #X0_cred = #iss_cred_id.pubkey.X0.unwrap();
                 #iss_cred_id.MAC.P = #P_cred;
                 #finalize_Q_code
             };
+            if cred_hide_joint {
+                iss_proof_rand_scalars.push(s_cred.clone());
+            }
+            iss_proof_pub_points.push(P_cred.clone());
+            iss_proof_priv_scalars.push(x0_cred.clone());
+            iss_proof_rand_scalars.push(xr_cred.clone());
+            iss_proof_pub_points.push(X0_cred.clone());
+            iss_proof_rand_scalars.push(b_cred.clone());
+            iss_proof_const_points.push(A_ident.clone());
+            iss_proof_const_points.push(B_ident.clone());
+            iss_proof_statements.push(quote! {
+                #X0_cred = #x0_cred * #B_ident + #xr_cred * #A_ident,
+            });
         }
 
         if use_muCMZ {
@@ -958,6 +1059,8 @@ fn protocol_macro(
             */
             let R_cred = format_ident!("R_iss_cred_{}", iss_cred.id);
             let s_cred = format_ident!("s_iss_cred_{}", iss_cred.id);
+            let x0_cred = format_ident!("x0_iss_cred_{}", iss_cred.id);
+            let X0_cred = format_ident!("X0_iss_cred_{}", iss_cred.id);
             reply_fields.push_point(&P_cred.to_string());
             reply_fields.push_point(&R_cred.to_string());
             if cred_hide_joint {
@@ -987,8 +1090,6 @@ fn protocol_macro(
                     #finalize_code
                 };
             }
-            let x0_cred = format_ident!("x0_iss_cred_{}", iss_cred.id);
-            let X0_cred = format_ident!("X0_iss_cred_{}", iss_cred.id);
             handle_code_post_auth = quote! {
                 #handle_code_post_auth
                 let #b_cred = <Scalar as ff::Field>::random(&mut *rng);
@@ -1026,7 +1127,7 @@ fn protocol_macro(
             iss_proof_statements.push(quote! {
                 #P_cred = #b_cred * #A_ident,
                 #X0_cred = #x0_cred * #B_ident,
-                #R_cred = #x0_cred * #P_cred + #b_cred * #K_cred
+                #R_cred = #x0_cred * #P_cred + #b_cred * #K_cred,
             });
         }
 
@@ -1039,11 +1140,17 @@ fn protocol_macro(
     */
     if any_hide_joint && !use_muCMZ {
         clientstate_fields.push_scalar("d");
+        clientstate_fields.push_point("D");
         request_fields.push_point("D");
         prepare_code = quote! {
             let (d,D) = bp.keypairB(&mut *rng);
             #prepare_code
-        }
+        };
+        finalize_code = quote! {
+            #finalize_code
+            let #D_ident = self.D;
+        };
+        iss_proof_pub_points.push(D_ident.clone());
     }
 
     if proto_spec.issue_creds.len() > 0 {
@@ -1052,7 +1159,8 @@ fn protocol_macro(
         reply_fields.push_bytevec(&iss_proof_ident.to_string());
         let iss_params_fields = iss_proof_pub_points
             .iter()
-            .chain(iss_proof_const_points.iter());
+            .chain(iss_proof_const_points.iter())
+            .chain(iss_proof_pub_scalars.iter());
         let iss_witness_fields = iss_proof_rand_scalars
             .iter()
             .chain(iss_proof_priv_scalars.iter());
@@ -1070,7 +1178,8 @@ fn protocol_macro(
         };
         let cli_params_fields = iss_proof_pub_points
             .iter()
-            .chain(iss_proof_const_points.iter());
+            .chain(iss_proof_const_points.iter())
+            .chain(iss_proof_pub_scalars.iter());
         finalize_code = quote! {
             #finalize_code
             let iss_proof_params = issuer_proof::Params {
@@ -1369,11 +1478,11 @@ fn protocol_macro(
             sigma_compiler! { issuer_proof<Point>,
                 (#(#iss_proof_rand_scalars),*),
                 (#(#iss_proof_priv_scalars),*),
-                (), // pub_scalars
+                (#(#iss_proof_pub_scalars),*),
                 (), // cind_points
                 (#(#iss_proof_pub_points),*),
                 (#(#iss_proof_const_points),*),
-                #(#iss_proof_statements),*
+                #(#iss_proof_statements)*
             }
         }
     };