bitcoin_key/key.rs
1crate::ix!();
2
3/**
4 | An encapsulated private key.
5 |
6 */
7pub struct Key {
8
9 /**
10 | Whether this private key is valid. We
11 | check for correctness when modifying the
12 | key data, so fValid should always
13 | correspond to the actual state.
14 */
15 valid: bool,
16
17 /**
18 Whether the public key corresponding to this
19 private key is (to be) compressed.
20 */
21 compressed: bool,
22
23 /**
24 The actual byte data
25 */
26 keydata: Vec<u8,SecureAllocator>,
27}
28
29impl Key {
30
31 /**
32 | Initialize using begin and end iterators
33 | to byte data.
34 |
35 */
36 pub fn set<T>(&mut self,
37 pbegin: T,
38 pend: T,
39 compressed_in: bool) {
40
41 todo!();
42 /*
43 if (size_t(pend - pbegin) != keydata.size()) {
44 fValid = false;
45 } else if (Check(&pbegin[0])) {
46 memcpy(keydata.data(), (unsigned char*)&pbegin[0], keydata.size());
47 fValid = true;
48 fCompressed = fCompressedIn;
49 } else {
50 fValid = false;
51 }
52 */
53 }
54
55 /**
56 | Simple read-only vector-like interface.
57 |
58 */
59 pub fn size(&self) -> u32 {
60
61 todo!();
62 /*
63 return (fValid ? keydata.size() : 0);
64 */
65 }
66
67 pub fn begin(&self) -> *const u8 {
68
69 todo!();
70 /*
71 return keydata.data();
72 */
73 }
74
75 pub fn end(&self) -> *const u8 {
76
77 todo!();
78 /*
79 return keydata.data() + size();
80 */
81 }
82
83 /**
84 | Check whether this private key is valid.
85 |
86 */
87 pub fn is_valid(&self) -> bool {
88
89 todo!();
90 /*
91 return fValid;
92 */
93 }
94
95 /**
96 | Check whether the public key corresponding
97 | to this private key is (to be) compressed.
98 |
99 */
100 pub fn is_compressed(&self) -> bool {
101
102 todo!();
103 /*
104 return fCompressed;
105 */
106 }
107
108 /**
109 | Check whether the 32-byte array pointed
110 | to by vch is valid keydata.
111 |
112 */
113 pub fn check(&mut self, vch: *const u8) -> bool {
114
115 todo!();
116 /*
117 return secp256k1_ec_seckey_verify(secp256k1_context_sign, vch);
118 */
119 }
120
121 /**
122 | Generate a new private key using a cryptographic
123 | PRNG.
124 |
125 */
126 pub fn make_new_key(&mut self, compressed_in: bool) {
127
128 todo!();
129 /*
130 do {
131 GetStrongRandBytes(keydata.data(), keydata.size());
132 } while (!Check(keydata.data()));
133 fValid = true;
134 fCompressed = fCompressedIn;
135 */
136 }
137
138 /**
139 | Negate private key
140 |
141 */
142 pub fn negate(&mut self) -> bool {
143
144 todo!();
145 /*
146 assert(fValid);
147 return secp256k1_ec_seckey_negate(secp256k1_context_sign, keydata.data());
148 */
149 }
150
151 /**
152 | Convert the private key to a CPrivKey
153 | (serialized OpenSSL private key data).
154 |
155 | This is expensive.
156 |
157 */
158 pub fn get_priv_key(&self) -> PrivKey {
159
160 todo!();
161 /*
162 assert(fValid);
163 CPrivKey seckey;
164 int ret;
165 size_t seckeylen;
166 seckey.resize(SIZE);
167 seckeylen = SIZE;
168 ret = ec_seckey_export_der(secp256k1_context_sign, seckey.data(), &seckeylen, begin(), fCompressed);
169 assert(ret);
170 seckey.resize(seckeylen);
171 return seckey;
172 */
173 }
174
175 /**
176 | Compute the public key from a private
177 | key.
178 |
179 | This is expensive.
180 |
181 */
182 pub fn get_pub_key(&self) -> crate::PubKey {
183
184 todo!();
185 /*
186 assert(fValid);
187 secp256k1_pubkey pubkey;
188 size_t clen = CPubKey::SIZE;
189 CPubKey result;
190 int ret = secp256k1_ec_pubkey_create(secp256k1_context_sign, &pubkey, begin());
191 assert(ret);
192 secp256k1_ec_pubkey_serialize(secp256k1_context_sign, (unsigned char*)result.begin(), &clen, &pubkey, fCompressed ? SECP256K1_EC_COMPRESSED : SECP256K1_EC_UNCOMPRESSED);
193 assert(result.size() == clen);
194 assert(result.IsValid());
195 return result;
196 */
197 }
198
199 /**
200 | Create a DER-serialized signature.
201 |
202 | The test_case parameter tweaks the
203 | deterministic nonce.
204 |
205 */
206 pub fn sign(&self,
207 hash: &u256,
208 vch_sig: &mut Vec<u8>,
209 grind: Option<bool>,
210 test_case: Option<u32>) -> bool {
211
212 let grind: bool = grind.unwrap_or(true);
213 let test_case: u32 = test_case.unwrap_or(0);
214
215 todo!();
216 /*
217 if (!fValid)
218 return false;
219 vchSig.resize(CPubKey::SIGNATURE_SIZE);
220 size_t nSigLen = CPubKey::SIGNATURE_SIZE;
221 unsigned char extra_entropy[32] = {0};
222 WriteLE32(extra_entropy, test_case);
223 secp256k1_ecdsa_signature sig;
224 uint32_t counter = 0;
225 int ret = secp256k1_ecdsa_sign(secp256k1_context_sign, &sig, hash.begin(), begin(), secp256k1_nonce_function_rfc6979, (!grind && test_case) ? extra_entropy : nullptr);
226
227 // Grind for low R
228 while (ret && !SigHasLowR(&sig) && grind) {
229 WriteLE32(extra_entropy, ++counter);
230 ret = secp256k1_ecdsa_sign(secp256k1_context_sign, &sig, hash.begin(), begin(), secp256k1_nonce_function_rfc6979, extra_entropy);
231 }
232 assert(ret);
233 secp256k1_ecdsa_signature_serialize_der(secp256k1_context_sign, vchSig.data(), &nSigLen, &sig);
234 vchSig.resize(nSigLen);
235 return true;
236 */
237 }
238
239 /**
240 | Verify thoroughly whether a private
241 | key and a public key match.
242 |
243 | This is done using a different mechanism
244 | than just regenerating it.
245 |
246 */
247 pub fn verify_pub_key(&self, pubkey: &crate::PubKey) -> bool {
248
249 todo!();
250 /*
251 if (pubkey.IsCompressed() != fCompressed) {
252 return false;
253 }
254 unsigned char rnd[8];
255 std::string str = "Bitcoin key verification\n";
256 GetRandBytes(rnd, sizeof(rnd));
257 uint256 hash;
258 CHash256().Write(MakeUCharSpan(str)).Write(rnd).Finalize(hash);
259 std::vector<unsigned char> vchSig;
260 Sign(hash, vchSig);
261 return pubkey.Verify(hash, vchSig);
262 */
263 }
264
265 /**
266 | Create a compact signature (65 bytes),
267 | which allows reconstructing the used
268 | public key.
269 |
270 | The format is one header byte, followed
271 | by two times 32 bytes for the serialized
272 | r and s values.
273 |
274 | The header byte: 0x1B = first key with
275 | even y, 0x1C = first key with odd y, 0x1D
276 | = second key with even y, 0x1E = second
277 | key with odd y, add 0x04 for compressed
278 | keys.
279 |
280 */
281 pub fn sign_compact(&self,
282 hash: &u256,
283 vch_sig: &mut Vec<u8>) -> bool {
284
285 todo!();
286 /*
287 if (!fValid)
288 return false;
289 vchSig.resize(CPubKey::COMPACT_SIGNATURE_SIZE);
290 int rec = -1;
291 secp256k1_ecdsa_recoverable_signature sig;
292 int ret = secp256k1_ecdsa_sign_recoverable(secp256k1_context_sign, &sig, hash.begin(), begin(), secp256k1_nonce_function_rfc6979, nullptr);
293 assert(ret);
294 ret = secp256k1_ecdsa_recoverable_signature_serialize_compact(secp256k1_context_sign, &vchSig[1], &rec, &sig);
295 assert(ret);
296 assert(rec != -1);
297 vchSig[0] = 27 + rec + (fCompressed ? 4 : 0);
298 return true;
299 */
300 }
301
302 /**
303 | Create a BIP-340 Schnorr signature,
304 | for the xonly-pubkey corresponding
305 | to *this, optionally tweaked by *merkle_root.
306 | Additional nonce entropy can be provided
307 | through aux. merkle_root is used to
308 | optionally perform tweaking of the
309 | private key, as specified in BIP341:
310 |
311 | - If merkle_root == nullptr: no tweaking
312 | is done, sign with key directly (this
313 | is used for signatures in BIP342 script).
314 |
315 | - If merkle_root->IsNull(): sign with
316 | key + H_TapTweak(pubkey) (this is used
317 | for key path spending when no scripts
318 | are present).
319 |
320 | - Otherwise: sign with key + H_TapTweak(pubkey
321 | || *merkle_root) (this is used for key
322 | path spending, with specific
323 |
324 | Merkle root of the script tree).
325 |
326 */
327 pub fn sign_schnorr(&self,
328 hash: &u256,
329 sig: &[u8],
330 merkle_root: *const u256,
331 aux: *const u256) -> bool {
332
333 todo!();
334 /*
335 assert(sig.size() == 64);
336 secp256k1_keypair keypair;
337 if (!secp256k1_keypair_create(secp256k1_context_sign, &keypair, begin())) return false;
338 if (merkle_root) {
339 secp256k1_xonly_pubkey pubkey;
340 if (!secp256k1_keypair_xonly_pub(secp256k1_context_sign, &pubkey, nullptr, &keypair)) return false;
341 unsigned char pubkey_bytes[32];
342 if (!secp256k1_xonly_pubkey_serialize(secp256k1_context_sign, pubkey_bytes, &pubkey)) return false;
343 uint256 tweak = XOnlyPubKey(pubkey_bytes).ComputeTapTweakHash(merkle_root->IsNull() ? nullptr : merkle_root);
344 if (!secp256k1_keypair_xonly_tweak_add(GetVerifyContext(), &keypair, tweak.data())) return false;
345 }
346 bool ret = secp256k1_schnorrsig_sign(secp256k1_context_sign, sig.data(), hash.data(), &keypair, aux ? (unsigned char*)aux->data() : nullptr);
347 memory_cleanse(&keypair, sizeof(keypair));
348 return ret;
349 */
350 }
351
352 /**
353 | Load private key and check that public
354 | key matches.
355 |
356 */
357 pub fn load(&mut self,
358 seckey: &PrivKey,
359 vch_pub_key: &crate::PubKey,
360 skip_check: Option<bool>) -> bool {
361 let skip_check: bool = skip_check.unwrap_or(false);
362
363 todo!();
364 /*
365 if (!ec_seckey_import_der(secp256k1_context_sign, (unsigned char*)begin(), seckey.data(), seckey.size()))
366 return false;
367 fCompressed = vchPubKey.IsCompressed();
368 fValid = true;
369
370 if (fSkipCheck)
371 return true;
372
373 return VerifyPubKey(vchPubKey);
374 */
375 }
376
377 /**
378 | Derive BIP32 child key.
379 |
380 */
381 pub fn derive(&self,
382 key_child: &mut Key,
383 cc_child: &mut ChainCode,
384 n_child: u32,
385 cc: &ChainCode) -> bool {
386
387 todo!();
388 /*
389 assert(IsValid());
390 assert(IsCompressed());
391 std::vector<unsigned char, secure_allocator<unsigned char>> vout(64);
392 if ((nChild >> 31) == 0) {
393 CPubKey pubkey = GetPubKey();
394 assert(pubkey.size() == CPubKey::COMPRESSED_SIZE);
395 BIP32Hash(cc, nChild, *pubkey.begin(), pubkey.begin()+1, vout.data());
396 } else {
397 assert(size() == 32);
398 BIP32Hash(cc, nChild, 0, begin(), vout.data());
399 }
400 memcpy(ccChild.begin(), vout.data()+32, 32);
401 memcpy((unsigned char*)keyChild.begin(), begin(), 32);
402 bool ret = secp256k1_ec_seckey_tweak_add(secp256k1_context_sign, (unsigned char*)keyChild.begin(), vout.data());
403 keyChild.fCompressed = true;
404 keyChild.fValid = ret;
405 return ret;
406 */
407 }
408}
409
410impl Default for Key {
411
412 /**
413 Construct an invalid private key.
414 */
415 fn default() -> Self {
416 todo!();
417 /*
418 : valid(false),
419 : compressed(false),
420
421 // Important: vch must be 32 bytes in length to not break serialization
422 keydata.resize(32);
423 */
424 }
425}
426
427impl PartialEq<Key> for Key {
428
429 #[inline] fn eq(&self, other: &Key) -> bool {
430 todo!();
431 /*
432 return a.fCompressed == b.fCompressed &&
433 a.size() == b.size() &&
434 memcmp(a.keydata.data(), b.keydata.data(), a.size()) == 0;
435 */
436 }
437}
438
439impl Eq for Key {}
440