Add payment disclosure as experimental feature.

This commit is contained in:
Simon
2017-11-14 13:29:05 -08:00
parent 086c6bed58
commit 45232b1961
27 changed files with 1324 additions and 14 deletions

View File

@@ -198,7 +198,8 @@ public:
uint64_t vpub_old,
uint64_t vpub_new,
const uint256& rt,
bool computeProof
bool computeProof,
uint256 *out_esk // Payment disclosure
) {
if (computeProof && !pk) {
throw std::runtime_error("JoinSplit proving key not loaded");
@@ -303,6 +304,12 @@ public:
}
out_ephemeralKey = encryptor.get_epk();
// !!! Payment disclosure START
if (out_esk != nullptr) {
*out_esk = encryptor.get_esk();
}
// !!! Payment disclosure END
}
// Authenticate h_sig with each of the input

View File

@@ -78,7 +78,11 @@ public:
uint64_t vpub_old,
uint64_t vpub_new,
const uint256& rt,
bool computeProof = true
bool computeProof = true,
// For paymentdisclosure, we need to retrieve the esk.
// Reference as non-const parameter with default value leads to compile error.
// So use pointer for simplicity.
uint256 *out_esk = nullptr
) = 0;
virtual bool verify(

View File

@@ -135,6 +135,52 @@ typename NoteDecryption<MLEN>::Plaintext NoteDecryption<MLEN>::decrypt
return plaintext;
}
//
// Payment disclosure - decrypt with esk
//
template<size_t MLEN>
typename PaymentDisclosureNoteDecryption<MLEN>::Plaintext PaymentDisclosureNoteDecryption<MLEN>::decryptWithEsk
(const PaymentDisclosureNoteDecryption<MLEN>::Ciphertext &ciphertext,
const uint256 &pk_enc,
const uint256 &esk,
const uint256 &hSig,
unsigned char nonce
) const
{
uint256 dhsecret;
if (crypto_scalarmult(dhsecret.begin(), esk.begin(), pk_enc.begin()) != 0) {
throw std::logic_error("Could not create DH secret");
}
// Regenerate keypair
uint256 epk = NoteEncryption<MLEN>::generate_pubkey(esk);
unsigned char K[NOTEENCRYPTION_CIPHER_KEYSIZE];
KDF(K, dhsecret, epk, pk_enc, hSig, nonce);
// The nonce is zero because we never reuse keys
unsigned char cipher_nonce[crypto_aead_chacha20poly1305_IETF_NPUBBYTES] = {};
PaymentDisclosureNoteDecryption<MLEN>::Plaintext plaintext;
// Message length is always NOTEENCRYPTION_AUTH_BYTES less than
// the ciphertext length.
if (crypto_aead_chacha20poly1305_ietf_decrypt(plaintext.begin(), NULL,
NULL,
ciphertext.begin(), PaymentDisclosureNoteDecryption<MLEN>::CLEN,
NULL,
0,
cipher_nonce, K) != 0) {
throw note_decryption_failed();
}
return plaintext;
}
template<size_t MLEN>
uint256 NoteEncryption<MLEN>::generate_privkey(const uint252 &a_sk)
{
@@ -176,4 +222,6 @@ uint252 random_uint252()
template class NoteEncryption<ZC_NOTEPLAINTEXT_SIZE>;
template class NoteDecryption<ZC_NOTEPLAINTEXT_SIZE>;
template class PaymentDisclosureNoteDecryption<ZC_NOTEPLAINTEXT_SIZE>;
}

View File

@@ -31,6 +31,11 @@ public:
NoteEncryption(uint256 hSig);
// Gets the ephemeral secret key
uint256 get_esk() {
return esk;
}
// Gets the ephemeral public key
uint256 get_epk() {
return epk;
@@ -87,9 +92,34 @@ public:
note_decryption_failed() : std::runtime_error("Could not decrypt message") { }
};
// Subclass PaymentDisclosureNoteDecryption provides a method to decrypt a note with esk.
template<size_t MLEN>
class PaymentDisclosureNoteDecryption : public NoteDecryption<MLEN> {
protected:
public:
enum { CLEN=MLEN+NOTEENCRYPTION_AUTH_BYTES };
typedef boost::array<unsigned char, CLEN> Ciphertext;
typedef boost::array<unsigned char, MLEN> Plaintext;
PaymentDisclosureNoteDecryption() : NoteDecryption<MLEN>() {}
PaymentDisclosureNoteDecryption(uint256 sk_enc) : NoteDecryption<MLEN>(sk_enc) {}
Plaintext decryptWithEsk(
const Ciphertext &ciphertext,
const uint256 &pk_enc,
const uint256 &esk,
const uint256 &hSig,
unsigned char nonce
) const;
};
}
typedef libzcash::NoteEncryption<ZC_NOTEPLAINTEXT_SIZE> ZCNoteEncryption;
typedef libzcash::NoteDecryption<ZC_NOTEPLAINTEXT_SIZE> ZCNoteDecryption;
typedef libzcash::PaymentDisclosureNoteDecryption<ZC_NOTEPLAINTEXT_SIZE> ZCPaymentDisclosureNoteDecryption;
#endif /* ZC_NOTE_ENCRYPTION_H_ */