Auto merge of #3324 - ebfull:sapling-note-encryption, r=ebfull
Sapling note encryption implementation Closes #3055 Implemented along with @gtank and @Eirik0 DH key exchange was implemented in https://github.com/zcash/librustzcash/pull/18
This commit is contained in:
commit
d86f60f382
|
@ -3,8 +3,8 @@ $(package)_version=0.1
|
|||
$(package)_download_path=https://github.com/zcash/$(package)/archive/
|
||||
$(package)_file_name=$(package)-$($(package)_git_commit).tar.gz
|
||||
$(package)_download_file=$($(package)_git_commit).tar.gz
|
||||
$(package)_sha256_hash=5231145ea6abf61092c21b6770baf3af65994f83dff96b10118ba5dd53451f26
|
||||
$(package)_git_commit=0af1ce8bf121e1ad367db907c39d214581e270a6
|
||||
$(package)_sha256_hash=5a50aae38a9ef4823cd319278ad95706a129cc091e1cca9342802f1ff75aba15
|
||||
$(package)_git_commit=93e26d1d8716ac88f8bb372d442315edcd2deabd
|
||||
$(package)_dependencies=rust $(rust_crates)
|
||||
$(package)_patches=cargo.config
|
||||
|
||||
|
|
|
@ -6,7 +6,9 @@
|
|||
|
||||
#include "zcash/NoteEncryption.hpp"
|
||||
#include "zcash/prf.h"
|
||||
#include "zcash/Address.hpp"
|
||||
#include "crypto/sha256.h"
|
||||
#include "librustzcash.h"
|
||||
|
||||
class TestNoteDecryption : public ZCNoteDecryption {
|
||||
public:
|
||||
|
@ -17,6 +19,189 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
TEST(noteencryption, SaplingApi)
|
||||
{
|
||||
using namespace libzcash;
|
||||
|
||||
// Create recipient addresses
|
||||
auto sk = SaplingSpendingKey(uint256()).expanded_spending_key();
|
||||
auto vk = sk.full_viewing_key();
|
||||
auto ivk = vk.in_viewing_key();
|
||||
SaplingPaymentAddress pk_1 = *ivk.address({0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0});
|
||||
SaplingPaymentAddress pk_2 = *ivk.address({4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0});
|
||||
|
||||
// Blob of stuff we're encrypting
|
||||
std::array<unsigned char, ZC_SAPLING_ENCPLAINTEXT_SIZE> message;
|
||||
for (size_t i = 0; i < ZC_SAPLING_ENCPLAINTEXT_SIZE; i++) {
|
||||
// Fill the message with dummy data
|
||||
message[i] = (unsigned char) i;
|
||||
}
|
||||
|
||||
std::array<unsigned char, ZC_SAPLING_OUTPLAINTEXT_SIZE> small_message;
|
||||
for (size_t i = 0; i < ZC_SAPLING_OUTPLAINTEXT_SIZE; i++) {
|
||||
// Fill the message with dummy data
|
||||
small_message[i] = (unsigned char) i;
|
||||
}
|
||||
|
||||
// Invalid diversifier
|
||||
ASSERT_EQ(boost::none, SaplingNoteEncryption::FromDiversifier({1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}));
|
||||
|
||||
// Encrypt to pk_1
|
||||
auto enc = *SaplingNoteEncryption::FromDiversifier(pk_1.d);
|
||||
auto ciphertext_1 = *enc.encrypt_to_recipient(
|
||||
pk_1.pk_d,
|
||||
message
|
||||
);
|
||||
auto epk_1 = enc.get_epk();
|
||||
{
|
||||
uint256 test_epk;
|
||||
uint256 test_esk = enc.get_esk();
|
||||
ASSERT_TRUE(librustzcash_sapling_ka_derivepublic(pk_1.d.begin(), test_esk.begin(), test_epk.begin()));
|
||||
ASSERT_TRUE(test_epk == epk_1);
|
||||
}
|
||||
auto cv_1 = random_uint256();
|
||||
auto cm_1 = random_uint256();
|
||||
auto out_ciphertext_1 = enc.encrypt_to_ourselves(
|
||||
sk.ovk,
|
||||
cv_1,
|
||||
cm_1,
|
||||
small_message
|
||||
);
|
||||
|
||||
// Encrypt to pk_2
|
||||
enc = *SaplingNoteEncryption::FromDiversifier(pk_2.d);
|
||||
auto ciphertext_2 = *enc.encrypt_to_recipient(
|
||||
pk_2.pk_d,
|
||||
message
|
||||
);
|
||||
auto epk_2 = enc.get_epk();
|
||||
|
||||
auto cv_2 = random_uint256();
|
||||
auto cm_2 = random_uint256();
|
||||
auto out_ciphertext_2 = enc.encrypt_to_ourselves(
|
||||
sk.ovk,
|
||||
cv_2,
|
||||
cm_2,
|
||||
small_message
|
||||
);
|
||||
|
||||
// Test nonce-reuse resistance of API
|
||||
{
|
||||
auto tmp_enc = *SaplingNoteEncryption::FromDiversifier(pk_1.d);
|
||||
|
||||
tmp_enc.encrypt_to_recipient(
|
||||
pk_1.pk_d,
|
||||
message
|
||||
);
|
||||
|
||||
ASSERT_THROW(tmp_enc.encrypt_to_recipient(
|
||||
pk_1.pk_d,
|
||||
message
|
||||
), std::logic_error);
|
||||
|
||||
tmp_enc.encrypt_to_ourselves(
|
||||
sk.ovk,
|
||||
cv_2,
|
||||
cm_2,
|
||||
small_message
|
||||
);
|
||||
|
||||
ASSERT_THROW(tmp_enc.encrypt_to_ourselves(
|
||||
sk.ovk,
|
||||
cv_2,
|
||||
cm_2,
|
||||
small_message
|
||||
), std::logic_error);
|
||||
}
|
||||
|
||||
// Try to decrypt
|
||||
auto plaintext_1 = *AttemptSaplingEncDecryption(
|
||||
ciphertext_1,
|
||||
ivk,
|
||||
epk_1
|
||||
);
|
||||
ASSERT_TRUE(message == plaintext_1);
|
||||
|
||||
auto small_plaintext_1 = *AttemptSaplingOutDecryption(
|
||||
out_ciphertext_1,
|
||||
sk.ovk,
|
||||
cv_1,
|
||||
cm_1,
|
||||
epk_1
|
||||
);
|
||||
ASSERT_TRUE(small_message == small_plaintext_1);
|
||||
|
||||
auto plaintext_2 = *AttemptSaplingEncDecryption(
|
||||
ciphertext_2,
|
||||
ivk,
|
||||
epk_2
|
||||
);
|
||||
ASSERT_TRUE(message == plaintext_2);
|
||||
|
||||
auto small_plaintext_2 = *AttemptSaplingOutDecryption(
|
||||
out_ciphertext_2,
|
||||
sk.ovk,
|
||||
cv_2,
|
||||
cm_2,
|
||||
epk_2
|
||||
);
|
||||
ASSERT_TRUE(small_message == small_plaintext_2);
|
||||
|
||||
// Try to decrypt out ciphertext with wrong key material
|
||||
ASSERT_FALSE(AttemptSaplingOutDecryption(
|
||||
out_ciphertext_1,
|
||||
random_uint256(),
|
||||
cv_1,
|
||||
cm_1,
|
||||
epk_1
|
||||
));
|
||||
ASSERT_FALSE(AttemptSaplingOutDecryption(
|
||||
out_ciphertext_1,
|
||||
sk.ovk,
|
||||
random_uint256(),
|
||||
cm_1,
|
||||
epk_1
|
||||
));
|
||||
ASSERT_FALSE(AttemptSaplingOutDecryption(
|
||||
out_ciphertext_1,
|
||||
sk.ovk,
|
||||
cv_1,
|
||||
random_uint256(),
|
||||
epk_1
|
||||
));
|
||||
ASSERT_FALSE(AttemptSaplingOutDecryption(
|
||||
out_ciphertext_1,
|
||||
sk.ovk,
|
||||
cv_1,
|
||||
cm_1,
|
||||
random_uint256()
|
||||
));
|
||||
|
||||
// Try to decrypt with wrong ephemeral key
|
||||
ASSERT_FALSE(AttemptSaplingEncDecryption(
|
||||
ciphertext_1,
|
||||
ivk,
|
||||
epk_2
|
||||
));
|
||||
ASSERT_FALSE(AttemptSaplingEncDecryption(
|
||||
ciphertext_2,
|
||||
ivk,
|
||||
epk_1
|
||||
));
|
||||
|
||||
// Try to decrypt with wrong ivk
|
||||
ASSERT_FALSE(AttemptSaplingEncDecryption(
|
||||
ciphertext_1,
|
||||
uint256(),
|
||||
epk_1
|
||||
));
|
||||
ASSERT_FALSE(AttemptSaplingEncDecryption(
|
||||
ciphertext_2,
|
||||
uint256(),
|
||||
epk_2
|
||||
));
|
||||
}
|
||||
|
||||
TEST(noteencryption, api)
|
||||
{
|
||||
uint256 sk_enc = ZCNoteEncryption::generate_privkey(uint252(uint256S("21035d60bc1983e37950ce4803418a8fb33ea68d5b937ca382ecbae7564d6a07")));
|
||||
|
|
|
@ -84,33 +84,17 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
static constexpr size_t SAPLING_ENC_CIPHERTEXT_SIZE = (
|
||||
1 + // leading byte
|
||||
11 + // d
|
||||
8 + // value
|
||||
32 + // rcm
|
||||
ZC_MEMO_SIZE + // memo
|
||||
NOTEENCRYPTION_AUTH_BYTES);
|
||||
|
||||
static constexpr size_t SAPLING_OUT_CIPHERTEXT_SIZE = (
|
||||
32 + // pkd_new
|
||||
32 + // esk
|
||||
NOTEENCRYPTION_AUTH_BYTES);
|
||||
|
||||
/**
|
||||
* A shielded output to a transaction. It contains data that describes an Output transfer.
|
||||
*/
|
||||
class OutputDescription
|
||||
{
|
||||
public:
|
||||
typedef std::array<unsigned char, SAPLING_ENC_CIPHERTEXT_SIZE> sapling_enc_ct_t; // TODO: Replace with actual type
|
||||
typedef std::array<unsigned char, SAPLING_OUT_CIPHERTEXT_SIZE> sapling_out_ct_t; // TODO: Replace with actual type
|
||||
|
||||
uint256 cv; //!< A value commitment to the value of the output note.
|
||||
uint256 cm; //!< The note commitment for the output note.
|
||||
uint256 ephemeralKey; //!< A Jubjub public key.
|
||||
sapling_enc_ct_t encCiphertext; //!< A ciphertext component for the encrypted output note.
|
||||
sapling_out_ct_t outCiphertext; //!< A ciphertext component for the encrypted output note.
|
||||
libzcash::SaplingEncCiphertext encCiphertext; //!< A ciphertext component for the encrypted output note.
|
||||
libzcash::SaplingOutCiphertext outCiphertext; //!< A ciphertext component for the encrypted output note.
|
||||
libzcash::GrothProof zkproof; //!< A zero-knowledge proof using the output circuit.
|
||||
|
||||
OutputDescription() { }
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
#include "uint256.h"
|
||||
#include "uint252.h"
|
||||
#include "serialize.h"
|
||||
#include "Zcash.h"
|
||||
|
||||
#include <boost/variant.hpp>
|
||||
|
||||
|
@ -18,7 +19,7 @@ const size_t SerializedPaymentAddressSize = 64;
|
|||
const size_t SerializedViewingKeySize = 64;
|
||||
const size_t SerializedSpendingKeySize = 32;
|
||||
|
||||
typedef std::array<unsigned char, 11> diversifier_t;
|
||||
typedef std::array<unsigned char, ZC_DIVERSIFIER_SIZE> diversifier_t;
|
||||
|
||||
class SproutPaymentAddress {
|
||||
public:
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
#include "sodium.h"
|
||||
#include <boost/static_assert.hpp>
|
||||
#include "prf.h"
|
||||
#include "librustzcash.h"
|
||||
|
||||
#define NOTEENCRYPTION_CIPHER_KEYSIZE 32
|
||||
|
||||
|
@ -13,6 +14,58 @@ void clamp_curve25519(unsigned char key[crypto_scalarmult_SCALARBYTES])
|
|||
key[31] |= 64;
|
||||
}
|
||||
|
||||
void PRF_ock(
|
||||
unsigned char K[NOTEENCRYPTION_CIPHER_KEYSIZE],
|
||||
const uint256 &ovk,
|
||||
const uint256 &cv,
|
||||
const uint256 &cm,
|
||||
const uint256 &epk
|
||||
)
|
||||
{
|
||||
unsigned char block[128] = {};
|
||||
memcpy(block+0, ovk.begin(), 32);
|
||||
memcpy(block+32, cv.begin(), 32);
|
||||
memcpy(block+64, cm.begin(), 32);
|
||||
memcpy(block+96, epk.begin(), 32);
|
||||
|
||||
unsigned char personalization[crypto_generichash_blake2b_PERSONALBYTES] = {};
|
||||
memcpy(personalization, "Zcash_Derive_ock", 16);
|
||||
|
||||
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");
|
||||
}
|
||||
}
|
||||
|
||||
void KDF_Sapling(
|
||||
unsigned char K[NOTEENCRYPTION_CIPHER_KEYSIZE],
|
||||
const uint256 &dhsecret,
|
||||
const uint256 &epk
|
||||
)
|
||||
{
|
||||
unsigned char block[64] = {};
|
||||
memcpy(block+0, dhsecret.begin(), 32);
|
||||
memcpy(block+32, epk.begin(), 32);
|
||||
|
||||
unsigned char personalization[crypto_generichash_blake2b_PERSONALBYTES] = {};
|
||||
memcpy(personalization, "Zcash_SaplingKDF", 16);
|
||||
|
||||
if (crypto_generichash_blake2b_salt_personal(K, NOTEENCRYPTION_CIPHER_KEYSIZE,
|
||||
block, 64,
|
||||
NULL, 0, // No key.
|
||||
NULL, // No salt.
|
||||
personalization
|
||||
) != 0)
|
||||
{
|
||||
throw std::logic_error("hash function failure");
|
||||
}
|
||||
}
|
||||
|
||||
void KDF(unsigned char K[NOTEENCRYPTION_CIPHER_KEYSIZE],
|
||||
const uint256 &dhsecret,
|
||||
const uint256 &epk,
|
||||
|
@ -48,6 +101,155 @@ void KDF(unsigned char K[NOTEENCRYPTION_CIPHER_KEYSIZE],
|
|||
|
||||
namespace libzcash {
|
||||
|
||||
boost::optional<SaplingNoteEncryption> SaplingNoteEncryption::FromDiversifier(diversifier_t d) {
|
||||
uint256 epk;
|
||||
uint256 esk;
|
||||
|
||||
// Pick random esk
|
||||
librustzcash_sapling_generate_r(esk.begin());
|
||||
|
||||
// Compute epk given the diversifier
|
||||
if (!librustzcash_sapling_ka_derivepublic(d.begin(), esk.begin(), epk.begin())) {
|
||||
return boost::none;
|
||||
}
|
||||
|
||||
return SaplingNoteEncryption(epk, esk);
|
||||
}
|
||||
|
||||
boost::optional<SaplingEncCiphertext> SaplingNoteEncryption::encrypt_to_recipient(
|
||||
const uint256 &pk_d,
|
||||
const SaplingEncPlaintext &message
|
||||
)
|
||||
{
|
||||
if (already_encrypted_enc) {
|
||||
throw std::logic_error("already encrypted to the recipient using this key");
|
||||
}
|
||||
|
||||
uint256 dhsecret;
|
||||
|
||||
if (!librustzcash_sapling_ka_agree(pk_d.begin(), esk.begin(), dhsecret.begin())) {
|
||||
return boost::none;
|
||||
}
|
||||
|
||||
// Construct the symmetric key
|
||||
unsigned char K[NOTEENCRYPTION_CIPHER_KEYSIZE];
|
||||
KDF_Sapling(K, dhsecret, epk);
|
||||
|
||||
// The nonce is zero because we never reuse keys
|
||||
unsigned char cipher_nonce[crypto_aead_chacha20poly1305_IETF_NPUBBYTES] = {};
|
||||
|
||||
SaplingEncCiphertext ciphertext;
|
||||
|
||||
crypto_aead_chacha20poly1305_ietf_encrypt(
|
||||
ciphertext.begin(), NULL,
|
||||
message.begin(), ZC_SAPLING_ENCPLAINTEXT_SIZE,
|
||||
NULL, 0, // no "additional data"
|
||||
NULL, cipher_nonce, K
|
||||
);
|
||||
|
||||
already_encrypted_enc = true;
|
||||
|
||||
return ciphertext;
|
||||
}
|
||||
|
||||
boost::optional<SaplingEncPlaintext> AttemptSaplingEncDecryption(
|
||||
const SaplingEncCiphertext &ciphertext,
|
||||
const uint256 &ivk,
|
||||
const uint256 &epk
|
||||
)
|
||||
{
|
||||
uint256 dhsecret;
|
||||
|
||||
if (!librustzcash_sapling_ka_agree(epk.begin(), ivk.begin(), dhsecret.begin())) {
|
||||
return boost::none;
|
||||
}
|
||||
|
||||
// Construct the symmetric key
|
||||
unsigned char K[NOTEENCRYPTION_CIPHER_KEYSIZE];
|
||||
KDF_Sapling(K, dhsecret, epk);
|
||||
|
||||
// The nonce is zero because we never reuse keys
|
||||
unsigned char cipher_nonce[crypto_aead_chacha20poly1305_IETF_NPUBBYTES] = {};
|
||||
|
||||
SaplingEncPlaintext plaintext;
|
||||
|
||||
if (crypto_aead_chacha20poly1305_ietf_decrypt(
|
||||
plaintext.begin(), NULL,
|
||||
NULL,
|
||||
ciphertext.begin(), ZC_SAPLING_ENCCIPHERTEXT_SIZE,
|
||||
NULL,
|
||||
0,
|
||||
cipher_nonce, K) != 0)
|
||||
{
|
||||
return boost::none;
|
||||
}
|
||||
|
||||
return plaintext;
|
||||
}
|
||||
|
||||
SaplingOutCiphertext SaplingNoteEncryption::encrypt_to_ourselves(
|
||||
const uint256 &ovk,
|
||||
const uint256 &cv,
|
||||
const uint256 &cm,
|
||||
const SaplingOutPlaintext &message
|
||||
)
|
||||
{
|
||||
if (already_encrypted_out) {
|
||||
throw std::logic_error("already encrypted to the recipient using this key");
|
||||
}
|
||||
|
||||
// Construct the symmetric key
|
||||
unsigned char K[NOTEENCRYPTION_CIPHER_KEYSIZE];
|
||||
PRF_ock(K, ovk, cv, cm, epk);
|
||||
|
||||
// The nonce is zero because we never reuse keys
|
||||
unsigned char cipher_nonce[crypto_aead_chacha20poly1305_IETF_NPUBBYTES] = {};
|
||||
|
||||
SaplingOutCiphertext ciphertext;
|
||||
|
||||
crypto_aead_chacha20poly1305_ietf_encrypt(
|
||||
ciphertext.begin(), NULL,
|
||||
message.begin(), ZC_SAPLING_OUTPLAINTEXT_SIZE,
|
||||
NULL, 0, // no "additional data"
|
||||
NULL, cipher_nonce, K
|
||||
);
|
||||
|
||||
already_encrypted_out = true;
|
||||
|
||||
return ciphertext;
|
||||
}
|
||||
|
||||
boost::optional<SaplingOutPlaintext> AttemptSaplingOutDecryption(
|
||||
const SaplingOutCiphertext &ciphertext,
|
||||
const uint256 &ovk,
|
||||
const uint256 &cv,
|
||||
const uint256 &cm,
|
||||
const uint256 &epk
|
||||
)
|
||||
{
|
||||
// Construct the symmetric key
|
||||
unsigned char K[NOTEENCRYPTION_CIPHER_KEYSIZE];
|
||||
PRF_ock(K, ovk, cv, cm, epk);
|
||||
|
||||
// The nonce is zero because we never reuse keys
|
||||
unsigned char cipher_nonce[crypto_aead_chacha20poly1305_IETF_NPUBBYTES] = {};
|
||||
|
||||
SaplingOutPlaintext plaintext;
|
||||
|
||||
if (crypto_aead_chacha20poly1305_ietf_decrypt(
|
||||
plaintext.begin(), NULL,
|
||||
NULL,
|
||||
ciphertext.begin(), ZC_SAPLING_OUTCIPHERTEXT_SIZE,
|
||||
NULL,
|
||||
0,
|
||||
cipher_nonce, K) != 0)
|
||||
{
|
||||
return boost::none;
|
||||
}
|
||||
|
||||
return plaintext;
|
||||
}
|
||||
|
||||
template<size_t MLEN>
|
||||
NoteEncryption<MLEN>::NoteEncryption(uint256 hSig) : nonce(0), hSig(hSig) {
|
||||
// All of this code assumes crypto_scalarmult_BYTES is 32
|
||||
|
|
|
@ -10,12 +10,78 @@ https://github.com/zcash/zips/blob/master/protocol/protocol.pdf
|
|||
#include "uint252.h"
|
||||
|
||||
#include "zcash/Zcash.h"
|
||||
#include "zcash/Address.hpp"
|
||||
|
||||
#include <array>
|
||||
|
||||
namespace libzcash {
|
||||
|
||||
#define NOTEENCRYPTION_AUTH_BYTES 16
|
||||
// Ciphertext for the recipient to decrypt
|
||||
typedef std::array<unsigned char, ZC_SAPLING_ENCCIPHERTEXT_SIZE> SaplingEncCiphertext;
|
||||
typedef std::array<unsigned char, ZC_SAPLING_ENCPLAINTEXT_SIZE> SaplingEncPlaintext;
|
||||
|
||||
// Ciphertext for outgoing viewing key to decrypt
|
||||
typedef std::array<unsigned char, ZC_SAPLING_OUTCIPHERTEXT_SIZE> SaplingOutCiphertext;
|
||||
typedef std::array<unsigned char, ZC_SAPLING_OUTPLAINTEXT_SIZE> SaplingOutPlaintext;
|
||||
|
||||
//! This is not a thread-safe API.
|
||||
class SaplingNoteEncryption {
|
||||
protected:
|
||||
// Ephemeral public key
|
||||
uint256 epk;
|
||||
|
||||
// Ephemeral secret key
|
||||
uint256 esk;
|
||||
|
||||
bool already_encrypted_enc;
|
||||
bool already_encrypted_out;
|
||||
|
||||
SaplingNoteEncryption(uint256 epk, uint256 esk) : epk(epk), esk(esk), already_encrypted_enc(false), already_encrypted_out(false) {
|
||||
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
static boost::optional<SaplingNoteEncryption> FromDiversifier(diversifier_t d);
|
||||
|
||||
boost::optional<SaplingEncCiphertext> encrypt_to_recipient(
|
||||
const uint256 &pk_d,
|
||||
const SaplingEncPlaintext &message
|
||||
);
|
||||
|
||||
SaplingOutCiphertext encrypt_to_ourselves(
|
||||
const uint256 &ovk,
|
||||
const uint256 &cv,
|
||||
const uint256 &cm,
|
||||
const SaplingOutPlaintext &message
|
||||
);
|
||||
|
||||
uint256 get_epk() const {
|
||||
return epk;
|
||||
}
|
||||
|
||||
uint256 get_esk() const {
|
||||
return esk;
|
||||
}
|
||||
};
|
||||
|
||||
// Attempts to decrypt a Sapling note. This will not check that the contents
|
||||
// of the ciphertext are correct.
|
||||
boost::optional<SaplingEncPlaintext> AttemptSaplingEncDecryption(
|
||||
const SaplingEncCiphertext &ciphertext,
|
||||
const uint256 &ivk,
|
||||
const uint256 &epk
|
||||
);
|
||||
|
||||
// Attempts to decrypt a Sapling note. This will not check that the contents
|
||||
// of the ciphertext are correct.
|
||||
boost::optional<SaplingOutPlaintext> AttemptSaplingOutDecryption(
|
||||
const SaplingOutCiphertext &ciphertext,
|
||||
const uint256 &ovk,
|
||||
const uint256 &cv,
|
||||
const uint256 &cm,
|
||||
const uint256 &epk
|
||||
);
|
||||
|
||||
template<size_t MLEN>
|
||||
class NoteEncryption {
|
||||
|
|
|
@ -8,12 +8,23 @@
|
|||
|
||||
#define SAPLING_INCREMENTAL_MERKLE_TREE_DEPTH 32
|
||||
|
||||
#define NOTEENCRYPTION_AUTH_BYTES 16
|
||||
|
||||
#define ZC_NOTEPLAINTEXT_LEADING 1
|
||||
#define ZC_V_SIZE 8
|
||||
#define ZC_RHO_SIZE 32
|
||||
#define ZC_R_SIZE 32
|
||||
#define ZC_MEMO_SIZE 512
|
||||
#define ZC_DIVERSIFIER_SIZE 11
|
||||
#define ZC_JUBJUB_POINT_SIZE 32
|
||||
#define ZC_JUBJUB_SCALAR_SIZE 32
|
||||
|
||||
#define ZC_NOTEPLAINTEXT_SIZE (ZC_NOTEPLAINTEXT_LEADING + ZC_V_SIZE + ZC_RHO_SIZE + ZC_R_SIZE + ZC_MEMO_SIZE)
|
||||
|
||||
#define ZC_SAPLING_ENCPLAINTEXT_SIZE (ZC_NOTEPLAINTEXT_LEADING + ZC_DIVERSIFIER_SIZE + ZC_V_SIZE + ZC_R_SIZE + ZC_MEMO_SIZE)
|
||||
#define ZC_SAPLING_OUTPLAINTEXT_SIZE (ZC_JUBJUB_POINT_SIZE + ZC_JUBJUB_SCALAR_SIZE)
|
||||
|
||||
#define ZC_SAPLING_ENCCIPHERTEXT_SIZE (ZC_SAPLING_ENCPLAINTEXT_SIZE + NOTEENCRYPTION_AUTH_BYTES)
|
||||
#define ZC_SAPLING_OUTCIPHERTEXT_SIZE (ZC_SAPLING_OUTPLAINTEXT_SIZE + NOTEENCRYPTION_AUTH_BYTES)
|
||||
|
||||
#endif // ZC_ZCASH_H_
|
||||
|
|
Loading…
Reference in New Issue