NoteEncryption implementation and integration, removal of ECIES and crypto++ dependencies.

This commit is contained in:
Sean Bowe
2016-03-31 22:18:36 -06:00
parent b2cf9ba300
commit 6c36a9fe03
23 changed files with 1206 additions and 735 deletions

View File

@@ -11,26 +11,14 @@
* @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 "zcash/NoteEncryption.hpp"
#include "Zerocash.h"
#include "Address.h"
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->sk_enc = sk_enc;
}
@@ -47,23 +35,27 @@ bool PrivateAddress::operator!=(const PrivateAddress& rhs) const {
return !(*this == rhs);
}
const std::string PrivateAddress::getEncryptionSecretKey() const {
const uint256& PrivateAddress::getEncryptionSecretKey() const {
return this->sk_enc;
}
const std::vector<unsigned char>& PrivateAddress::getAddressSecret() const {
const uint256& PrivateAddress::getAddressSecret() const {
return this->a_sk;
}
PublicAddress::PublicAddress(): a_pk(ZC_A_PK_SIZE) {
this->pk_enc = "";
PublicAddress::PublicAddress() {
}
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);
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);
@@ -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);
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;
decodedPrivateKey.Load(StringStore(addr_sk.getEncryptionSecretKey()).Ref());
this->a_pk = uint256(a_pk_vv);
decodedPrivateKey.MakePublicKey(publicKey);
std::string encodedPublicKey;
publicKey.Save(StringSink(encodedPublicKey).Ref());
this->pk_enc = encodedPublicKey;
this->pk_enc = ZCNoteEncryption::generate_pubkey(addr_sk.getEncryptionSecretKey());
}
const std::string PublicAddress::getEncryptionPublicKey() const {
const uint256& PublicAddress::getEncryptionPublicKey() const {
return this->pk_enc;
}
const std::vector<unsigned char>& PublicAddress::getPublicAddressSecret() const {
const uint256& PublicAddress::getPublicAddressSecret() const {
return this->a_pk;
}
@@ -135,16 +121,11 @@ Address Address::CreateNewRandomAddress() {
getRandBytes(a_sk_bytes, ZC_A_SK_SIZE);
convertBytesToBytesVector(a_sk_bytes, a_sk);
AutoSeededRandomPool prng;
uint256 a_sk_u(a_sk);
ECIES<ECP>::PrivateKey privateKey;
privateKey.Initialize(prng, ASN1::secp256r1());
uint256 sk_enc = ZCNoteEncryption::generate_privkey(a_sk_u);
std::string encodedPrivateKey;
privateKey.Save(StringSink(encodedPrivateKey).Ref());
PrivateAddress addr_sk(a_sk, encodedPrivateKey);
PrivateAddress addr_sk(a_sk_u, sk_enc);
return Address(addr_sk);
}

View File

@@ -15,6 +15,7 @@
#include <vector>
#include <string>
#include "uint256.h"
namespace libzerocash {
@@ -24,17 +25,17 @@ class PrivateAddress {
public:
/* This constructor is to be used ONLY for deserialization. */
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;
const std::vector<unsigned char>& getAddressSecret() const;
const std::string getEncryptionSecretKey() const;
const uint256& getAddressSecret() const;
const uint256& getEncryptionSecretKey() const;
private:
std::vector<unsigned char> a_sk;
std::string sk_enc;
uint256 a_sk;
uint256 sk_enc;
};
@@ -44,19 +45,19 @@ class PublicAddress {
public:
/* This constructor is to be used ONLY for deserialization. */
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);
bool operator==(const PublicAddress& rhs) const;
bool operator!=(const PublicAddress& rhs) const;
const std::vector<unsigned char>& getPublicAddressSecret() const;
const std::string getEncryptionPublicKey() const;
const uint256& getPublicAddressSecret() const;
const uint256& getEncryptionPublicKey() const;
private:
std::vector<unsigned char> a_pk;
std::string pk_enc;
uint256 a_pk;
uint256 pk_enc;
};
/******************************** Address ************************************/

View File

@@ -11,20 +11,6 @@
* @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 "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) {
// Retreive and decode the private key
ECIES<ECP>::PrivateKey decodedPrivateKey;
decodedPrivateKey.Load(StringStore(addr.getPrivateAddress().getEncryptionSecretKey()).Ref());
Coin::Coin(const ZCNoteEncryption::Ciphertext& bucket,
Address& addr,
uint256& epk,
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
AutoSeededRandomPool prng;
ECIES<ECP>::Decryptor decrypt(decodedPrivateKey);
// Convert the input string into a vector of bytes
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]);
ZCNoteDecryption decrypter(addr.getPrivateAddress().getEncryptionSecretKey());
auto plaintext = decrypter.decrypt(bucket,
epk,
uint256(),
nonce);
// Grab the byte vectors
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->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);
}
@@ -82,7 +57,8 @@ Coin::Coin(const PublicAddress& addr, uint64_t value): addr_pk(addr), cm(), rho(
{
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];
getRandBytes(rho_bytes, ZC_RHO_SIZE);
@@ -101,7 +77,7 @@ Coin::Coin(const PublicAddress& addr, uint64_t value,
{
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);
}

View File

@@ -17,6 +17,8 @@
#include "Address.h"
#include "CoinCommitment.h"
#include "zcash/NoteEncryption.hpp"
namespace libzerocash {
/********************************* Coin **************************************/
@@ -41,7 +43,7 @@ public:
const std::vector<unsigned char>& rho,
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;

View File

@@ -11,25 +11,6 @@
* @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 "PourTransaction.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);
}
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,
ZerocashParams& params,
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_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(addr_2_new.getPublicAddressSecret(), addr_pk_new_2_bv);
convertBytesVectorToVector(a, addr_sk_old_1_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_2_old.getR(), rand_old_2_bv);
@@ -293,65 +289,45 @@ void PourTransaction::init(uint16_t version_num,
this->zkSNARK = std::string(1235,'A');
}
unsigned char val_new_1_bytes[ZC_V_SIZE];
unsigned char val_new_2_bytes[ZC_V_SIZE];
unsigned char nonce_new_1_bytes[ZC_RHO_SIZE];
unsigned char nonce_new_2_bytes[ZC_RHO_SIZE];
unsigned char rand_new_1_bytes[ZC_R_SIZE];
unsigned char rand_new_2_bytes[ZC_R_SIZE];
// TODO: when h_Sig is constructed properly as per spec
// replace uint256() with it
ZCNoteEncryption encryptor = ZCNoteEncryption(uint256());
{
std::vector<unsigned char> plaintext_internals;
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);
convertVectorToBytes(val_new_2_bv, val_new_2_bytes);
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::vector<unsigned char> memo(ZC_MEMO_SIZE, 0x00);
plaintext_internals.insert(plaintext_internals.end(), memo.begin(), memo.end());
std::string val_new_1_string(val_new_1_bytes, val_new_1_bytes + ZC_V_SIZE);
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);
assert(plaintext_internals.size() == 216);
AutoSeededRandomPool prng_1;
AutoSeededRandomPool prng_2;
boost::array<unsigned char, 216> pt;
memcpy(&pt[0], &plaintext_internals[0], 216);
ECIES<ECP>::PublicKey publicKey_1;
publicKey_1.Load(StringStore(addr_1_new.getEncryptionPublicKey()).Ref());
ECIES<ECP>::Encryptor encryptor_1(publicKey_1);
this->ciphertext_1 = encryptor.encrypt(addr_1_new.getEncryptionPublicKey(),
pt);
}
{
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;
ciphertext_1_internals.insert(ciphertext_1_internals.end(), c_1_new.coinValue.begin(), c_1_new.coinValue.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());
std::vector<unsigned char> memo(ZC_MEMO_SIZE, 0x00);
plaintext_internals.insert(plaintext_internals.end(), memo.begin(), memo.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->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;
this->ephemeralKey = encryptor.get_epk();
}
bool PourTransaction::verify(ZerocashParams& params,
@@ -434,11 +410,11 @@ const std::vector<unsigned char>& PourTransaction::getSpentSerial2() const{
return this->serialNumber_2;
}
const std::string& PourTransaction::getCiphertext1() const {
const ZCNoteEncryption::Ciphertext& PourTransaction::getCiphertext1() const {
return this->ciphertext_1;
}
const std::string& PourTransaction::getCiphertext2() const {
const ZCNoteEncryption::Ciphertext& PourTransaction::getCiphertext2() const {
return this->ciphertext_2;
}

View File

@@ -22,6 +22,9 @@
#include <boost/array.hpp>
#include "uint256.h"
#include "zcash/NoteEncryption.hpp"
typedef std::vector<unsigned char> CoinCommitmentValue;
namespace libzerocash {
@@ -113,8 +116,8 @@ public:
const std::vector<unsigned char>& getSpentSerial1() const;
const std::vector<unsigned char>& getSpentSerial2() const;
const std::string& getCiphertext1() const;
const std::string& getCiphertext2() const;
const ZCNoteEncryption::Ciphertext& getCiphertext1() const;
const ZCNoteEncryption::Ciphertext& getCiphertext2() const;
/**
* 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,
boost::array<std::vector<unsigned char>, 2>& commitments,
boost::array<std::vector<unsigned char>, 2>& macs,
boost::array<std::string, 2>& ciphertexts
boost::array<ZCNoteEncryption::Ciphertext, 2>& ciphertexts,
uint256& epk
) const {
serials[0] = this->serialNumber_1;
serials[1] = this->serialNumber_2;
@@ -147,6 +151,7 @@ public:
macs[1] = this->MAC_2;
ciphertexts[0] = this->ciphertext_1;
ciphertexts[1] = this->ciphertext_2;
epk = this->ephemeralKey;
return this->zkSNARK;
}
@@ -179,18 +184,19 @@ public:
private:
std::vector<unsigned char> publicOldValue; // public input value of the Pour transaction
std::vector<unsigned char> publicNewValue; // public output value of the Pour transaction
std::vector<unsigned char> serialNumber_1; // serial number of input (old) coin #1
std::vector<unsigned char> serialNumber_2; // serial number of input (old) coin #1
CoinCommitment cm_1; // coin commitment for output coin #1
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_2; // second MAC (h_2 in paper notation)
std::string ciphertext_1; // ciphertext #1
std::string ciphertext_2; // ciphertext #2
std::string zkSNARK; // contents of the zkSNARK proof itself
uint16_t version; // version for the Pour transaction
std::vector<unsigned char> publicOldValue; // public input value of the Pour transaction
std::vector<unsigned char> publicNewValue; // public output value of the Pour transaction
std::vector<unsigned char> serialNumber_1; // serial number of input (old) coin #1
std::vector<unsigned char> serialNumber_2; // serial number of input (old) coin #1
CoinCommitment cm_1; // coin commitment for output coin #1
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_2; // second MAC (h_2 in paper notation)
ZCNoteEncryption::Ciphertext ciphertext_1; // ciphertext #1
ZCNoteEncryption::Ciphertext ciphertext_2; // ciphertext #2
uint256 ephemeralKey; // epk
std::string zkSNARK; // contents of the zkSNARK proof itself
uint16_t version; // version for the Pour transaction
};
} /* namespace libzerocash */

View File

@@ -33,6 +33,7 @@
#define ZC_V_SIZE 8
#define ZC_RHO_SIZE 32
#define ZC_R_SIZE 48
#define ZC_MEMO_SIZE 128
#define ZC_S_SIZE 0
#define ZC_K_SIZE 32
#define ZC_CM_SIZE 32