NoteEncryption implementation and integration, removal of ECIES and crypto++ dependencies.
This commit is contained in:
parent
b2cf9ba300
commit
6c36a9fe03
|
@ -699,11 +699,6 @@ AC_CHECK_LIB([gmp],[[__gmpn_sub_n]],GMP_LIBS=-lgmp, [AC_MSG_ERROR(libgmp missing
|
||||||
AC_CHECK_HEADER([gmpxx.h],,AC_MSG_ERROR(libgmpxx headers missing))
|
AC_CHECK_HEADER([gmpxx.h],,AC_MSG_ERROR(libgmpxx headers missing))
|
||||||
AC_CHECK_LIB([gmpxx],[main],GMPXX_LIBS=-lgmpxx, [AC_MSG_ERROR(libgmpxx missing)])
|
AC_CHECK_LIB([gmpxx],[main],GMPXX_LIBS=-lgmpxx, [AC_MSG_ERROR(libgmpxx missing)])
|
||||||
|
|
||||||
AC_CHECK_HEADER([cryptopp/eccrypto.h],,AC_MSG_ERROR(libcryptopp headers missing))
|
|
||||||
# We link against "main" as a stop-gap; crypto++ is full of template
|
|
||||||
# classes whose library symbols are mangled by some black alchemy.
|
|
||||||
AC_CHECK_LIB([cryptopp],[main],CRYPTOPP_LIBS=-lcryptopp, [AC_MSG_ERROR(libcryptopp missing)])
|
|
||||||
|
|
||||||
# libsnark header layout is broken unless cpp's -I is passed with the
|
# libsnark header layout is broken unless cpp's -I is passed with the
|
||||||
# libsnark directory, so for now we use this hideous workaround:
|
# libsnark directory, so for now we use this hideous workaround:
|
||||||
echo 'Hunting for libsnark include directory...'
|
echo 'Hunting for libsnark include directory...'
|
||||||
|
@ -720,7 +715,7 @@ CPPFLAGS="-I$LIBSNARK_INCDIR $CPPFLAGS"
|
||||||
AC_CHECK_HEADER([libsnark/gadgetlib1/gadget.hpp],,AC_MSG_ERROR(libsnark headers missing))
|
AC_CHECK_HEADER([libsnark/gadgetlib1/gadget.hpp],,AC_MSG_ERROR(libsnark headers missing))
|
||||||
AC_CHECK_LIB([snark],[main],LIBSNARK_LIBS=-lsnark, [AC_MSG_ERROR(libsnark missing)], [-lgmpxx])
|
AC_CHECK_LIB([snark],[main],LIBSNARK_LIBS=-lsnark, [AC_MSG_ERROR(libsnark missing)], [-lgmpxx])
|
||||||
|
|
||||||
LIBZEROCASH_LIBS="-lsnark -lcryptopp -lgmp -lgmpxx -lboost_system-mt -lcrypto -lsodium"
|
LIBZEROCASH_LIBS="-lsnark -lgmp -lgmpxx -lboost_system-mt -lcrypto -lsodium"
|
||||||
|
|
||||||
AC_CHECK_LIB([crypto],[RAND_egd],[],[
|
AC_CHECK_LIB([crypto],[RAND_egd],[],[
|
||||||
AC_ARG_WITH([libressl],
|
AC_ARG_WITH([libressl],
|
||||||
|
@ -929,7 +924,6 @@ AC_SUBST(MINIUPNPC_CPPFLAGS)
|
||||||
AC_SUBST(MINIUPNPC_LIBS)
|
AC_SUBST(MINIUPNPC_LIBS)
|
||||||
AC_SUBST(GMP_LIBS)
|
AC_SUBST(GMP_LIBS)
|
||||||
AC_SUBST(GMPXX_LIBS)
|
AC_SUBST(GMPXX_LIBS)
|
||||||
AC_SUBST(CRYPTOPP_LIBS)
|
|
||||||
AC_SUBST(LIBSNARK_LIBS)
|
AC_SUBST(LIBSNARK_LIBS)
|
||||||
AC_SUBST(LIBZEROCASH_LIBS)
|
AC_SUBST(LIBZEROCASH_LIBS)
|
||||||
AC_CONFIG_FILES([Makefile src/Makefile share/setup.nsi share/qt/Info.plist src/test/buildenv.py])
|
AC_CONFIG_FILES([Makefile src/Makefile share/setup.nsi share/qt/Info.plist src/test/buildenv.py])
|
||||||
|
|
|
@ -1,20 +0,0 @@
|
||||||
package=crypto++
|
|
||||||
$(package)_version=5.6.2
|
|
||||||
$(package)_download_path=http://www.cryptopp.com/
|
|
||||||
$(package)_file_name=cryptopp562.zip
|
|
||||||
$(package)_sha256_hash=5cbfd2fcb4a6b3aab35902e2e0f3b59d9171fee12b3fc2b363e1801dfec53574
|
|
||||||
$(package)_dependencies=
|
|
||||||
|
|
||||||
# SECURITY BUG: _extract_cmds is responsible for verifying the archive
|
|
||||||
# hash, but does not do so here:
|
|
||||||
define $(package)_extract_cmds
|
|
||||||
unzip $($(package)_source_dir)/$($(package)_file_name)
|
|
||||||
endef
|
|
||||||
|
|
||||||
define $(package)_build_cmds
|
|
||||||
$(MAKE) static CXXFLAGS='-DNDEBUG -g -O2 -fPIC'
|
|
||||||
endef
|
|
||||||
|
|
||||||
define $(package)_stage_cmds
|
|
||||||
$(MAKE) install PREFIX=$($(package)_staging_dir)$(host_prefix)
|
|
||||||
endef
|
|
|
@ -1,4 +1,4 @@
|
||||||
zerocash_packages := libsnark crypto++ libgmp libsodium
|
zerocash_packages := libsnark libgmp libsodium
|
||||||
packages := boost openssl $(zerocash_packages) googletest
|
packages := boost openssl $(zerocash_packages) googletest
|
||||||
native_packages := native_ccache native_comparisontool
|
native_packages := native_ccache native_comparisontool
|
||||||
|
|
||||||
|
|
|
@ -82,7 +82,9 @@ LIBZEROCASH_H = \
|
||||||
zerocash/Zerocash.h \
|
zerocash/Zerocash.h \
|
||||||
zerocash/ZerocashParams.h \
|
zerocash/ZerocashParams.h \
|
||||||
zerocash/zerocash_pour_params.hpp \
|
zerocash/zerocash_pour_params.hpp \
|
||||||
zerocash/utils/util.h
|
zerocash/utils/util.h \
|
||||||
|
zcash/NoteEncryption.hpp \
|
||||||
|
zcash/prf.h
|
||||||
|
|
||||||
.PHONY: FORCE
|
.PHONY: FORCE
|
||||||
# bitcoin core #
|
# bitcoin core #
|
||||||
|
@ -400,7 +402,6 @@ bitcoin_tx_LDADD = \
|
||||||
$(LIBBITCOIN_UNIVALUE) \
|
$(LIBBITCOIN_UNIVALUE) \
|
||||||
$(LIBBITCOIN_COMMON) \
|
$(LIBBITCOIN_COMMON) \
|
||||||
$(LIBBITCOIN_UTIL) \
|
$(LIBBITCOIN_UTIL) \
|
||||||
$(LIBBITCOIN_CRYPTO) \
|
|
||||||
$(LIBSECP256K1) \
|
$(LIBSECP256K1) \
|
||||||
$(LIBZEROCASH) \
|
$(LIBZEROCASH) \
|
||||||
$(LIBBITCOIN_CRYPTO) \
|
$(LIBBITCOIN_CRYPTO) \
|
||||||
|
@ -421,7 +422,9 @@ libzerocash_a_SOURCES = \
|
||||||
zerocash/PourProver.cpp \
|
zerocash/PourProver.cpp \
|
||||||
zerocash/PourTransaction.cpp \
|
zerocash/PourTransaction.cpp \
|
||||||
zerocash/ZerocashParams.cpp \
|
zerocash/ZerocashParams.cpp \
|
||||||
zerocash/utils/util.cpp
|
zerocash/utils/util.cpp \
|
||||||
|
zcash/NoteEncryption.cpp \
|
||||||
|
zcash/prf.cpp
|
||||||
|
|
||||||
libzerocash_a_CPPFLAGS = -fPIC -DCURVE_ALT_BN128 -DBOOST_SPIRIT_THREADSAFE -DHAVE_BUILD_INFO -D__STDC_FORMAT_MACROS -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=2 -std=c++11 -pipe -O2 -O0 -g -Wstack-protector -fstack-protector-all -fPIE -fvisibility=hidden -DSTATIC $(BITCOIN_INCLUDES)
|
libzerocash_a_CPPFLAGS = -fPIC -DCURVE_ALT_BN128 -DBOOST_SPIRIT_THREADSAFE -DHAVE_BUILD_INFO -D__STDC_FORMAT_MACROS -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=2 -std=c++11 -pipe -O2 -O0 -g -Wstack-protector -fstack-protector-all -fPIE -fvisibility=hidden -DSTATIC $(BITCOIN_INCLUDES)
|
||||||
|
|
||||||
|
|
|
@ -56,6 +56,7 @@ BITCOIN_TESTS =\
|
||||||
test/miner_tests.cpp \
|
test/miner_tests.cpp \
|
||||||
test/mruset_tests.cpp \
|
test/mruset_tests.cpp \
|
||||||
test/multisig_tests.cpp \
|
test/multisig_tests.cpp \
|
||||||
|
test/noteencryption_tests.cpp \
|
||||||
test/netbase_tests.cpp \
|
test/netbase_tests.cpp \
|
||||||
test/pmt_tests.cpp \
|
test/pmt_tests.cpp \
|
||||||
test/policyestimator_tests.cpp \
|
test/policyestimator_tests.cpp \
|
||||||
|
|
|
@ -38,6 +38,7 @@ zerocash_tests_zerocashTest_SOURCES = \
|
||||||
zerocash_tests_zerocashTest_LDADD = \
|
zerocash_tests_zerocashTest_LDADD = \
|
||||||
$(BOOST_LIBS) \
|
$(BOOST_LIBS) \
|
||||||
$(LIBZEROCASH) \
|
$(LIBZEROCASH) \
|
||||||
|
$(LIBBITCOIN_UTIL) \
|
||||||
$(LIBBITCOIN_CRYPTO) \
|
$(LIBBITCOIN_CRYPTO) \
|
||||||
$(LIBZEROCASH_LIBS)
|
$(LIBZEROCASH_LIBS)
|
||||||
|
|
||||||
|
@ -47,6 +48,7 @@ zerocash_tests_test_zerocash_pour_ppzksnark_SOURCES = zerocash/tests/test_zeroca
|
||||||
zerocash_tests_test_zerocash_pour_ppzksnark_LDADD = \
|
zerocash_tests_test_zerocash_pour_ppzksnark_LDADD = \
|
||||||
$(BOOST_LIBS) \
|
$(BOOST_LIBS) \
|
||||||
$(LIBZEROCASH) \
|
$(LIBZEROCASH) \
|
||||||
|
$(LIBBITCOIN_UTIL) \
|
||||||
$(LIBBITCOIN_CRYPTO) \
|
$(LIBBITCOIN_CRYPTO) \
|
||||||
$(LIBZEROCASH_LIBS)
|
$(LIBZEROCASH_LIBS)
|
||||||
|
|
||||||
|
|
|
@ -58,14 +58,11 @@ CPourTx::CPourTx(ZerocashParams& params,
|
||||||
boost::array<std::vector<unsigned char>, NUM_POUR_INPUTS> serials_bv;
|
boost::array<std::vector<unsigned char>, NUM_POUR_INPUTS> serials_bv;
|
||||||
boost::array<std::vector<unsigned char>, NUM_POUR_OUTPUTS> commitments_bv;
|
boost::array<std::vector<unsigned char>, NUM_POUR_OUTPUTS> commitments_bv;
|
||||||
boost::array<std::vector<unsigned char>, NUM_POUR_INPUTS> macs_bv;
|
boost::array<std::vector<unsigned char>, NUM_POUR_INPUTS> macs_bv;
|
||||||
boost::array<std::string, NUM_POUR_OUTPUTS> ciphertexts_bv;
|
|
||||||
|
|
||||||
proof = pourtx.unpack(serials_bv, commitments_bv, macs_bv, ciphertexts_bv);
|
proof = pourtx.unpack(serials_bv, commitments_bv, macs_bv, ciphertexts, ephemeralKey);
|
||||||
serials = unsigned_char_vector_array_to_uint256_array(serials_bv);
|
serials = unsigned_char_vector_array_to_uint256_array(serials_bv);
|
||||||
commitments = unsigned_char_vector_array_to_uint256_array(commitments_bv);
|
commitments = unsigned_char_vector_array_to_uint256_array(commitments_bv);
|
||||||
macs = unsigned_char_vector_array_to_uint256_array(macs_bv);
|
macs = unsigned_char_vector_array_to_uint256_array(macs_bv);
|
||||||
|
|
||||||
ciphertexts = ciphertexts_bv;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CPourTx::Verify(ZerocashParams& params) const {
|
bool CPourTx::Verify(ZerocashParams& params) const {
|
||||||
|
|
|
@ -17,6 +17,8 @@
|
||||||
#include "zerocash/PourInput.h"
|
#include "zerocash/PourInput.h"
|
||||||
#include "zerocash/PourOutput.h"
|
#include "zerocash/PourOutput.h"
|
||||||
|
|
||||||
|
#include "zcash/NoteEncryption.hpp"
|
||||||
|
|
||||||
using namespace libzerocash;
|
using namespace libzerocash;
|
||||||
|
|
||||||
static const unsigned int NUM_POUR_INPUTS = 2;
|
static const unsigned int NUM_POUR_INPUTS = 2;
|
||||||
|
@ -58,10 +60,13 @@ public:
|
||||||
boost::array<uint256, NUM_POUR_OUTPUTS> commitments;
|
boost::array<uint256, NUM_POUR_OUTPUTS> commitments;
|
||||||
|
|
||||||
// Ciphertexts
|
// Ciphertexts
|
||||||
// These are encrypted using ECIES. They are used to
|
// These contain trapdoors, values and other information
|
||||||
// transfer metadata and seeds to generate trapdoors
|
// that the recipient needs, including a memo field. It
|
||||||
// for the recipient to spend the value.
|
// is encrypted using the scheme implemented in crypto/NoteEncryption.cpp
|
||||||
boost::array<std::string, NUM_POUR_OUTPUTS> ciphertexts;
|
boost::array<ZCNoteEncryption::Ciphertext, NUM_POUR_OUTPUTS> ciphertexts;
|
||||||
|
|
||||||
|
// Ephemeral key
|
||||||
|
uint256 ephemeralKey;
|
||||||
|
|
||||||
// MACs
|
// MACs
|
||||||
// The verification of the pour requires these MACs
|
// The verification of the pour requires these MACs
|
||||||
|
@ -72,9 +77,7 @@ public:
|
||||||
// This is a zk-SNARK which ensures that this pour is valid.
|
// This is a zk-SNARK which ensures that this pour is valid.
|
||||||
std::string proof;
|
std::string proof;
|
||||||
|
|
||||||
CPourTx(): vpub_old(0), vpub_new(0), scriptPubKey(), scriptSig(), anchor(), serials(), commitments(), ciphertexts(), macs(), proof() {
|
CPourTx(): vpub_old(0), vpub_new(0) { }
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
CPourTx(ZerocashParams& params,
|
CPourTx(ZerocashParams& params,
|
||||||
const CScript& scriptPubKey,
|
const CScript& scriptPubKey,
|
||||||
|
@ -100,6 +103,7 @@ public:
|
||||||
READWRITE(serials);
|
READWRITE(serials);
|
||||||
READWRITE(commitments);
|
READWRITE(commitments);
|
||||||
READWRITE(ciphertexts);
|
READWRITE(ciphertexts);
|
||||||
|
READWRITE(ephemeralKey);
|
||||||
READWRITE(macs);
|
READWRITE(macs);
|
||||||
READWRITE(proof);
|
READWRITE(proof);
|
||||||
}
|
}
|
||||||
|
@ -115,6 +119,7 @@ public:
|
||||||
a.serials == b.serials &&
|
a.serials == b.serials &&
|
||||||
a.commitments == b.commitments &&
|
a.commitments == b.commitments &&
|
||||||
a.ciphertexts == b.ciphertexts &&
|
a.ciphertexts == b.ciphertexts &&
|
||||||
|
a.ephemeralKey == b.ephemeralKey &&
|
||||||
a.macs == b.macs &&
|
a.macs == b.macs &&
|
||||||
a.proof == b.proof
|
a.proof == b.proof
|
||||||
);
|
);
|
||||||
|
|
File diff suppressed because one or more lines are too long
|
@ -0,0 +1,183 @@
|
||||||
|
#include "test/test_bitcoin.h"
|
||||||
|
#include "sodium.h"
|
||||||
|
|
||||||
|
#include <stdexcept>
|
||||||
|
|
||||||
|
#include "zcash/NoteEncryption.hpp"
|
||||||
|
#include "zcash/prf.h"
|
||||||
|
|
||||||
|
#include <boost/test/unit_test.hpp>
|
||||||
|
|
||||||
|
class TestNoteDecryption : public ZCNoteDecryption {
|
||||||
|
public:
|
||||||
|
TestNoteDecryption(uint256 sk_enc) : ZCNoteDecryption(sk_enc) {}
|
||||||
|
|
||||||
|
void change_pk_enc(uint256 to) {
|
||||||
|
pk_enc = to;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
BOOST_FIXTURE_TEST_SUITE(noteencryption_tests, BasicTestingSetup)
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(noteencryption)
|
||||||
|
{
|
||||||
|
uint256 sk_enc = ZCNoteEncryption::generate_privkey(uint256S("21035d60bc1983e37950ce4803418a8fb33ea68d5b937ca382ecbae7564d6a77"));
|
||||||
|
uint256 pk_enc = ZCNoteEncryption::generate_pubkey(sk_enc);
|
||||||
|
|
||||||
|
ZCNoteEncryption b = ZCNoteEncryption(uint256());
|
||||||
|
|
||||||
|
boost::array<unsigned char, 216> message;
|
||||||
|
for (unsigned char i = 0; i < 216; i++) {
|
||||||
|
// Fill the message with dummy data
|
||||||
|
message[i] = (unsigned char) i;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < 255; i++) {
|
||||||
|
auto ciphertext = b.encrypt(pk_enc, message);
|
||||||
|
|
||||||
|
{
|
||||||
|
ZCNoteDecryption decrypter(sk_enc);
|
||||||
|
|
||||||
|
// Test decryption
|
||||||
|
auto plaintext = decrypter.decrypt(ciphertext, b.get_epk(), uint256(), i);
|
||||||
|
BOOST_CHECK(plaintext == message);
|
||||||
|
|
||||||
|
// Test wrong nonce
|
||||||
|
BOOST_CHECK_THROW(decrypter.decrypt(ciphertext, b.get_epk(), uint256(), (i == 0) ? 1 : (i - 1)), std::runtime_error);
|
||||||
|
|
||||||
|
// Test wrong ephemeral key
|
||||||
|
BOOST_CHECK_THROW(decrypter.decrypt(ciphertext, ZCNoteEncryption::generate_privkey(uint256()), uint256(), i), std::runtime_error);
|
||||||
|
|
||||||
|
// Test wrong seed
|
||||||
|
BOOST_CHECK_THROW(decrypter.decrypt(ciphertext, b.get_epk(), uint256S("11035d60bc1983e37950ce4803418a8fb33ea68d5b937ca382ecbae7564d6a77"), i), std::runtime_error);
|
||||||
|
|
||||||
|
// Test corrupted ciphertext
|
||||||
|
ciphertext[10] ^= 0xff;
|
||||||
|
BOOST_CHECK_THROW(decrypter.decrypt(ciphertext, b.get_epk(), uint256(), i), std::runtime_error);
|
||||||
|
ciphertext[10] ^= 0xff;
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
// Test wrong private key
|
||||||
|
uint256 sk_enc_2 = ZCNoteEncryption::generate_privkey(uint256());
|
||||||
|
ZCNoteDecryption decrypter(sk_enc_2);
|
||||||
|
|
||||||
|
BOOST_CHECK_THROW(decrypter.decrypt(ciphertext, b.get_epk(), uint256(), i), std::runtime_error);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
TestNoteDecryption decrypter(sk_enc);
|
||||||
|
|
||||||
|
// Test decryption
|
||||||
|
auto plaintext = decrypter.decrypt(ciphertext, b.get_epk(), uint256(), i);
|
||||||
|
BOOST_CHECK(plaintext == message);
|
||||||
|
|
||||||
|
// Test wrong public key (test of KDF)
|
||||||
|
decrypter.change_pk_enc(uint256());
|
||||||
|
BOOST_CHECK_THROW(decrypter.decrypt(ciphertext, b.get_epk(), uint256(), i), std::runtime_error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Nonce space should run out here
|
||||||
|
BOOST_CHECK_THROW(b.encrypt(pk_enc, message), std::logic_error);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint256 test_prf(
|
||||||
|
unsigned char distinguisher,
|
||||||
|
uint256 x,
|
||||||
|
uint256 y
|
||||||
|
) {
|
||||||
|
*x.begin() &= 0x0f;
|
||||||
|
*x.begin() |= distinguisher;
|
||||||
|
CSHA256 hasher;
|
||||||
|
hasher.Write(x.begin(), 32);
|
||||||
|
hasher.Write(y.begin(), 32);
|
||||||
|
|
||||||
|
uint256 ret;
|
||||||
|
hasher.FinalizeNoPadding(ret.begin());
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(prf_addr)
|
||||||
|
{
|
||||||
|
for (size_t i = 0; i < 100; i++) {
|
||||||
|
uint256 a_sk = libzcash::random_uint256();
|
||||||
|
uint256 rest;
|
||||||
|
BOOST_CHECK_MESSAGE(
|
||||||
|
test_prf(0xc0, a_sk, rest) == PRF_addr_a_pk(a_sk),
|
||||||
|
a_sk.GetHex()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (size_t i = 0; i < 100; i++) {
|
||||||
|
uint256 a_sk = libzcash::random_uint256();
|
||||||
|
uint256 rest;
|
||||||
|
*rest.begin() = 0x01;
|
||||||
|
BOOST_CHECK_MESSAGE(
|
||||||
|
test_prf(0xc0, a_sk, rest) == PRF_addr_sk_enc(a_sk),
|
||||||
|
a_sk.GetHex()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(prf_nf)
|
||||||
|
{
|
||||||
|
for (size_t i = 0; i < 100; i++) {
|
||||||
|
uint256 a_sk = libzcash::random_uint256();
|
||||||
|
uint256 rho = libzcash::random_uint256();
|
||||||
|
BOOST_CHECK_MESSAGE(
|
||||||
|
test_prf(0xe0, a_sk, rho) == PRF_nf(a_sk, rho),
|
||||||
|
a_sk.GetHex() + " and " + rho.GetHex()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(prf_pk)
|
||||||
|
{
|
||||||
|
for (size_t i = 0; i < 100; i++) {
|
||||||
|
uint256 a_sk = libzcash::random_uint256();
|
||||||
|
uint256 h_sig = libzcash::random_uint256();
|
||||||
|
BOOST_CHECK_MESSAGE(
|
||||||
|
test_prf(0x00, a_sk, h_sig) == PRF_pk(a_sk, 0, h_sig),
|
||||||
|
a_sk.GetHex() + " and " + h_sig.GetHex()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (size_t i = 0; i < 100; i++) {
|
||||||
|
uint256 a_sk = libzcash::random_uint256();
|
||||||
|
uint256 h_sig = libzcash::random_uint256();
|
||||||
|
BOOST_CHECK_MESSAGE(
|
||||||
|
test_prf(0x40, a_sk, h_sig) == PRF_pk(a_sk, 1, h_sig),
|
||||||
|
a_sk.GetHex() + " and " + h_sig.GetHex()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint256 dummy;
|
||||||
|
BOOST_CHECK_THROW(PRF_pk(dummy, 2, dummy), std::domain_error);
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(prf_rho)
|
||||||
|
{
|
||||||
|
for (size_t i = 0; i < 100; i++) {
|
||||||
|
uint256 phi = libzcash::random_uint256();
|
||||||
|
uint256 h_sig = libzcash::random_uint256();
|
||||||
|
BOOST_CHECK_MESSAGE(
|
||||||
|
test_prf(0x20, phi, h_sig) == PRF_rho(phi, 0, h_sig),
|
||||||
|
phi.GetHex() + " and " + h_sig.GetHex()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (size_t i = 0; i < 100; i++) {
|
||||||
|
uint256 phi = libzcash::random_uint256();
|
||||||
|
uint256 h_sig = libzcash::random_uint256();
|
||||||
|
BOOST_CHECK_MESSAGE(
|
||||||
|
test_prf(0x60, phi, h_sig) == PRF_rho(phi, 1, h_sig),
|
||||||
|
phi.GetHex() + " and " + h_sig.GetHex()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint256 dummy;
|
||||||
|
BOOST_CHECK_THROW(PRF_rho(dummy, 2, dummy), std::domain_error);
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_SUITE_END()
|
|
@ -129,6 +129,7 @@ void static RandomTransaction(CMutableTransaction &tx, bool fSingle) {
|
||||||
pourtx.anchor = GetRandHash();
|
pourtx.anchor = GetRandHash();
|
||||||
pourtx.serials[0] = GetRandHash();
|
pourtx.serials[0] = GetRandHash();
|
||||||
pourtx.serials[1] = GetRandHash();
|
pourtx.serials[1] = GetRandHash();
|
||||||
|
pourtx.ephemeralKey = GetRandHash();
|
||||||
pourtx.ciphertexts[0] = {insecure_rand() % 100, insecure_rand() % 100};
|
pourtx.ciphertexts[0] = {insecure_rand() % 100, insecure_rand() % 100};
|
||||||
pourtx.ciphertexts[1] = {insecure_rand() % 100, insecure_rand() % 100};
|
pourtx.ciphertexts[1] = {insecure_rand() % 100, insecure_rand() % 100};
|
||||||
pourtx.macs[0] = GetRandHash();
|
pourtx.macs[0] = GetRandHash();
|
||||||
|
|
|
@ -2454,8 +2454,8 @@ Value zc_raw_receive(const json_spirit::Array& params, bool fHelp)
|
||||||
|
|
||||||
LOCK(cs_main);
|
LOCK(cs_main);
|
||||||
|
|
||||||
std::vector<unsigned char> a_sk;
|
uint256 a_sk;
|
||||||
std::string sk_enc;
|
uint256 sk_enc;
|
||||||
|
|
||||||
{
|
{
|
||||||
CDataStream ssData(ParseHexV(params[0], "zcsecretkey"), SER_NETWORK, PROTOCOL_VERSION);
|
CDataStream ssData(ParseHexV(params[0], "zcsecretkey"), SER_NETWORK, PROTOCOL_VERSION);
|
||||||
|
@ -2472,9 +2472,24 @@ Value zc_raw_receive(const json_spirit::Array& params, bool fHelp)
|
||||||
libzerocash::PrivateAddress zcsecretkey(a_sk, sk_enc);
|
libzerocash::PrivateAddress zcsecretkey(a_sk, sk_enc);
|
||||||
libzerocash::Address zcaddress(zcsecretkey);
|
libzerocash::Address zcaddress(zcsecretkey);
|
||||||
|
|
||||||
auto encrypted_bucket_vec = ParseHexV(params[1], "encrypted_bucket");
|
uint256 epk;
|
||||||
std::string encrypted_bucket(encrypted_bucket_vec.begin(), encrypted_bucket_vec.end());
|
unsigned char nonce;
|
||||||
libzerocash::Coin decrypted_bucket(encrypted_bucket, zcaddress);
|
ZCNoteEncryption::Ciphertext ct;
|
||||||
|
|
||||||
|
{
|
||||||
|
CDataStream ssData(ParseHexV(params[1], "encrypted_bucket"), SER_NETWORK, PROTOCOL_VERSION);
|
||||||
|
try {
|
||||||
|
ssData >> nonce;
|
||||||
|
ssData >> epk;
|
||||||
|
ssData >> ct;
|
||||||
|
} catch(const std::exception &) {
|
||||||
|
throw runtime_error(
|
||||||
|
"encrypted_bucket could not be decoded"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
libzerocash::Coin decrypted_bucket(ct, zcaddress, epk, nonce);
|
||||||
|
|
||||||
std::vector<unsigned char> commitment_v = decrypted_bucket.getCoinCommitment().getCommitmentValue();
|
std::vector<unsigned char> commitment_v = decrypted_bucket.getCoinCommitment().getCommitmentValue();
|
||||||
uint256 commitment = uint256(commitment_v);
|
uint256 commitment = uint256(commitment_v);
|
||||||
|
@ -2565,8 +2580,8 @@ Value zc_raw_pour(const json_spirit::Array& params, bool fHelp)
|
||||||
ssData >> rho;
|
ssData >> rho;
|
||||||
ssData >> r;
|
ssData >> r;
|
||||||
|
|
||||||
std::vector<unsigned char> a_sk;
|
uint256 a_sk;
|
||||||
std::string sk_enc;
|
uint256 sk_enc;
|
||||||
|
|
||||||
{
|
{
|
||||||
CDataStream ssData2(ParseHexV(s.value_, "zcsecretkey"), SER_NETWORK, PROTOCOL_VERSION);
|
CDataStream ssData2(ParseHexV(s.value_, "zcsecretkey"), SER_NETWORK, PROTOCOL_VERSION);
|
||||||
|
@ -2608,8 +2623,8 @@ Value zc_raw_pour(const json_spirit::Array& params, bool fHelp)
|
||||||
{
|
{
|
||||||
CDataStream ssData(ParseHexV(s.name_, "to_address"), SER_NETWORK, PROTOCOL_VERSION);
|
CDataStream ssData(ParseHexV(s.name_, "to_address"), SER_NETWORK, PROTOCOL_VERSION);
|
||||||
|
|
||||||
std::vector<unsigned char> pubAddressSecret;
|
uint256 pubAddressSecret;
|
||||||
std::string encryptionPublicKey;
|
uint256 encryptionPublicKey;
|
||||||
|
|
||||||
ssData >> pubAddressSecret;
|
ssData >> pubAddressSecret;
|
||||||
ssData >> encryptionPublicKey;
|
ssData >> encryptionPublicKey;
|
||||||
|
@ -2653,9 +2668,28 @@ Value zc_raw_pour(const json_spirit::Array& params, bool fHelp)
|
||||||
CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
|
CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
|
||||||
ss << rawTx;
|
ss << rawTx;
|
||||||
|
|
||||||
|
std::string encryptedBucket1;
|
||||||
|
std::string encryptedBucket2;
|
||||||
|
{
|
||||||
|
CDataStream ss2(SER_NETWORK, PROTOCOL_VERSION);
|
||||||
|
ss2 << ((unsigned char) 0x00);
|
||||||
|
ss2 << pourtx.ephemeralKey;
|
||||||
|
ss2 << pourtx.ciphertexts[0];
|
||||||
|
|
||||||
|
encryptedBucket1 = HexStr(ss2.begin(), ss2.end());
|
||||||
|
}
|
||||||
|
{
|
||||||
|
CDataStream ss2(SER_NETWORK, PROTOCOL_VERSION);
|
||||||
|
ss2 << ((unsigned char) 0x01);
|
||||||
|
ss2 << pourtx.ephemeralKey;
|
||||||
|
ss2 << pourtx.ciphertexts[1];
|
||||||
|
|
||||||
|
encryptedBucket2 = HexStr(ss2.begin(), ss2.end());
|
||||||
|
}
|
||||||
|
|
||||||
Object result;
|
Object result;
|
||||||
result.push_back(Pair("encryptedbucket1", HexStr(pourtx.ciphertexts[0].begin(), pourtx.ciphertexts[0].end())));
|
result.push_back(Pair("encryptedbucket1", encryptedBucket1));
|
||||||
result.push_back(Pair("encryptedbucket2", HexStr(pourtx.ciphertexts[1].begin(), pourtx.ciphertexts[1].end())));
|
result.push_back(Pair("encryptedbucket2", encryptedBucket2));
|
||||||
result.push_back(Pair("rawtxn", HexStr(ss.begin(), ss.end())));
|
result.push_back(Pair("rawtxn", HexStr(ss.begin(), ss.end())));
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,169 @@
|
||||||
|
#include "NoteEncryption.hpp"
|
||||||
|
#include <stdexcept>
|
||||||
|
#include "sodium.h"
|
||||||
|
#include <boost/static_assert.hpp>
|
||||||
|
#include "prf.h"
|
||||||
|
|
||||||
|
#define NOTEENCRYPTION_CIPHER_KEYSIZE 32
|
||||||
|
|
||||||
|
void clamp_curve25519(unsigned char key[crypto_scalarmult_SCALARBYTES])
|
||||||
|
{
|
||||||
|
key[0] &= 248;
|
||||||
|
key[31] &= 127;
|
||||||
|
key[31] |= 64;
|
||||||
|
}
|
||||||
|
|
||||||
|
void KDF(unsigned char K[NOTEENCRYPTION_CIPHER_KEYSIZE],
|
||||||
|
const uint256 &dhsecret,
|
||||||
|
const uint256 &epk,
|
||||||
|
const uint256 &pk_enc,
|
||||||
|
const uint256 &hSig,
|
||||||
|
unsigned char nonce
|
||||||
|
)
|
||||||
|
{
|
||||||
|
if (nonce == 0xff) {
|
||||||
|
throw std::logic_error("no additional nonce space for KDF");
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned char block[128] = {};
|
||||||
|
memcpy(block+0, hSig.begin(), 32);
|
||||||
|
memcpy(block+32, dhsecret.begin(), 32);
|
||||||
|
memcpy(block+64, epk.begin(), 32);
|
||||||
|
memcpy(block+96, pk_enc.begin(), 32);
|
||||||
|
|
||||||
|
unsigned char personalization[crypto_generichash_blake2b_PERSONALBYTES] = {};
|
||||||
|
memcpy(personalization, "ZcashKDF", 8);
|
||||||
|
memcpy(personalization+8, &nonce, 1);
|
||||||
|
|
||||||
|
if (crypto_generichash_blake2b_salt_personal(K, NOTEENCRYPTION_CIPHER_KEYSIZE,
|
||||||
|
block, 128,
|
||||||
|
NULL, 0, // No key.
|
||||||
|
NULL, // No salt.
|
||||||
|
personalization
|
||||||
|
) != 0)
|
||||||
|
{
|
||||||
|
throw std::logic_error("hash function failure");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace libzcash {
|
||||||
|
|
||||||
|
template<size_t MLEN>
|
||||||
|
NoteEncryption<MLEN>::NoteEncryption(uint256 hSig) : nonce(0), hSig(hSig) {
|
||||||
|
// All of this code assumes crypto_scalarmult_BYTES is 32
|
||||||
|
// There's no reason that will _ever_ change, but for
|
||||||
|
// completeness purposes, let's check anyway.
|
||||||
|
BOOST_STATIC_ASSERT(32 == crypto_scalarmult_BYTES);
|
||||||
|
BOOST_STATIC_ASSERT(32 == crypto_scalarmult_SCALARBYTES);
|
||||||
|
BOOST_STATIC_ASSERT(NOTEENCRYPTION_AUTH_BYTES == crypto_aead_chacha20poly1305_ABYTES);
|
||||||
|
|
||||||
|
// Create the ephemeral keypair
|
||||||
|
esk = random_uint256();
|
||||||
|
epk = generate_pubkey(esk);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<size_t MLEN>
|
||||||
|
NoteDecryption<MLEN>::NoteDecryption(uint256 sk_enc) : sk_enc(sk_enc) {
|
||||||
|
this->pk_enc = NoteEncryption<MLEN>::generate_pubkey(sk_enc);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<size_t MLEN>
|
||||||
|
typename NoteEncryption<MLEN>::Ciphertext NoteEncryption<MLEN>::encrypt
|
||||||
|
(const uint256 &pk_enc,
|
||||||
|
const NoteEncryption<MLEN>::Plaintext &message
|
||||||
|
)
|
||||||
|
{
|
||||||
|
uint256 dhsecret;
|
||||||
|
|
||||||
|
if (crypto_scalarmult(dhsecret.begin(), esk.begin(), pk_enc.begin()) != 0) {
|
||||||
|
throw std::logic_error("Could not create DH secret");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Construct the symmetric key
|
||||||
|
unsigned char K[NOTEENCRYPTION_CIPHER_KEYSIZE];
|
||||||
|
KDF(K, dhsecret, epk, pk_enc, hSig, nonce);
|
||||||
|
|
||||||
|
// Increment the number of encryptions we've performed
|
||||||
|
nonce++;
|
||||||
|
|
||||||
|
// The nonce is zero because we never reuse keys
|
||||||
|
unsigned char cipher_nonce[crypto_aead_chacha20poly1305_IETF_NPUBBYTES] = {};
|
||||||
|
|
||||||
|
NoteEncryption<MLEN>::Ciphertext ciphertext;
|
||||||
|
|
||||||
|
crypto_aead_chacha20poly1305_ietf_encrypt(ciphertext.begin(), NULL,
|
||||||
|
message.begin(), MLEN,
|
||||||
|
NULL, 0, // no "additional data"
|
||||||
|
NULL, cipher_nonce, K);
|
||||||
|
|
||||||
|
return ciphertext;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<size_t MLEN>
|
||||||
|
typename NoteDecryption<MLEN>::Plaintext NoteDecryption<MLEN>::decrypt
|
||||||
|
(const NoteDecryption<MLEN>::Ciphertext &ciphertext,
|
||||||
|
const uint256 &epk,
|
||||||
|
const uint256 &hSig,
|
||||||
|
unsigned char nonce
|
||||||
|
) const
|
||||||
|
{
|
||||||
|
uint256 dhsecret;
|
||||||
|
|
||||||
|
if (crypto_scalarmult(dhsecret.begin(), sk_enc.begin(), epk.begin()) != 0) {
|
||||||
|
throw std::logic_error("Could not create DH secret");
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned char K[NOTEENCRYPTION_CIPHER_KEYSIZE];
|
||||||
|
KDF(K, dhsecret, epk, pk_enc, hSig, nonce);
|
||||||
|
|
||||||
|
// The nonce is zero because we never reuse keys
|
||||||
|
unsigned char cipher_nonce[crypto_aead_chacha20poly1305_IETF_NPUBBYTES] = {};
|
||||||
|
|
||||||
|
NoteDecryption<MLEN>::Plaintext plaintext;
|
||||||
|
|
||||||
|
if (crypto_aead_chacha20poly1305_ietf_decrypt(plaintext.begin(), NULL,
|
||||||
|
NULL,
|
||||||
|
ciphertext.begin(), NoteDecryption<MLEN>::CLEN,
|
||||||
|
NULL,
|
||||||
|
0,
|
||||||
|
cipher_nonce, K) != 0) {
|
||||||
|
throw std::runtime_error("Could not decrypt message");
|
||||||
|
}
|
||||||
|
|
||||||
|
return plaintext;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<size_t MLEN>
|
||||||
|
uint256 NoteEncryption<MLEN>::generate_privkey(const uint256 &a_sk)
|
||||||
|
{
|
||||||
|
uint256 sk = PRF_addr_sk_enc(a_sk);
|
||||||
|
|
||||||
|
clamp_curve25519(sk.begin());
|
||||||
|
|
||||||
|
return sk;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<size_t MLEN>
|
||||||
|
uint256 NoteEncryption<MLEN>::generate_pubkey(const uint256 &sk_enc)
|
||||||
|
{
|
||||||
|
uint256 pk;
|
||||||
|
|
||||||
|
if (crypto_scalarmult_base(pk.begin(), sk_enc.begin()) != 0) {
|
||||||
|
throw std::logic_error("Could not create public key");
|
||||||
|
}
|
||||||
|
|
||||||
|
return pk;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint256 random_uint256()
|
||||||
|
{
|
||||||
|
uint256 ret;
|
||||||
|
randombytes_buf(ret.begin(), 32);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
template class NoteEncryption<ZC_V_SIZE + ZC_RHO_SIZE + ZC_R_SIZE + ZC_MEMO_SIZE>;
|
||||||
|
template class NoteDecryption<ZC_V_SIZE + ZC_RHO_SIZE + ZC_R_SIZE + ZC_MEMO_SIZE>;
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,79 @@
|
||||||
|
/*
|
||||||
|
See the Zcash protocol specification for more information.
|
||||||
|
https://github.com/zcash/zips/blob/master/protocol/protocol.pdf
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef ZC_NOTE_ENCRYPTION_H_
|
||||||
|
#define ZC_NOTE_ENCRYPTION_H_
|
||||||
|
|
||||||
|
#include <boost/array.hpp>
|
||||||
|
#include "uint256.h"
|
||||||
|
|
||||||
|
#include "zerocash/Zerocash.h"
|
||||||
|
|
||||||
|
namespace libzcash {
|
||||||
|
|
||||||
|
#define NOTEENCRYPTION_AUTH_BYTES 16
|
||||||
|
|
||||||
|
template<size_t MLEN>
|
||||||
|
class NoteEncryption {
|
||||||
|
protected:
|
||||||
|
enum { CLEN=MLEN+NOTEENCRYPTION_AUTH_BYTES };
|
||||||
|
uint256 epk;
|
||||||
|
uint256 esk;
|
||||||
|
unsigned char nonce;
|
||||||
|
uint256 hSig;
|
||||||
|
|
||||||
|
public:
|
||||||
|
typedef boost::array<unsigned char, CLEN> Ciphertext;
|
||||||
|
typedef boost::array<unsigned char, MLEN> Plaintext;
|
||||||
|
|
||||||
|
NoteEncryption(uint256 hSig);
|
||||||
|
|
||||||
|
// Gets the ephemeral public key
|
||||||
|
uint256 get_epk() {
|
||||||
|
return epk;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Encrypts `message` with `pk_enc` and returns the ciphertext.
|
||||||
|
// This can only be called twice for a given instantiation before
|
||||||
|
// the nonce-space runs out.
|
||||||
|
Ciphertext encrypt(const uint256 &pk_enc,
|
||||||
|
const Plaintext &message
|
||||||
|
);
|
||||||
|
|
||||||
|
// Creates a NoteEncryption private key
|
||||||
|
static uint256 generate_privkey(const uint256 &a_sk);
|
||||||
|
|
||||||
|
// Creates a NoteEncryption public key from a private key
|
||||||
|
static uint256 generate_pubkey(const uint256 &sk_enc);
|
||||||
|
};
|
||||||
|
|
||||||
|
template<size_t MLEN>
|
||||||
|
class NoteDecryption {
|
||||||
|
protected:
|
||||||
|
enum { CLEN=MLEN+NOTEENCRYPTION_AUTH_BYTES };
|
||||||
|
uint256 sk_enc;
|
||||||
|
uint256 pk_enc;
|
||||||
|
|
||||||
|
public:
|
||||||
|
typedef boost::array<unsigned char, CLEN> Ciphertext;
|
||||||
|
typedef boost::array<unsigned char, MLEN> Plaintext;
|
||||||
|
|
||||||
|
NoteDecryption(uint256 sk_enc);
|
||||||
|
|
||||||
|
Plaintext decrypt(const Ciphertext &ciphertext,
|
||||||
|
const uint256 &epk,
|
||||||
|
const uint256 &hSig,
|
||||||
|
unsigned char nonce
|
||||||
|
) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
uint256 random_uint256();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef libzcash::NoteEncryption<ZC_V_SIZE + ZC_RHO_SIZE + ZC_R_SIZE + ZC_MEMO_SIZE> ZCNoteEncryption;
|
||||||
|
typedef libzcash::NoteDecryption<ZC_V_SIZE + ZC_RHO_SIZE + ZC_R_SIZE + ZC_MEMO_SIZE> ZCNoteDecryption;
|
||||||
|
|
||||||
|
#endif /* ZC_NOTE_ENCRYPTION_H_ */
|
|
@ -0,0 +1,63 @@
|
||||||
|
#include "prf.h"
|
||||||
|
#include "crypto/sha256.h"
|
||||||
|
|
||||||
|
uint256 PRF(bool a, bool b, bool c, bool d,
|
||||||
|
const uint256& x,
|
||||||
|
const uint256& y)
|
||||||
|
{
|
||||||
|
uint256 res;
|
||||||
|
unsigned char blob[64];
|
||||||
|
|
||||||
|
memcpy(&blob[0], x.begin(), 32);
|
||||||
|
memcpy(&blob[32], y.begin(), 32);
|
||||||
|
|
||||||
|
blob[0] &= 0x0F;
|
||||||
|
blob[0] |= (a ? 1 << 7 : 0) | (b ? 1 << 6 : 0) | (c ? 1 << 5 : 0) | (d ? 1 << 4 : 0);
|
||||||
|
|
||||||
|
CSHA256 hasher;
|
||||||
|
hasher.Write(blob, 64);
|
||||||
|
hasher.FinalizeNoPadding(res.begin());
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint256 PRF_addr(const uint256& a_sk, unsigned char t)
|
||||||
|
{
|
||||||
|
uint256 y;
|
||||||
|
*(y.begin()) = t;
|
||||||
|
|
||||||
|
return PRF(1, 1, 0, 0, a_sk, y);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint256 PRF_addr_a_pk(const uint256& a_sk)
|
||||||
|
{
|
||||||
|
return PRF_addr(a_sk, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint256 PRF_addr_sk_enc(const uint256& a_sk)
|
||||||
|
{
|
||||||
|
return PRF_addr(a_sk, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint256 PRF_nf(const uint256& 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)
|
||||||
|
{
|
||||||
|
if ((i0 != 0) && (i0 != 1)) {
|
||||||
|
throw std::domain_error("PRF_pk invoked with index out of bounds");
|
||||||
|
}
|
||||||
|
|
||||||
|
return PRF(0, i0, 0, 0, a_sk, h_sig);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint256 PRF_rho(const uint256& 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");
|
||||||
|
}
|
||||||
|
|
||||||
|
return PRF(0, i0, 1, 0, phi, h_sig);
|
||||||
|
}
|
|
@ -0,0 +1,17 @@
|
||||||
|
/*
|
||||||
|
Zcash uses SHA256Compress as a PRF for various components
|
||||||
|
within the zkSNARK circuit.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _PRF_H_
|
||||||
|
#define _PRF_H_
|
||||||
|
|
||||||
|
#include "uint256.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);
|
||||||
|
|
||||||
|
#endif // _PRF_H_
|
|
@ -11,26 +11,14 @@
|
||||||
* @copyright MIT license (see LICENSE file)
|
* @copyright MIT license (see LICENSE file)
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
|
||||||
#include <cryptopp/osrng.h>
|
#include "zcash/NoteEncryption.hpp"
|
||||||
using CryptoPP::AutoSeededRandomPool;
|
|
||||||
|
|
||||||
#include <cryptopp/eccrypto.h>
|
|
||||||
using CryptoPP::ECP;
|
|
||||||
using CryptoPP::ECIES;
|
|
||||||
|
|
||||||
#include <cryptopp/oids.h>
|
|
||||||
namespace ASN1 = CryptoPP::ASN1;
|
|
||||||
|
|
||||||
#include <cryptopp/filters.h>
|
|
||||||
using CryptoPP::StringSink;
|
|
||||||
using CryptoPP::StringStore;
|
|
||||||
|
|
||||||
#include "Zerocash.h"
|
#include "Zerocash.h"
|
||||||
#include "Address.h"
|
#include "Address.h"
|
||||||
|
|
||||||
namespace libzerocash {
|
namespace libzerocash {
|
||||||
|
|
||||||
PrivateAddress::PrivateAddress(const std::vector<unsigned char> a_sk, const std::string sk_enc) {
|
PrivateAddress::PrivateAddress(const uint256 &a_sk, const uint256 &sk_enc) {
|
||||||
this->a_sk = a_sk;
|
this->a_sk = a_sk;
|
||||||
this->sk_enc = sk_enc;
|
this->sk_enc = sk_enc;
|
||||||
}
|
}
|
||||||
|
@ -47,23 +35,27 @@ bool PrivateAddress::operator!=(const PrivateAddress& rhs) const {
|
||||||
return !(*this == rhs);
|
return !(*this == rhs);
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::string PrivateAddress::getEncryptionSecretKey() const {
|
const uint256& PrivateAddress::getEncryptionSecretKey() const {
|
||||||
return this->sk_enc;
|
return this->sk_enc;
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::vector<unsigned char>& PrivateAddress::getAddressSecret() const {
|
const uint256& PrivateAddress::getAddressSecret() const {
|
||||||
return this->a_sk;
|
return this->a_sk;
|
||||||
}
|
}
|
||||||
|
|
||||||
PublicAddress::PublicAddress(): a_pk(ZC_A_PK_SIZE) {
|
PublicAddress::PublicAddress() {
|
||||||
this->pk_enc = "";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
PublicAddress::PublicAddress(const std::vector<unsigned char>& a_pk, std::string& pk_enc) : a_pk(a_pk), pk_enc(pk_enc) {}
|
PublicAddress::PublicAddress(const uint256& a_pk, uint256& pk_enc) : a_pk(a_pk), pk_enc(pk_enc) {}
|
||||||
|
|
||||||
PublicAddress::PublicAddress(const PrivateAddress& addr_sk): a_pk(ZC_A_PK_SIZE) {
|
PublicAddress::PublicAddress(const PrivateAddress& addr_sk) {
|
||||||
std::vector<bool> a_sk_bool(ZC_A_SK_SIZE * 8);
|
std::vector<bool> a_sk_bool(ZC_A_SK_SIZE * 8);
|
||||||
convertBytesVectorToVector(addr_sk.getAddressSecret(), a_sk_bool);
|
|
||||||
|
std::vector<unsigned char> a_sk_v(addr_sk.getAddressSecret().begin(),
|
||||||
|
addr_sk.getAddressSecret().end());
|
||||||
|
|
||||||
|
convertBytesVectorToVector(a_sk_v, a_sk_bool);
|
||||||
|
|
||||||
std::vector<bool> zeros_256(256, 0);
|
std::vector<bool> zeros_256(256, 0);
|
||||||
|
|
||||||
|
@ -73,26 +65,20 @@ PublicAddress::PublicAddress(const PrivateAddress& addr_sk): a_pk(ZC_A_PK_SIZE)
|
||||||
std::vector<bool> a_pk_bool(ZC_A_PK_SIZE * 8);
|
std::vector<bool> a_pk_bool(ZC_A_PK_SIZE * 8);
|
||||||
hashVector(a_pk_internal, a_pk_bool);
|
hashVector(a_pk_internal, a_pk_bool);
|
||||||
|
|
||||||
convertVectorToBytesVector(a_pk_bool, this->a_pk);
|
std::vector<unsigned char> a_pk_vv(ZC_A_PK_SIZE);
|
||||||
|
|
||||||
ECIES<ECP>::PublicKey publicKey;
|
convertVectorToBytesVector(a_pk_bool, a_pk_vv);
|
||||||
|
|
||||||
ECIES<ECP>::PrivateKey decodedPrivateKey;
|
this->a_pk = uint256(a_pk_vv);
|
||||||
decodedPrivateKey.Load(StringStore(addr_sk.getEncryptionSecretKey()).Ref());
|
|
||||||
|
|
||||||
decodedPrivateKey.MakePublicKey(publicKey);
|
this->pk_enc = ZCNoteEncryption::generate_pubkey(addr_sk.getEncryptionSecretKey());
|
||||||
|
|
||||||
std::string encodedPublicKey;
|
|
||||||
publicKey.Save(StringSink(encodedPublicKey).Ref());
|
|
||||||
|
|
||||||
this->pk_enc = encodedPublicKey;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::string PublicAddress::getEncryptionPublicKey() const {
|
const uint256& PublicAddress::getEncryptionPublicKey() const {
|
||||||
return this->pk_enc;
|
return this->pk_enc;
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::vector<unsigned char>& PublicAddress::getPublicAddressSecret() const {
|
const uint256& PublicAddress::getPublicAddressSecret() const {
|
||||||
return this->a_pk;
|
return this->a_pk;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -135,16 +121,11 @@ Address Address::CreateNewRandomAddress() {
|
||||||
getRandBytes(a_sk_bytes, ZC_A_SK_SIZE);
|
getRandBytes(a_sk_bytes, ZC_A_SK_SIZE);
|
||||||
convertBytesToBytesVector(a_sk_bytes, a_sk);
|
convertBytesToBytesVector(a_sk_bytes, a_sk);
|
||||||
|
|
||||||
AutoSeededRandomPool prng;
|
uint256 a_sk_u(a_sk);
|
||||||
|
|
||||||
ECIES<ECP>::PrivateKey privateKey;
|
uint256 sk_enc = ZCNoteEncryption::generate_privkey(a_sk_u);
|
||||||
privateKey.Initialize(prng, ASN1::secp256r1());
|
|
||||||
|
|
||||||
std::string encodedPrivateKey;
|
PrivateAddress addr_sk(a_sk_u, sk_enc);
|
||||||
|
|
||||||
privateKey.Save(StringSink(encodedPrivateKey).Ref());
|
|
||||||
|
|
||||||
PrivateAddress addr_sk(a_sk, encodedPrivateKey);
|
|
||||||
return Address(addr_sk);
|
return Address(addr_sk);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
|
#include "uint256.h"
|
||||||
|
|
||||||
namespace libzerocash {
|
namespace libzerocash {
|
||||||
|
|
||||||
|
@ -24,17 +25,17 @@ class PrivateAddress {
|
||||||
public:
|
public:
|
||||||
/* This constructor is to be used ONLY for deserialization. */
|
/* This constructor is to be used ONLY for deserialization. */
|
||||||
PrivateAddress();
|
PrivateAddress();
|
||||||
PrivateAddress(const std::vector<unsigned char> a_sk, const std::string sk_enc);
|
PrivateAddress(const uint256 &a_sk, const uint256 &sk_enc);
|
||||||
|
|
||||||
bool operator==(const PrivateAddress& rhs) const;
|
bool operator==(const PrivateAddress& rhs) const;
|
||||||
bool operator!=(const PrivateAddress& rhs) const;
|
bool operator!=(const PrivateAddress& rhs) const;
|
||||||
|
|
||||||
const std::vector<unsigned char>& getAddressSecret() const;
|
const uint256& getAddressSecret() const;
|
||||||
const std::string getEncryptionSecretKey() const;
|
const uint256& getEncryptionSecretKey() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::vector<unsigned char> a_sk;
|
uint256 a_sk;
|
||||||
std::string sk_enc;
|
uint256 sk_enc;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -44,19 +45,19 @@ class PublicAddress {
|
||||||
public:
|
public:
|
||||||
/* This constructor is to be used ONLY for deserialization. */
|
/* This constructor is to be used ONLY for deserialization. */
|
||||||
PublicAddress();
|
PublicAddress();
|
||||||
PublicAddress(const std::vector<unsigned char>& a_pk, std::string& pk_enc);
|
PublicAddress(const uint256& a_pk, uint256& pk_enc);
|
||||||
PublicAddress(const PrivateAddress& addr_sk);
|
PublicAddress(const PrivateAddress& addr_sk);
|
||||||
|
|
||||||
bool operator==(const PublicAddress& rhs) const;
|
bool operator==(const PublicAddress& rhs) const;
|
||||||
bool operator!=(const PublicAddress& rhs) const;
|
bool operator!=(const PublicAddress& rhs) const;
|
||||||
|
|
||||||
|
|
||||||
const std::vector<unsigned char>& getPublicAddressSecret() const;
|
const uint256& getPublicAddressSecret() const;
|
||||||
const std::string getEncryptionPublicKey() const;
|
const uint256& getEncryptionPublicKey() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::vector<unsigned char> a_pk;
|
uint256 a_pk;
|
||||||
std::string pk_enc;
|
uint256 pk_enc;
|
||||||
};
|
};
|
||||||
|
|
||||||
/******************************** Address ************************************/
|
/******************************** Address ************************************/
|
||||||
|
|
|
@ -11,20 +11,6 @@
|
||||||
* @copyright MIT license (see LICENSE file)
|
* @copyright MIT license (see LICENSE file)
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
|
||||||
#include <cryptopp/osrng.h>
|
|
||||||
using CryptoPP::AutoSeededRandomPool;
|
|
||||||
|
|
||||||
#include <cryptopp/eccrypto.h>
|
|
||||||
using CryptoPP::ECP;
|
|
||||||
using CryptoPP::ECIES;
|
|
||||||
|
|
||||||
#include <cryptopp/oids.h>
|
|
||||||
namespace ASN1 = CryptoPP::ASN1;
|
|
||||||
|
|
||||||
#include <cryptopp/filters.h>
|
|
||||||
using CryptoPP::StringSink;
|
|
||||||
using CryptoPP::StringStore;
|
|
||||||
|
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
|
|
||||||
#include "Zerocash.h"
|
#include "Zerocash.h"
|
||||||
|
@ -36,29 +22,17 @@ Coin::Coin(): addr_pk(), cm(), rho(ZC_RHO_SIZE), r(ZC_R_SIZE), coinValue(ZC_V_SI
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Coin::Coin(const std::string bucket, Address& addr): addr_pk(), cm(), rho(ZC_RHO_SIZE), r(ZC_R_SIZE), k(ZC_K_SIZE), coinValue(ZC_V_SIZE) {
|
Coin::Coin(const ZCNoteEncryption::Ciphertext& bucket,
|
||||||
// Retreive and decode the private key
|
Address& addr,
|
||||||
ECIES<ECP>::PrivateKey decodedPrivateKey;
|
uint256& epk,
|
||||||
decodedPrivateKey.Load(StringStore(addr.getPrivateAddress().getEncryptionSecretKey()).Ref());
|
unsigned char nonce
|
||||||
|
): addr_pk(), cm(), rho(ZC_RHO_SIZE), r(ZC_R_SIZE), k(ZC_K_SIZE), coinValue(ZC_V_SIZE) {
|
||||||
|
|
||||||
// Create the decryption session
|
ZCNoteDecryption decrypter(addr.getPrivateAddress().getEncryptionSecretKey());
|
||||||
AutoSeededRandomPool prng;
|
auto plaintext = decrypter.decrypt(bucket,
|
||||||
ECIES<ECP>::Decryptor decrypt(decodedPrivateKey);
|
epk,
|
||||||
|
uint256(),
|
||||||
// Convert the input string into a vector of bytes
|
nonce);
|
||||||
std::vector<byte> bucket_bytes(bucket.begin(), bucket.end());
|
|
||||||
|
|
||||||
// Construct a temporary object to store the plaintext, large enough
|
|
||||||
// to store the plaintext if it were extended beyond the real size.
|
|
||||||
std::vector<unsigned char> plaintext;
|
|
||||||
// Size as needed, filling with zeros.
|
|
||||||
plaintext.resize(decrypt.MaxPlaintextLength(decrypt.CiphertextLength(ZC_V_SIZE + ZC_R_SIZE + ZC_RHO_SIZE)), 0);
|
|
||||||
|
|
||||||
// Perform the decryption
|
|
||||||
decrypt.Decrypt(prng,
|
|
||||||
&bucket_bytes[0],
|
|
||||||
decrypt.CiphertextLength(ZC_V_SIZE + ZC_R_SIZE + ZC_RHO_SIZE),
|
|
||||||
&plaintext[0]);
|
|
||||||
|
|
||||||
// Grab the byte vectors
|
// Grab the byte vectors
|
||||||
std::vector<unsigned char> value_v(plaintext.begin(),
|
std::vector<unsigned char> value_v(plaintext.begin(),
|
||||||
|
@ -73,7 +47,8 @@ Coin::Coin(const std::string bucket, Address& addr): addr_pk(), cm(), rho(ZC_RHO
|
||||||
this->rho = rho_v;
|
this->rho = rho_v;
|
||||||
this->addr_pk = addr.getPublicAddress();
|
this->addr_pk = addr.getPublicAddress();
|
||||||
|
|
||||||
std::vector<unsigned char> a_pk = addr.getPublicAddress().getPublicAddressSecret();
|
std::vector<unsigned char> a_pk(addr.getPublicAddress().getPublicAddressSecret().begin(),
|
||||||
|
addr.getPublicAddress().getPublicAddressSecret().end());
|
||||||
|
|
||||||
this->computeCommitments(a_pk);
|
this->computeCommitments(a_pk);
|
||||||
}
|
}
|
||||||
|
@ -82,7 +57,8 @@ Coin::Coin(const PublicAddress& addr, uint64_t value): addr_pk(addr), cm(), rho(
|
||||||
{
|
{
|
||||||
convertIntToBytesVector(value, this->coinValue);
|
convertIntToBytesVector(value, this->coinValue);
|
||||||
|
|
||||||
std::vector<unsigned char> a_pk = addr.getPublicAddressSecret();
|
std::vector<unsigned char> a_pk(addr.getPublicAddressSecret().begin(),
|
||||||
|
addr.getPublicAddressSecret().end());
|
||||||
|
|
||||||
unsigned char rho_bytes[ZC_RHO_SIZE];
|
unsigned char rho_bytes[ZC_RHO_SIZE];
|
||||||
getRandBytes(rho_bytes, ZC_RHO_SIZE);
|
getRandBytes(rho_bytes, ZC_RHO_SIZE);
|
||||||
|
@ -101,7 +77,7 @@ Coin::Coin(const PublicAddress& addr, uint64_t value,
|
||||||
{
|
{
|
||||||
convertIntToBytesVector(value, this->coinValue);
|
convertIntToBytesVector(value, this->coinValue);
|
||||||
|
|
||||||
std::vector<unsigned char> a_pk = addr.getPublicAddressSecret();
|
std::vector<unsigned char> a_pk(addr.getPublicAddressSecret().begin(), addr.getPublicAddressSecret().end());
|
||||||
|
|
||||||
this->computeCommitments(a_pk);
|
this->computeCommitments(a_pk);
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,6 +17,8 @@
|
||||||
#include "Address.h"
|
#include "Address.h"
|
||||||
#include "CoinCommitment.h"
|
#include "CoinCommitment.h"
|
||||||
|
|
||||||
|
#include "zcash/NoteEncryption.hpp"
|
||||||
|
|
||||||
namespace libzerocash {
|
namespace libzerocash {
|
||||||
|
|
||||||
/********************************* Coin **************************************/
|
/********************************* Coin **************************************/
|
||||||
|
@ -41,7 +43,7 @@ public:
|
||||||
const std::vector<unsigned char>& rho,
|
const std::vector<unsigned char>& rho,
|
||||||
const std::vector<unsigned char>& r);
|
const std::vector<unsigned char>& r);
|
||||||
|
|
||||||
Coin(const std::string bucket, Address& addr);
|
Coin(const ZCNoteEncryption::Ciphertext&, Address& addr, uint256& epk, unsigned char nonce);
|
||||||
|
|
||||||
const PublicAddress& getPublicAddress() const;
|
const PublicAddress& getPublicAddress() const;
|
||||||
|
|
||||||
|
|
|
@ -11,25 +11,6 @@
|
||||||
* @copyright MIT license (see LICENSE file)
|
* @copyright MIT license (see LICENSE file)
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
|
||||||
#include <cryptopp/osrng.h>
|
|
||||||
using CryptoPP::AutoSeededRandomPool;
|
|
||||||
|
|
||||||
#include <cryptopp/eccrypto.h>
|
|
||||||
using CryptoPP::ECP;
|
|
||||||
using CryptoPP::ECIES;
|
|
||||||
|
|
||||||
#include <cryptopp/filters.h>
|
|
||||||
using CryptoPP::StringSource;
|
|
||||||
using CryptoPP::StringStore;
|
|
||||||
using CryptoPP::StringSink;
|
|
||||||
using CryptoPP::PK_EncryptorFilter;
|
|
||||||
|
|
||||||
#include <openssl/ec.h>
|
|
||||||
#include <openssl/ecdsa.h>
|
|
||||||
#include <openssl/obj_mac.h>
|
|
||||||
#include <openssl/bn.h>
|
|
||||||
#include <openssl/sha.h>
|
|
||||||
|
|
||||||
#include "Zerocash.h"
|
#include "Zerocash.h"
|
||||||
#include "PourTransaction.h"
|
#include "PourTransaction.h"
|
||||||
#include "PourInput.h"
|
#include "PourInput.h"
|
||||||
|
@ -113,6 +94,11 @@ PourTransaction::PourTransaction(uint16_t version_num,
|
||||||
patMAC_1, patMAC_2, addr_1_new, addr_2_new, v_pub_old, v_pub_new, pubkeyHash, c_1_new, c_2_new);
|
patMAC_1, patMAC_2, addr_1_new, addr_2_new, v_pub_old, v_pub_new, pubkeyHash, c_1_new, c_2_new);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::vector<unsigned char> from_uint256(const uint256 &in)
|
||||||
|
{
|
||||||
|
return std::vector<unsigned char>(in.begin(), in.end());
|
||||||
|
}
|
||||||
|
|
||||||
void PourTransaction::init(uint16_t version_num,
|
void PourTransaction::init(uint16_t version_num,
|
||||||
ZerocashParams& params,
|
ZerocashParams& params,
|
||||||
const MerkleRootType& rt,
|
const MerkleRootType& rt,
|
||||||
|
@ -168,11 +154,21 @@ void PourTransaction::init(uint16_t version_num,
|
||||||
convertBytesVectorToVector(c_1_new.getCoinCommitment().getCommitmentValue(), cm_new_1_bv);
|
convertBytesVectorToVector(c_1_new.getCoinCommitment().getCommitmentValue(), cm_new_1_bv);
|
||||||
convertBytesVectorToVector(c_2_new.getCoinCommitment().getCommitmentValue(), cm_new_2_bv);
|
convertBytesVectorToVector(c_2_new.getCoinCommitment().getCommitmentValue(), cm_new_2_bv);
|
||||||
|
|
||||||
convertBytesVectorToVector(addr_1_old.getPrivateAddress().getAddressSecret(), addr_sk_old_1_bv);
|
{
|
||||||
convertBytesVectorToVector(addr_2_old.getPrivateAddress().getAddressSecret(), addr_sk_old_2_bv);
|
auto a = from_uint256(addr_1_old.getPrivateAddress().getAddressSecret());
|
||||||
|
auto b = from_uint256(addr_2_old.getPrivateAddress().getAddressSecret());
|
||||||
|
|
||||||
convertBytesVectorToVector(addr_1_new.getPublicAddressSecret(), addr_pk_new_1_bv);
|
convertBytesVectorToVector(a, addr_sk_old_1_bv);
|
||||||
convertBytesVectorToVector(addr_2_new.getPublicAddressSecret(), addr_pk_new_2_bv);
|
convertBytesVectorToVector(b, addr_sk_old_2_bv);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
auto a = from_uint256(addr_1_new.getPublicAddressSecret());
|
||||||
|
auto b = from_uint256(addr_2_new.getPublicAddressSecret());
|
||||||
|
|
||||||
|
convertBytesVectorToVector(a, addr_pk_new_1_bv);
|
||||||
|
convertBytesVectorToVector(b, addr_pk_new_2_bv);
|
||||||
|
}
|
||||||
|
|
||||||
convertBytesVectorToVector(c_1_old.getR(), rand_old_1_bv);
|
convertBytesVectorToVector(c_1_old.getR(), rand_old_1_bv);
|
||||||
convertBytesVectorToVector(c_2_old.getR(), rand_old_2_bv);
|
convertBytesVectorToVector(c_2_old.getR(), rand_old_2_bv);
|
||||||
|
@ -293,65 +289,45 @@ void PourTransaction::init(uint16_t version_num,
|
||||||
this->zkSNARK = std::string(1235,'A');
|
this->zkSNARK = std::string(1235,'A');
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned char val_new_1_bytes[ZC_V_SIZE];
|
// TODO: when h_Sig is constructed properly as per spec
|
||||||
unsigned char val_new_2_bytes[ZC_V_SIZE];
|
// replace uint256() with it
|
||||||
unsigned char nonce_new_1_bytes[ZC_RHO_SIZE];
|
ZCNoteEncryption encryptor = ZCNoteEncryption(uint256());
|
||||||
unsigned char nonce_new_2_bytes[ZC_RHO_SIZE];
|
{
|
||||||
unsigned char rand_new_1_bytes[ZC_R_SIZE];
|
std::vector<unsigned char> plaintext_internals;
|
||||||
unsigned char rand_new_2_bytes[ZC_R_SIZE];
|
plaintext_internals.insert(plaintext_internals.end(), c_1_new.coinValue.begin(), c_1_new.coinValue.end());
|
||||||
|
plaintext_internals.insert(plaintext_internals.end(), c_1_new.r.begin(), c_1_new.r.end());
|
||||||
|
plaintext_internals.insert(plaintext_internals.end(), c_1_new.rho.begin(), c_1_new.rho.end());
|
||||||
|
|
||||||
convertVectorToBytes(val_new_1_bv, val_new_1_bytes);
|
std::vector<unsigned char> memo(ZC_MEMO_SIZE, 0x00);
|
||||||
convertVectorToBytes(val_new_2_bv, val_new_2_bytes);
|
plaintext_internals.insert(plaintext_internals.end(), memo.begin(), memo.end());
|
||||||
convertVectorToBytes(rand_new_1_bv, rand_new_1_bytes);
|
|
||||||
convertVectorToBytes(rand_new_2_bv, rand_new_2_bytes);
|
|
||||||
convertVectorToBytes(nonce_new_1_bv, nonce_new_1_bytes);
|
|
||||||
convertVectorToBytes(nonce_new_2_bv, nonce_new_2_bytes);
|
|
||||||
|
|
||||||
std::string val_new_1_string(val_new_1_bytes, val_new_1_bytes + ZC_V_SIZE);
|
assert(plaintext_internals.size() == 216);
|
||||||
std::string val_new_2_string(val_new_2_bytes, val_new_2_bytes + ZC_V_SIZE);
|
|
||||||
std::string nonce_new_1_string(nonce_new_1_bytes, nonce_new_1_bytes + ZC_RHO_SIZE);
|
|
||||||
std::string nonce_new_2_string(nonce_new_2_bytes, nonce_new_2_bytes + ZC_RHO_SIZE);
|
|
||||||
std::string rand_new_1_string(rand_new_1_bytes, rand_new_1_bytes + ZC_R_SIZE);
|
|
||||||
std::string rand_new_2_string(rand_new_2_bytes, rand_new_2_bytes + ZC_R_SIZE);
|
|
||||||
|
|
||||||
AutoSeededRandomPool prng_1;
|
boost::array<unsigned char, 216> pt;
|
||||||
AutoSeededRandomPool prng_2;
|
memcpy(&pt[0], &plaintext_internals[0], 216);
|
||||||
|
|
||||||
ECIES<ECP>::PublicKey publicKey_1;
|
this->ciphertext_1 = encryptor.encrypt(addr_1_new.getEncryptionPublicKey(),
|
||||||
publicKey_1.Load(StringStore(addr_1_new.getEncryptionPublicKey()).Ref());
|
pt);
|
||||||
ECIES<ECP>::Encryptor encryptor_1(publicKey_1);
|
}
|
||||||
|
{
|
||||||
|
std::vector<unsigned char> plaintext_internals;
|
||||||
|
plaintext_internals.insert(plaintext_internals.end(), c_2_new.coinValue.begin(), c_2_new.coinValue.end());
|
||||||
|
plaintext_internals.insert(plaintext_internals.end(), c_2_new.r.begin(), c_2_new.r.end());
|
||||||
|
plaintext_internals.insert(plaintext_internals.end(), c_2_new.rho.begin(), c_2_new.rho.end());
|
||||||
|
|
||||||
std::vector<unsigned char> ciphertext_1_internals;
|
std::vector<unsigned char> memo(ZC_MEMO_SIZE, 0x00);
|
||||||
ciphertext_1_internals.insert(ciphertext_1_internals.end(), c_1_new.coinValue.begin(), c_1_new.coinValue.end());
|
plaintext_internals.insert(plaintext_internals.end(), memo.begin(), memo.end());
|
||||||
ciphertext_1_internals.insert(ciphertext_1_internals.end(), c_1_new.r.begin(), c_1_new.r.end());
|
|
||||||
ciphertext_1_internals.insert(ciphertext_1_internals.end(), c_1_new.rho.begin(), c_1_new.rho.end());
|
|
||||||
|
|
||||||
assert(ciphertext_1_internals.size() == (ZC_V_SIZE + ZC_R_SIZE + ZC_RHO_SIZE));
|
assert(plaintext_internals.size() == 216);
|
||||||
|
|
||||||
byte gEncryptBuf[encryptor_1.CiphertextLength(ZC_V_SIZE + ZC_R_SIZE + ZC_RHO_SIZE)];
|
boost::array<unsigned char, 216> pt;
|
||||||
|
memcpy(&pt[0], &plaintext_internals[0], 216);
|
||||||
|
|
||||||
encryptor_1.Encrypt(prng_1, &ciphertext_1_internals[0], ZC_V_SIZE + ZC_R_SIZE + ZC_RHO_SIZE, gEncryptBuf);
|
this->ciphertext_2 = encryptor.encrypt(addr_2_new.getEncryptionPublicKey(),
|
||||||
|
pt);
|
||||||
|
}
|
||||||
|
|
||||||
std::string C_1_string(gEncryptBuf, gEncryptBuf + sizeof gEncryptBuf / sizeof gEncryptBuf[0]);
|
this->ephemeralKey = encryptor.get_epk();
|
||||||
this->ciphertext_1 = C_1_string;
|
|
||||||
|
|
||||||
ECIES<ECP>::PublicKey publicKey_2;
|
|
||||||
publicKey_2.Load(StringStore(addr_2_new.getEncryptionPublicKey()).Ref());
|
|
||||||
ECIES<ECP>::Encryptor encryptor_2(publicKey_2);
|
|
||||||
|
|
||||||
std::vector<unsigned char> ciphertext_2_internals;
|
|
||||||
ciphertext_2_internals.insert(ciphertext_2_internals.end(), c_2_new.coinValue.begin(), c_2_new.coinValue.end());
|
|
||||||
ciphertext_2_internals.insert(ciphertext_2_internals.end(), c_2_new.r.begin(), c_2_new.r.end());
|
|
||||||
ciphertext_2_internals.insert(ciphertext_2_internals.end(), c_2_new.rho.begin(), c_2_new.rho.end());
|
|
||||||
|
|
||||||
assert(ciphertext_2_internals.size() == (ZC_V_SIZE + ZC_R_SIZE + ZC_RHO_SIZE));
|
|
||||||
|
|
||||||
byte gEncryptBuf_2[encryptor_2.CiphertextLength(ZC_V_SIZE + ZC_R_SIZE + ZC_RHO_SIZE)];
|
|
||||||
|
|
||||||
encryptor_2.Encrypt(prng_1, &ciphertext_2_internals[0], ZC_V_SIZE + ZC_R_SIZE + ZC_RHO_SIZE, gEncryptBuf_2);
|
|
||||||
|
|
||||||
std::string C_2_string(gEncryptBuf_2, gEncryptBuf_2 + sizeof gEncryptBuf_2 / sizeof gEncryptBuf_2[0]);
|
|
||||||
this->ciphertext_2 = C_2_string;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool PourTransaction::verify(ZerocashParams& params,
|
bool PourTransaction::verify(ZerocashParams& params,
|
||||||
|
@ -434,11 +410,11 @@ const std::vector<unsigned char>& PourTransaction::getSpentSerial2() const{
|
||||||
return this->serialNumber_2;
|
return this->serialNumber_2;
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::string& PourTransaction::getCiphertext1() const {
|
const ZCNoteEncryption::Ciphertext& PourTransaction::getCiphertext1() const {
|
||||||
return this->ciphertext_1;
|
return this->ciphertext_1;
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::string& PourTransaction::getCiphertext2() const {
|
const ZCNoteEncryption::Ciphertext& PourTransaction::getCiphertext2() const {
|
||||||
return this->ciphertext_2;
|
return this->ciphertext_2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -22,6 +22,9 @@
|
||||||
|
|
||||||
#include <boost/array.hpp>
|
#include <boost/array.hpp>
|
||||||
|
|
||||||
|
#include "uint256.h"
|
||||||
|
#include "zcash/NoteEncryption.hpp"
|
||||||
|
|
||||||
typedef std::vector<unsigned char> CoinCommitmentValue;
|
typedef std::vector<unsigned char> CoinCommitmentValue;
|
||||||
|
|
||||||
namespace libzerocash {
|
namespace libzerocash {
|
||||||
|
@ -113,8 +116,8 @@ public:
|
||||||
|
|
||||||
const std::vector<unsigned char>& getSpentSerial1() const;
|
const std::vector<unsigned char>& getSpentSerial1() const;
|
||||||
const std::vector<unsigned char>& getSpentSerial2() const;
|
const std::vector<unsigned char>& getSpentSerial2() const;
|
||||||
const std::string& getCiphertext1() const;
|
const ZCNoteEncryption::Ciphertext& getCiphertext1() const;
|
||||||
const std::string& getCiphertext2() const;
|
const ZCNoteEncryption::Ciphertext& getCiphertext2() const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the hash of the first new coin generated by this Pour.
|
* Returns the hash of the first new coin generated by this Pour.
|
||||||
|
@ -137,7 +140,8 @@ public:
|
||||||
std::string unpack(boost::array<std::vector<unsigned char>, 2>& serials,
|
std::string unpack(boost::array<std::vector<unsigned char>, 2>& serials,
|
||||||
boost::array<std::vector<unsigned char>, 2>& commitments,
|
boost::array<std::vector<unsigned char>, 2>& commitments,
|
||||||
boost::array<std::vector<unsigned char>, 2>& macs,
|
boost::array<std::vector<unsigned char>, 2>& macs,
|
||||||
boost::array<std::string, 2>& ciphertexts
|
boost::array<ZCNoteEncryption::Ciphertext, 2>& ciphertexts,
|
||||||
|
uint256& epk
|
||||||
) const {
|
) const {
|
||||||
serials[0] = this->serialNumber_1;
|
serials[0] = this->serialNumber_1;
|
||||||
serials[1] = this->serialNumber_2;
|
serials[1] = this->serialNumber_2;
|
||||||
|
@ -147,6 +151,7 @@ public:
|
||||||
macs[1] = this->MAC_2;
|
macs[1] = this->MAC_2;
|
||||||
ciphertexts[0] = this->ciphertext_1;
|
ciphertexts[0] = this->ciphertext_1;
|
||||||
ciphertexts[1] = this->ciphertext_2;
|
ciphertexts[1] = this->ciphertext_2;
|
||||||
|
epk = this->ephemeralKey;
|
||||||
|
|
||||||
return this->zkSNARK;
|
return this->zkSNARK;
|
||||||
}
|
}
|
||||||
|
@ -187,8 +192,9 @@ private:
|
||||||
CoinCommitment cm_2; // coin commitment for output coin #2
|
CoinCommitment cm_2; // coin commitment for output coin #2
|
||||||
std::vector<unsigned char> MAC_1; // first MAC (h_1 in paper notation)
|
std::vector<unsigned char> MAC_1; // first MAC (h_1 in paper notation)
|
||||||
std::vector<unsigned char> MAC_2; // second MAC (h_2 in paper notation)
|
std::vector<unsigned char> MAC_2; // second MAC (h_2 in paper notation)
|
||||||
std::string ciphertext_1; // ciphertext #1
|
ZCNoteEncryption::Ciphertext ciphertext_1; // ciphertext #1
|
||||||
std::string ciphertext_2; // ciphertext #2
|
ZCNoteEncryption::Ciphertext ciphertext_2; // ciphertext #2
|
||||||
|
uint256 ephemeralKey; // epk
|
||||||
std::string zkSNARK; // contents of the zkSNARK proof itself
|
std::string zkSNARK; // contents of the zkSNARK proof itself
|
||||||
uint16_t version; // version for the Pour transaction
|
uint16_t version; // version for the Pour transaction
|
||||||
};
|
};
|
||||||
|
|
|
@ -33,6 +33,7 @@
|
||||||
#define ZC_V_SIZE 8
|
#define ZC_V_SIZE 8
|
||||||
#define ZC_RHO_SIZE 32
|
#define ZC_RHO_SIZE 32
|
||||||
#define ZC_R_SIZE 48
|
#define ZC_R_SIZE 48
|
||||||
|
#define ZC_MEMO_SIZE 128
|
||||||
#define ZC_S_SIZE 0
|
#define ZC_S_SIZE 0
|
||||||
#define ZC_K_SIZE 32
|
#define ZC_K_SIZE 32
|
||||||
#define ZC_CM_SIZE 32
|
#define ZC_CM_SIZE 32
|
||||||
|
|
Loading…
Reference in New Issue