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