Browse Source

Prevent nonce reuse in Sapling note encryption API.

metaverse
Sean Bowe 6 years ago
parent
commit
c03e22612d
  1. 29
      src/gtest/test_noteencryption.cpp
  2. 12
      src/zcash/NoteEncryption.cpp
  3. 5
      src/zcash/NoteEncryption.hpp

29
src/gtest/test_noteencryption.cpp

@ -78,6 +78,35 @@ TEST(noteencryption, sapling_api)
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,

12
src/zcash/NoteEncryption.cpp

@ -121,6 +121,10 @@ boost::optional<SaplingEncCiphertext> SaplingNoteEncryption::encrypt_to_recipien
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())) {
@ -143,6 +147,8 @@ boost::optional<SaplingEncCiphertext> SaplingNoteEncryption::encrypt_to_recipien
NULL, cipher_nonce, K
);
already_encrypted_enc = true;
return ciphertext;
}
@ -188,6 +194,10 @@ SaplingOutCiphertext SaplingNoteEncryption::encrypt_to_ourselves(
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);
@ -204,6 +214,8 @@ SaplingOutCiphertext SaplingNoteEncryption::encrypt_to_ourselves(
NULL, cipher_nonce, K
);
already_encrypted_out = true;
return ciphertext;
}

5
src/zcash/NoteEncryption.hpp

@ -32,7 +32,10 @@ protected:
// Ephemeral secret key
uint256 esk;
SaplingNoteEncryption(uint256 epk, uint256 esk) : epk(epk), esk(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) {
}

Loading…
Cancel
Save