Line data Source code
1 : // Copyright (c) 2016-2020 The ZCash developers
2 : // Copyright (c) 2021 The PIVX Core developers
3 : // Distributed under the MIT software license, see the accompanying
4 : // file COPYING or https://www.opensource.org/licenses/mit-license.php.
5 :
6 : #include "sapling/note.h"
7 :
8 : #include "crypto/sha256.h"
9 : #include "random.h"
10 : #include "sapling/prf.h"
11 : #include "sapling/sapling_util.h"
12 : #include "streams.h"
13 : #include "version.h"
14 :
15 : #include <librustzcash.h>
16 :
17 : using namespace libzcash;
18 :
19 : // Construct and populate Sapling note for a given payment address and value.
20 2413 : SaplingNote::SaplingNote(const SaplingPaymentAddress& address, const uint64_t value) :
21 2413 : BaseNote(value)
22 : {
23 2413 : d = address.d;
24 2413 : pk_d = address.pk_d;
25 2413 : librustzcash_sapling_generate_r(r.begin());
26 2413 : }
27 :
28 : // Call librustzcash to compute the commitment
29 2737 : Optional<uint256> SaplingNote::cmu() const
30 : {
31 2737 : uint256 result;
32 2737 : if (!librustzcash_sapling_compute_cm(
33 : d.data(),
34 : pk_d.begin(),
35 : value(),
36 : r.begin(),
37 : result.begin()
38 : ))
39 : {
40 0 : return nullopt;
41 : }
42 :
43 2737 : return result;
44 : }
45 :
46 : // Call librustzcash to compute the nullifier
47 977 : Optional<uint256> SaplingNote::nullifier(const SaplingFullViewingKey& vk, const uint64_t position) const
48 : {
49 977 : auto ak = vk.ak;
50 977 : auto nk = vk.nk;
51 :
52 977 : uint256 result;
53 977 : if (!librustzcash_sapling_compute_nf(
54 : d.data(),
55 : pk_d.begin(),
56 : value(),
57 : r.begin(),
58 977 : ak.begin(),
59 977 : nk.begin(),
60 : position,
61 : result.begin()
62 : ))
63 : {
64 0 : return nullopt;
65 : }
66 :
67 977 : return result;
68 : }
69 :
70 : // Construct and populate SaplingNotePlaintext for a given note and memo.
71 1324 : SaplingNotePlaintext::SaplingNotePlaintext(
72 : const SaplingNote& note,
73 1324 : const std::array<unsigned char, ZC_MEMO_SIZE>& memo) : BaseNotePlaintext(note, memo)
74 : {
75 1324 : d = note.d;
76 1324 : rcm = note.r;
77 1324 : }
78 :
79 :
80 2078 : Optional<SaplingNote> SaplingNotePlaintext::note(const SaplingIncomingViewingKey& ivk) const
81 : {
82 2078 : auto addr = ivk.address(d);
83 2078 : if (addr) {
84 2078 : return SaplingNote(d, addr.get().pk_d, value_, rcm);
85 : } else {
86 0 : return nullopt;
87 : }
88 : }
89 :
90 104 : Optional<SaplingOutgoingPlaintext> SaplingOutgoingPlaintext::decrypt(
91 : const SaplingOutCiphertext& ciphertext,
92 : const uint256& ovk,
93 : const uint256& cv,
94 : const uint256& cm,
95 : const uint256& epk
96 : )
97 : {
98 208 : auto pt = AttemptSaplingOutDecryption(ciphertext, ovk, cv, cm, epk);
99 104 : if (!pt) {
100 8 : return nullopt;
101 : }
102 :
103 : // Deserialize from the plaintext
104 200 : CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
105 96 : ss << pt.get();
106 :
107 96 : SaplingOutgoingPlaintext ret;
108 96 : ss >> ret;
109 :
110 96 : assert(ss.size() == 0);
111 :
112 96 : return ret;
113 : }
114 :
115 8905 : Optional<SaplingNotePlaintext> SaplingNotePlaintext::decrypt(
116 : const SaplingEncCiphertext& ciphertext,
117 : const uint256& ivk,
118 : const uint256& epk,
119 : const uint256& cmu
120 : )
121 : {
122 17810 : auto pt = AttemptSaplingEncDecryption(ciphertext, ivk, epk);
123 8905 : if (!pt) {
124 4761 : return nullopt;
125 : }
126 :
127 : // Deserialize from the plaintext
128 13049 : CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
129 4144 : ss << pt.get();
130 :
131 8288 : SaplingNotePlaintext ret;
132 4144 : ss >> ret;
133 :
134 4144 : assert(ss.size() == 0);
135 :
136 4144 : uint256 pk_d;
137 4144 : if (!librustzcash_ivk_to_pkd(ivk.begin(), ret.d.data(), pk_d.begin())) {
138 0 : return nullopt;
139 : }
140 :
141 4144 : uint256 cmu_expected;
142 4144 : if (!librustzcash_sapling_compute_cm(
143 4144 : ret.d.data(),
144 4144 : pk_d.begin(),
145 : ret.value(),
146 4144 : ret.rcm.begin(),
147 : cmu_expected.begin()
148 : ))
149 : {
150 0 : return nullopt;
151 : }
152 :
153 4144 : if (cmu_expected != cmu) {
154 1 : return nullopt;
155 : }
156 :
157 4144 : return ret;
158 : }
159 :
160 97 : Optional<SaplingNotePlaintext> SaplingNotePlaintext::decrypt(
161 : const SaplingEncCiphertext& ciphertext,
162 : const uint256& epk,
163 : const uint256& esk,
164 : const uint256& pk_d,
165 : const uint256& cmu
166 : )
167 : {
168 194 : auto pt = AttemptSaplingEncDecryption(ciphertext, epk, esk, pk_d);
169 97 : if (!pt) {
170 0 : return nullopt;
171 : }
172 :
173 : // Deserialize from the plaintext
174 194 : CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
175 97 : ss << pt.get();
176 :
177 194 : SaplingNotePlaintext ret;
178 97 : ss >> ret;
179 :
180 97 : uint256 cmu_expected;
181 97 : if (!librustzcash_sapling_compute_cm(
182 97 : ret.d.data(),
183 : pk_d.begin(),
184 : ret.value(),
185 97 : ret.rcm.begin(),
186 : cmu_expected.begin()
187 : ))
188 : {
189 0 : return nullopt;
190 : }
191 :
192 97 : if (cmu_expected != cmu) {
193 1 : return nullopt;
194 : }
195 :
196 96 : assert(ss.size() == 0);
197 :
198 97 : return ret;
199 : }
200 :
201 1324 : Optional<SaplingNotePlaintextEncryptionResult> SaplingNotePlaintext::encrypt(const uint256& pk_d) const
202 : {
203 : // Get the encryptor
204 2648 : auto sne = SaplingNoteEncryption::FromDiversifier(d);
205 1324 : if (!sne) {
206 0 : return nullopt;
207 : }
208 1324 : auto enc = sne.get();
209 :
210 : // Create the plaintext
211 2648 : CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
212 1324 : ss << (*this);
213 1324 : SaplingEncPlaintext pt;
214 1324 : assert(pt.size() == ss.size());
215 1324 : memcpy(&pt[0], &ss[0], pt.size());
216 :
217 : // Encrypt the plaintext
218 2648 : auto encciphertext = enc.encrypt_to_recipient(pk_d, pt);
219 1324 : if (!encciphertext) {
220 0 : return nullopt;
221 : }
222 1324 : return SaplingNotePlaintextEncryptionResult(encciphertext.get(), enc);
223 : }
224 :
225 :
226 1324 : SaplingOutCiphertext SaplingOutgoingPlaintext::encrypt(
227 : const uint256& ovk,
228 : const uint256& cv,
229 : const uint256& cm,
230 : SaplingNoteEncryption& enc
231 : ) const
232 : {
233 : // Create the plaintext
234 1324 : CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
235 1324 : ss << (*this);
236 1324 : SaplingOutPlaintext pt;
237 1324 : assert(pt.size() == ss.size());
238 1324 : memcpy(&pt[0], &ss[0], pt.size());
239 :
240 2648 : return enc.encrypt_to_ourselves(ovk, cv, cm, pt);
241 : }
|