]> Git Repo - VerusCoin.git/commitdiff
Enforce first four bits are zero for all spending keys and phi.
authorSean Bowe <[email protected]>
Mon, 16 May 2016 15:50:31 +0000 (09:50 -0600)
committerSean Bowe <[email protected]>
Tue, 24 May 2016 17:07:09 +0000 (11:07 -0600)
15 files changed:
src/Makefile.am
src/gtest/test_joinsplit.cpp
src/gtest/test_noteencryption.cpp
src/uint252.h [new file with mode: 0644]
src/zcash/Address.cpp
src/zcash/Address.hpp
src/zcash/JoinSplit.cpp
src/zcash/JoinSplit.hpp
src/zcash/NoteEncryption.cpp
src/zcash/NoteEncryption.hpp
src/zcash/circuit/gadget.tcc
src/zcash/circuit/note.tcc
src/zcash/circuit/utils.tcc
src/zcash/prf.cpp
src/zcash/prf.h

index 6cb0f89b31d9cd1c2feccdff7fa52e464180c0bb..a6966b0120c12d7ade5cf9fb783e05fdfe67e1bd 100644 (file)
@@ -155,6 +155,7 @@ BITCOIN_CORE_H = \
   txmempool.h \
   ui_interface.h \
   uint256.h \
+  uint252.h \
   undo.h \
   util.h \
   utilmoneystr.h \
