Prevent nonce reuse in Sapling note encryption API.

This commit is contained in:
Sean Bowe 2018-06-14 12:21:28 -06:00
parent 90073aeca5
commit c03e22612d
3 changed files with 45 additions and 1 deletions

View File

@ -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,

View File

@ -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;
}

View File

@ -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) {
}