Implement Sapling note decryption using full viewing key.

This commit is contained in:
Simon 2018-07-20 16:31:48 -07:00
parent 687bd96cbd
commit 7b913c3e5e
5 changed files with 96 additions and 0 deletions

View File

@ -111,6 +111,25 @@ TEST(noteencryption, NotePlaintext)
ASSERT_TRUE(decrypted_out_ct_unwrapped.pk_d == out_pt.pk_d);
ASSERT_TRUE(decrypted_out_ct_unwrapped.esk == out_pt.esk);
// Test sender can decrypt the note ciphertext.
foo = SaplingNotePlaintext::decryptUsingFullViewingKey(
ct,
epk,
decrypted_out_ct_unwrapped.esk,
decrypted_out_ct_unwrapped.pk_d
);
if (!foo) {
FAIL();
}
bar = foo.get();
ASSERT_TRUE(bar.value() == pt.value());
ASSERT_TRUE(bar.memo() == pt.memo());
ASSERT_TRUE(bar.d == pt.d);
ASSERT_TRUE(bar.rcm == pt.rcm);
}
TEST(noteencryption, SaplingApi)

View File

@ -208,6 +208,30 @@ boost::optional<SaplingNotePlaintext> SaplingNotePlaintext::decrypt(
return ret;
}
boost::optional<SaplingNotePlaintext> SaplingNotePlaintext::decryptUsingFullViewingKey(
const SaplingEncCiphertext &ciphertext,
const uint256 &epk,
const uint256 &esk,
const uint256 &pk_d
)
{
auto pt = AttemptSaplingEncDecryptionUsingFullViewingKey(ciphertext, epk, esk, pk_d);
if (!pt) {
return boost::none;
}
// Deserialize from the plaintext
CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
ss << pt.get();
SaplingNotePlaintext ret;
ss >> ret;
assert(ss.size() == 0);
return ret;
}
boost::optional<SaplingNotePlaintextEncryptionResult> SaplingNotePlaintext::encrypt(const uint256& pk_d) const
{
// Get the encryptor

View File

@ -133,6 +133,13 @@ public:
const uint256 &epk
);
static boost::optional<SaplingNotePlaintext> decryptUsingFullViewingKey(
const SaplingEncCiphertext &ciphertext,
const uint256 &epk,
const uint256 &esk,
const uint256 &pk_d
);
boost::optional<SaplingNote> note(const SaplingIncomingViewingKey& ivk) const;
virtual ~SaplingNotePlaintext() {}

View File

@ -187,6 +187,43 @@ boost::optional<SaplingEncPlaintext> AttemptSaplingEncDecryption(
return plaintext;
}
boost::optional<SaplingEncPlaintext> AttemptSaplingEncDecryptionUsingFullViewingKey (
const SaplingEncCiphertext &ciphertext,
const uint256 &epk,
const uint256 &esk,
const uint256 &pk_d
)
{
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] = {};
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,

View File

@ -73,6 +73,15 @@ boost::optional<SaplingEncPlaintext> AttemptSaplingEncDecryption(
const uint256 &epk
);
// Attempts to decrypt a Sapling note using full viewing key.
// This will not check that the contents of the ciphertext are correct.
boost::optional<SaplingEncPlaintext> AttemptSaplingEncDecryptionUsingFullViewingKey (
const SaplingEncCiphertext &ciphertext,
const uint256 &epk,
const uint256 &esk,
const uint256 &pk_d
);
// Attempts to decrypt a Sapling note. This will not check that the contents
// of the ciphertext are correct.
boost::optional<SaplingOutPlaintext> AttemptSaplingOutDecryption(