index 96e887e77babd9b97a62dc0d1c6506f957db1044..7711dc998e360919da1194e08b6cfb458ab9be44 100644 (file)
@@ -257,7 +257,7 @@ TEST(joinsplit, full_api_test)
 
 TEST(joinsplit, note_plaintexts)
 {
-    uint256 a_sk = uint256S("f6da8716682d600f74fc16bd0187faad6a26b4aa4c24d5c055b216d94516847e");
+    uint252 a_sk = uint252(uint256S("f6da8716682d600f74fc16bd0187faad6a26b4aa4c24d5c055b216d94516840e"));
     uint256 a_pk = PRF_addr_a_pk(a_sk);
     uint256 sk_enc = ZCNoteEncryption::generate_privkey(a_sk);
     uint256 pk_enc = ZCNoteEncryption::generate_pubkey(sk_enc);
index bd4ca38ff1990f8d21835d05940a65e6da0174ae..29c44f37b5f0f0360b4643027ae96f37189129d2 100644 (file)
@@ -18,7 +18,7 @@ public:
 
 TEST(noteencryption, api)
 {
-    uint256 sk_enc = ZCNoteEncryption::generate_privkey(uint256S("21035d60bc1983e37950ce4803418a8fb33ea68d5b937ca382ecbae7564d6a77"));
+    uint256 sk_enc = ZCNoteEncryption::generate_privkey(uint252(uint256S("21035d60bc1983e37950ce4803418a8fb33ea68d5b937ca382ecbae7564d6a07")));
     uint256 pk_enc = ZCNoteEncryption::generate_pubkey(sk_enc);
 
     ZCNoteEncryption b = ZCNoteEncryption(uint256());
@@ -66,7 +66,7 @@ TEST(noteencryption, api)
 
         {
             // Test wrong private key
-            uint256 sk_enc_2 = ZCNoteEncryption::generate_privkey(uint256());
+            uint256 sk_enc_2 = ZCNoteEncryption::generate_privkey(uint252());
             ZCNoteDecryption decrypter(sk_enc_2);
 
             ASSERT_THROW(decrypter.decrypt(ciphertext, b.get_epk(), uint256(), i), std::runtime_error);
@@ -100,9 +100,10 @@ TEST(noteencryption, api)
 
 uint256 test_prf(
     unsigned char distinguisher,
-    uint25x,
+    uint252 seed_x,
     uint256 y
 ) {
+    uint256 x = seed_x.inner();
     *x.begin() &= 0x0f;
     *x.begin() |= distinguisher;
     CSHA256 hasher;
@@ -117,7 +118,7 @@ uint256 test_prf(
 TEST(noteencryption, prf_addr)
 {
     for (size_t i = 0; i < 100; i++) {
-        uint256 a_sk = libzcash::random_uint256();
+        uint252 a_sk = libzcash::random_uint252();
         uint256 rest;
         ASSERT_TRUE(
             test_prf(0xc0, a_sk, rest) == PRF_addr_a_pk(a_sk)
@@ -125,7 +126,7 @@ TEST(noteencryption, prf_addr)
     }
 
     for (size_t i = 0; i < 100; i++) {
-        uint256 a_sk = libzcash::random_uint256();
+        uint252 a_sk = libzcash::random_uint252();
         uint256 rest;
         *rest.begin() = 0x01;
         ASSERT_TRUE(
@@ -137,7 +138,7 @@ TEST(noteencryption, prf_addr)
 TEST(noteencryption, prf_nf)
 {
     for (size_t i = 0; i < 100; i++) {
-        uint256 a_sk = libzcash::random_uint256();
+        uint252 a_sk = libzcash::random_uint252();
         uint256 rho = libzcash::random_uint256();
         ASSERT_TRUE(
             test_prf(0xe0, a_sk, rho) == PRF_nf(a_sk, rho)
@@ -148,7 +149,7 @@ TEST(noteencryption, prf_nf)
 TEST(noteencryption, prf_pk)
 {
     for (size_t i = 0; i < 100; i++) {
-        uint256 a_sk = libzcash::random_uint256();
+        uint252 a_sk = libzcash::random_uint252();
         uint256 h_sig = libzcash::random_uint256();
         ASSERT_TRUE(
             test_prf(0x00, a_sk, h_sig) == PRF_pk(a_sk, 0, h_sig)
@@ -156,21 +157,22 @@ TEST(noteencryption, prf_pk)
     }
 
     for (size_t i = 0; i < 100; i++) {
-        uint256 a_sk = libzcash::random_uint256();
+        uint252 a_sk = libzcash::random_uint252();
         uint256 h_sig = libzcash::random_uint256();
         ASSERT_TRUE(
             test_prf(0x40, a_sk, h_sig) == PRF_pk(a_sk, 1, h_sig)
         );
     }
 
-    uint256 dummy;
-    ASSERT_THROW(PRF_pk(dummy, 2, dummy), std::domain_error);
+    uint252 dummy_a;
+    uint256 dummy_b;
+    ASSERT_THROW(PRF_pk(dummy_a, 2, dummy_b), std::domain_error);
 }
 
 TEST(noteencryption, prf_rho)
 {
     for (size_t i = 0; i < 100; i++) {
-        uint256 phi = libzcash::random_uint256();
+        uint252 phi = libzcash::random_uint252();
         uint256 h_sig = libzcash::random_uint256();
         ASSERT_TRUE(
             test_prf(0x20, phi, h_sig) == PRF_rho(phi, 0, h_sig)
@@ -178,13 +180,19 @@ TEST(noteencryption, prf_rho)
     }
 
     for (size_t i = 0; i < 100; i++) {
-        uint256 phi = libzcash::random_uint256();
+        uint252 phi = libzcash::random_uint252();
         uint256 h_sig = libzcash::random_uint256();
         ASSERT_TRUE(
             test_prf(0x60, phi, h_sig) == PRF_rho(phi, 1, h_sig)
         );
     }
 
-    uint256 dummy;
-    ASSERT_THROW(PRF_rho(dummy, 2, dummy), std::domain_error);
+    uint252 dummy_a;
+    uint256 dummy_b;
+    ASSERT_THROW(PRF_rho(dummy_a, 2, dummy_b), std::domain_error);
 }
+
+TEST(noteencryption, uint252)
+{
+    ASSERT_THROW(uint252(uint256S("f6da8716682d600f74fc16bd0187faad6a26b4aa4c24d5c055b216d94516847e")), std::domain_error);
+}
\ No newline at end of file
diff --git a/src/uint252.h b/src/uint252.h
new file mode 100644 (file)
index 0000000..c5ab1a3
--- /dev/null
@@ -0,0 +1,48 @@
+#ifndef UINT252_H
+#define UINT252_H
+
+#include <vector>
+#include "uint256.h"
+#include "serialize.h"
+
+// Wrapper of uint256 with guarantee that first
+// four bits are zero.
+class uint252 {
+private:
+    uint256 contents;
+
+public:
+    ADD_SERIALIZE_METHODS;
+
+    template <typename Stream, typename Operation>
+    inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) {
+        READWRITE(contents);
+
+        if ((*contents.begin()) & 0xF0) {
+            throw std::ios_base::failure("spending key has invalid leading bits");
+        }
+    }
+
+    const unsigned char* begin() const
+    {
+        return contents.begin();
+    }
+
+    const unsigned char* end() const
+    {
+        return contents.end();
+    }
+
+    uint252() : contents() {};
+    explicit uint252(const uint256& in) : contents(in) {
+        if (*contents.begin() & 0xF0) {
+            throw std::domain_error("leading bits are set in argument given to uint252 constructor");
+        }
+    }
+
+    uint256 inner() const {
+        return contents;
+    }
+};
+
+#endif
index d7438ee2b47c7306ee8f780cf6ad6bb1a657c264..446a63db157a58ca5f48756c52cd6f7897997e17 100644 (file)
@@ -13,7 +13,7 @@ ViewingKey SpendingKey::viewing_key() {
 }
 
 SpendingKey SpendingKey::random() {
-    return SpendingKey(random_uint256());
+    return SpendingKey(random_uint252());
 }
 
 PaymentAddress SpendingKey::address() {
index a240ace7f1ac1d0ffacec73756c83783655f2e62..91e35bd03147ab7d547a22d01ecb65cea9b2bcb6 100644 (file)
@@ -2,6 +2,7 @@
 #define _ZCADDRESS_H_
 
 #include "uint256.h"
+#include "uint252.h"
 #include "serialize.h"
 
 namespace libzcash {
@@ -37,10 +38,10 @@ public:
     uint256 pk_enc();
 };
 
-class SpendingKey : public uint256 {
+class SpendingKey : public uint252 {
 public:
-    SpendingKey() : uint256() { }
-    SpendingKey(uint256 a_sk) : uint256(a_sk) { }
+    SpendingKey() : uint252() { }
+    SpendingKey(uint252 a_sk) : uint252(a_sk) { }
 
     static SpendingKey random();
 
index 05da1e87af7b458592f732c5fd7fb9bfc2ac079d..72a634b1908482fa57f22620a019b7fea6380d92 100644 (file)
@@ -191,7 +191,7 @@ public:
         uint256 h_sig = this->h_sig(out_randomSeed, out_nullifiers, pubKeyHash);
 
         // Sample phi
-        uint256 phi = random_uint256();
+        uint252 phi = random_uint252();
 
         // Compute notes for outputs
         for (size_t i = 0; i < NumOutputs; i++) {
@@ -320,19 +320,19 @@ uint256 JoinSplit<NumInputs, NumOutputs>::h_sig(
     return output;
 }
 
-Note JSOutput::note(const uint256& phi, const uint256& r, size_t i, const uint256& h_sig) const {
+Note JSOutput::note(const uint252& phi, const uint256& r, size_t i, const uint256& h_sig) const {
     uint256 rho = PRF_rho(phi, i, h_sig);
 
     return Note(addr.a_pk, value, rho, r);
 }
 
 JSOutput::JSOutput() : addr(uint256(), uint256()), value(0) {
-    SpendingKey a_sk(random_uint256());
+    SpendingKey a_sk = SpendingKey::random();
     addr = a_sk.address();
 }
 
 JSInput::JSInput() : witness(ZCIncrementalMerkleTree().witness()),
-                     key(random_uint256()) {
+                     key(SpendingKey::random()) {
     note = Note(key.address().a_pk, 0, random_uint256(), random_uint256());
     ZCIncrementalMerkleTree dummy_tree;
     dummy_tree.append(note.cm());
index bd06c7ecbd6c37c7badccd3c77d6e359bcb42898..bf824e1cb0d2a14d80d44dac8578a80a16a89267 100644 (file)
@@ -8,6 +8,7 @@
 #include "NoteEncryption.hpp"
 
 #include "uint256.h"
+#include "uint252.h"
 
 #include <boost/array.hpp>
 
@@ -37,7 +38,7 @@ public:
     JSOutput();
     JSOutput(PaymentAddress addr, uint64_t value) : addr(addr), value(value) { }
 
-    Note note(const uint256& phi, const uint256& r, size_t i, const uint256& h_sig) const;
+    Note note(const uint252& phi, const uint256& r, size_t i, const uint256& h_sig) const;
 };
 
 template<size_t NumInputs, size_t NumOutputs>
index f7d0977dc0664e2540155b6830ca56bcf58feab6..812dd22b5b75c665a789fd07d826e0aad15e1e17 100644 (file)
@@ -136,7 +136,7 @@ typename NoteDecryption<MLEN>::Plaintext NoteDecryption<MLEN>::decrypt
 }
 
 template<size_t MLEN>
-uint256 NoteEncryption<MLEN>::generate_privkey(const uint256 &a_sk)
+uint256 NoteEncryption<MLEN>::generate_privkey(const uint252 &a_sk)
 {
     uint256 sk = PRF_addr_sk_enc(a_sk);
 
@@ -165,6 +165,14 @@ uint256 random_uint256()
     return ret;
 }
 
+uint252 random_uint252()
+{
+    uint256 rand = random_uint256();
+    (*rand.begin()) &= 0x0F;
+
+    return uint252(rand);
+}
+
 template class NoteEncryption<ZC_NOTEPLAINTEXT_LEADING + ZC_V_SIZE + ZC_RHO_SIZE + ZC_R_SIZE + ZC_MEMO_SIZE>;
 template class NoteDecryption<ZC_NOTEPLAINTEXT_LEADING + ZC_V_SIZE + ZC_RHO_SIZE + ZC_R_SIZE + ZC_MEMO_SIZE>;
 
index d5a831ad5a1a7ff5f1cbf09da18d2cb392b8fac6..ac8fb321fb883f5e3ecd45086ed7fd82931161af 100644 (file)
@@ -8,6 +8,7 @@ https://github.com/zcash/zips/blob/master/protocol/protocol.pdf
 
 #include <boost/array.hpp>
 #include "uint256.h"
+#include "uint252.h"
 
 #include "zcash/Zcash.h"
 
@@ -43,7 +44,7 @@ public:
                       );
 
     // Creates a NoteEncryption private key
-    static uint256 generate_privkey(const uint256 &a_sk);
+    static uint256 generate_privkey(const uint252 &a_sk);
 
     // Creates a NoteEncryption public key from a private key
     static uint256 generate_pubkey(const uint256 &sk_enc);
@@ -70,6 +71,7 @@ public:
 };
 
 uint256 random_uint256();
+uint252 random_uint252();
 
 }
 
index a79ad75c6cb38aed800936e71bcd15169d328e98..141ec834ef3f546d79cdee867114771bfbed2127 100644 (file)
@@ -187,7 +187,7 @@ public:
     }
 
     void generate_r1cs_witness(
-        const uint256& phi,
+        const uint252& phi,
         const uint256& rt,
         const uint256& h_sig,
         const boost::array<JSInput, NumInputs>& inputs,
@@ -234,7 +234,7 @@ public:
         // Witness phi
         zk_phi->bits.fill_with_bits(
             this->pb,
-            trailing252(uint256_to_bool_vector(phi))
+            uint252_to_bool_vector(phi)
         );
 
         // Witness h_sig
index c011db175e0186cad903120ab916d646ff6d0be5..87912b348e470cfa9a21a73ae83cdecb59a62e02 100644 (file)
@@ -131,7 +131,7 @@ public:
         // Witness a_sk for the input
         a_sk->bits.fill_with_bits(
             this->pb,
-            trailing252(uint256_to_bool_vector(key))
+            uint252_to_bool_vector(key)
         );
 
         // Witness a_pk for a_sk with PRF_addr
index 24ffe1b94c4ad9284c410aeffaa390a2c84530f4..c54abc56b34a1e1f8b9e7777f4428b6d15a4dce3 100644 (file)
@@ -1,3 +1,5 @@
+#include "uint252.h"
+
 template<typename FieldT>
 pb_variable_array<FieldT> from_bits(std::vector<bool> bits, pb_variable<FieldT>& ZERO) {
     pb_variable_array<FieldT> acc;
@@ -17,7 +19,8 @@ std::vector<bool> trailing252(std::vector<bool> input) {
     return std::vector<bool>(input.begin() + 4, input.end());
 }
 
-std::vector<bool> uint256_to_bool_vector(uint256 input) {
+template<typename T>
+std::vector<bool> to_bool_vector(T input) {
     std::vector<unsigned char> input_v(input.begin(), input.end());
     std::vector<bool> output_bv(256, 0);
     libzerocash::convertBytesVectorToVector(
@@ -28,6 +31,14 @@ std::vector<bool> uint256_to_bool_vector(uint256 input) {
     return output_bv;
 }
 
+std::vector<bool> uint256_to_bool_vector(uint256 input) {
+    return to_bool_vector(input);
+}
+
+std::vector<bool> uint252_to_bool_vector(uint252 input) {
+    return trailing252(to_bool_vector(input));
+}
+
 std::vector<bool> uint64_to_bool_vector(uint64_t input) {
     auto num_bv = convertIntToVectorLE(input);
     std::vector<bool> num_v(64, 0);
index a3fcdfe322be3821c64b432ca8d4b3ccd02369ef..d0f1dc4ec83ad321934e27e24b7d7ba5e4d6cb2b 100644 (file)
@@ -2,7 +2,7 @@
 #include "crypto/sha256.h"
 
 uint256 PRF(bool a, bool b, bool c, bool d,
-            const uint256& x,
+            const uint252& x,
             const uint256& y)
 {
     uint256 res;
@@ -21,7 +21,7 @@ uint256 PRF(bool a, bool b, bool c, bool d,
     return res;
 }
 
-uint256 PRF_addr(const uint256& a_sk, unsigned char t)
+uint256 PRF_addr(const uint252& a_sk, unsigned char t)
 {
     uint256 y;
     *(y.begin()) = t;
@@ -29,22 +29,22 @@ uint256 PRF_addr(const uint256& a_sk, unsigned char t)
     return PRF(1, 1, 0, 0, a_sk, y);
 }
 
-uint256 PRF_addr_a_pk(const uint256& a_sk)
+uint256 PRF_addr_a_pk(const uint252& a_sk)
 {
     return PRF_addr(a_sk, 0);
 }
 
-uint256 PRF_addr_sk_enc(const uint256& a_sk)
+uint256 PRF_addr_sk_enc(const uint252& a_sk)
 {
     return PRF_addr(a_sk, 1);
 }
 
-uint256 PRF_nf(const uint256& a_sk, const uint256& rho)
+uint256 PRF_nf(const uint252& a_sk, const uint256& rho)
 {
     return PRF(1, 1, 1, 0, a_sk, rho);
 }
 
-uint256 PRF_pk(const uint256& a_sk, size_t i0, const uint256& h_sig)
+uint256 PRF_pk(const uint252& a_sk, size_t i0, const uint256& h_sig)
 {
     if ((i0 != 0) && (i0 != 1)) {
         throw std::domain_error("PRF_pk invoked with index out of bounds");
@@ -53,7 +53,7 @@ uint256 PRF_pk(const uint256& a_sk, size_t i0, const uint256& h_sig)
     return PRF(0, i0, 0, 0, a_sk, h_sig);
 }
 
-uint256 PRF_rho(const uint256& phi, size_t i0, const uint256& h_sig)
+uint256 PRF_rho(const uint252& phi, size_t i0, const uint256& h_sig)
 {
     if ((i0 != 0) && (i0 != 1)) {
         throw std::domain_error("PRF_rho invoked with index out of bounds");
index 445a398984ba31d4d21424f7a33599abfe616e85..c6cb45384d461cdd0632cb059850bd7902281fc6 100644 (file)
@@ -7,11 +7,12 @@ within the zkSNARK circuit.
 #define _PRF_H_
 
 #include "uint256.h"
+#include "uint252.h"
 
-uint256 PRF_addr_a_pk(const uint256& a_sk);
-uint256 PRF_addr_sk_enc(const uint256& a_sk);
-uint256 PRF_nf(const uint256& a_sk, const uint256& rho);
-uint256 PRF_pk(const uint256& a_sk, size_t i0, const uint256& h_sig);
-uint256 PRF_rho(const uint256& phi, size_t i0, const uint256& h_sig);
+uint256 PRF_addr_a_pk(const uint252& a_sk);
+uint256 PRF_addr_sk_enc(const uint252& a_sk);
+uint256 PRF_nf(const uint252& a_sk, const uint256& rho);
+uint256 PRF_pk(const uint252& a_sk, size_t i0, const uint256& h_sig);
+uint256 PRF_rho(const uint252& phi, size_t i0, const uint256& h_sig);
 
 #endif // _PRF_H_
This page took 0.05261 seconds and 4 git commands to generate.