From e52f40e83971527c71e895ea81d67c6efa4bf779 Mon Sep 17 00:00:00 2001 From: Sean Bowe Date: Wed, 4 May 2016 18:25:56 -0600 Subject: [PATCH] zkSNARK: Authenticate h_sig with a_sk --- src/zcash/circuit/gadget.tcc | 32 ++++++++++++++++++++++++++++++-- src/zcash/circuit/note.tcc | 5 +++-- src/zcash/circuit/prfs.tcc | 21 +++++++++++++++++++++ 3 files changed, 54 insertions(+), 4 deletions(-) diff --git a/src/zcash/circuit/gadget.tcc b/src/zcash/circuit/gadget.tcc index 0f8d6fa48..84c718f0b 100644 --- a/src/zcash/circuit/gadget.tcc +++ b/src/zcash/circuit/gadget.tcc @@ -23,8 +23,13 @@ private: // Input note gadgets boost::array>, NumInputs> zk_input_notes; + boost::array>, NumInputs> zk_hmac_authentication; public: + // PRF_pk only has a 1-bit domain separation "nonce" + // for different hmacs. + BOOST_STATIC_ASSERT(NumInputs <= 2); + joinsplit_gadget(protoboard &pb) : gadget(pb) { // Verification { @@ -80,6 +85,17 @@ public: ZERO, zk_input_nullifiers[i] )); + + // The input keys authenticate h_sig to prevent + // malleability. + zk_hmac_authentication[i].reset(new PRF_pk_gadget( + pb, + ZERO, + zk_input_notes[i]->a_sk->bits, + zk_h_sig->bits, + i ? true : false, + zk_input_hmacs[i] + )); } } @@ -94,6 +110,9 @@ public: for (size_t i = 0; i < NumInputs; i++) { // Constrain the JoinSplit input constraints. zk_input_notes[i]->generate_r1cs_constraints(); + + // Authenticate h_sig with a_sk + zk_hmac_authentication[i]->generate_r1cs_constraints(); } } @@ -109,9 +128,18 @@ public: // Witness `zero` this->pb.val(ZERO) = FieldT::zero(); + // Witness h_sig + zk_h_sig->bits.fill_with_bits( + this->pb, + uint256_to_bool_vector(h_sig) + ); + for (size_t i = 0; i < NumInputs; i++) { // Witness the input information. zk_input_notes[i]->generate_r1cs_witness(inputs[i].key, inputs[i].note); + + // Witness hmacs + zk_hmac_authentication[i]->generate_r1cs_witness(); } // This happens last, because only by now are all the @@ -131,11 +159,11 @@ public: std::vector verify_inputs; insert_uint256(verify_inputs, uint256()); // TODO: rt - insert_uint256(verify_inputs, uint256()); // TODO: h_sig + insert_uint256(verify_inputs, h_sig); for (size_t i = 0; i < NumInputs; i++) { insert_uint256(verify_inputs, nullifiers[i]); - insert_uint256(verify_inputs, uint256()); // TODO: hmac + insert_uint256(verify_inputs, hmacs[i]); } for (size_t i = 0; i < NumOutputs; i++) { diff --git a/src/zcash/circuit/note.tcc b/src/zcash/circuit/note.tcc index 33987dd3c..e7ad5b88f 100644 --- a/src/zcash/circuit/note.tcc +++ b/src/zcash/circuit/note.tcc @@ -29,13 +29,14 @@ public: template class input_note_gadget : public note_gadget { -public: - std::shared_ptr> a_sk; +private: std::shared_ptr> a_pk; std::shared_ptr> rho; std::shared_ptr> spend_authority; std::shared_ptr> expose_nullifiers; +public: + std::shared_ptr> a_sk; input_note_gadget( protoboard& pb, diff --git a/src/zcash/circuit/prfs.tcc b/src/zcash/circuit/prfs.tcc index 215eebf59..3c03f7983 100644 --- a/src/zcash/circuit/prfs.tcc +++ b/src/zcash/circuit/prfs.tcc @@ -95,3 +95,24 @@ public: PRF_gadget::generate_r1cs_witness(); } }; + +template +class PRF_pk_gadget : public PRF_gadget { +public: + PRF_pk_gadget( + protoboard& pb, + pb_variable& ZERO, + pb_variable_array& a_sk, + pb_variable_array& h_sig, + bool nonce, + std::shared_ptr> result + ) : PRF_gadget(pb, ZERO, 0, nonce, 0, 0, a_sk, h_sig, result) {} + + void generate_r1cs_constraints() { + PRF_gadget::generate_r1cs_constraints(); + } + + void generate_r1cs_witness() { + PRF_gadget::generate_r1cs_witness(); + } +};