33//! Public and secret keys.
44//!
55
6- use core:: ops:: { self , BitXor } ;
6+ mod secret;
7+
8+ use core:: ops:: BitXor ;
79use core:: { fmt, ptr, str} ;
810
911#[ cfg( feature = "arbitrary" ) ]
@@ -12,115 +14,17 @@ use secp256k1_sys::secp256k1_ec_pubkey_sort;
1214#[ cfg( feature = "serde" ) ]
1315use serde:: ser:: SerializeTuple ;
1416
17+ pub use self :: secret:: SecretKey ;
1518use crate :: ellswift:: ElligatorSwift ;
1619use crate :: ffi:: types:: c_uint;
1720use crate :: ffi:: { self , CPtr } ;
18- use crate :: Error :: { self , InvalidPublicKey , InvalidPublicKeySum , InvalidSecretKey } ;
21+ use crate :: Error :: { self , InvalidPublicKey , InvalidPublicKeySum } ;
1922#[ cfg( feature = "global-context" ) ]
2023use crate :: SECP256K1 ;
2124use crate :: {
2225 constants, ecdsa, from_hex, schnorr, Message , Scalar , Secp256k1 , Signing , Verification ,
2326} ;
2427
25- /// Secret key - a 256-bit key used to create ECDSA and Taproot signatures.
26- ///
27- /// This value should be generated using a [cryptographically secure pseudorandom number generator].
28- ///
29- /// # Side channel attacks
30- ///
31- /// We have attempted to reduce the side channel attack surface by implementing a constant time `eq`
32- /// method. For similar reasons we explicitly do not implement `PartialOrd`, `Ord`, or `Hash` on
33- /// `SecretKey`. If you really want to order secret keys then you can use `AsRef` to get at the
34- /// underlying bytes and compare them - however this is almost certainly a bad idea.
35- ///
36- /// # Serde support
37- ///
38- /// Implements de/serialization with the `serde` feature enabled. We treat the byte value as a tuple
39- /// of 32 `u8`s for non-human-readable formats. This representation is optimal for some formats
40- /// (e.g. [`bincode`]) however other formats may be less optimal (e.g. [`cbor`]).
41- ///
42- /// # Examples
43- ///
44- /// Basic usage:
45- ///
46- /// ```
47- /// # #[cfg(all(feature = "rand", feature = "std"))] {
48- /// use secp256k1::{rand, Secp256k1, SecretKey};
49- ///
50- /// let secp = Secp256k1::new();
51- /// let secret_key = SecretKey::new(&mut rand::rng());
52- /// # }
53- /// ```
54- /// [`bincode`]: https://docs.rs/bincode
55- /// [`cbor`]: https://docs.rs/cbor
56- /// [cryptographically secure pseudorandom number generator]: https://en.wikipedia.org/wiki/Cryptographically_secure_pseudorandom_number_generator
57- #[ derive( Copy , Clone ) ]
58- pub struct SecretKey ( [ u8 ; constants:: SECRET_KEY_SIZE ] ) ;
59- impl_display_secret ! ( SecretKey ) ;
60- impl_non_secure_erase ! ( SecretKey , 0 , [ 1u8 ; constants:: SECRET_KEY_SIZE ] ) ;
61-
62- impl PartialEq for SecretKey {
63- /// This implementation is designed to be constant time to help prevent side channel attacks.
64- #[ inline]
65- fn eq ( & self , other : & Self ) -> bool {
66- let accum = self . 0 . iter ( ) . zip ( & other. 0 ) . fold ( 0 , |accum, ( a, b) | accum | a ^ b) ;
67- unsafe { core:: ptr:: read_volatile ( & accum) == 0 }
68- }
69- }
70-
71- impl Eq for SecretKey { }
72-
73- impl AsRef < [ u8 ; constants:: SECRET_KEY_SIZE ] > for SecretKey {
74- /// Gets a reference to the underlying array.
75- ///
76- /// # Side channel attacks
77- ///
78- /// Using ordering functions (`PartialOrd`/`Ord`) on a reference to secret keys leaks data
79- /// because the implementations are not constant time. Doing so will make your code vulnerable
80- /// to side channel attacks. [`SecretKey::eq`] is implemented using a constant time algorithm,
81- /// please consider using it to do comparisons of secret keys.
82- #[ inline]
83- fn as_ref ( & self ) -> & [ u8 ; constants:: SECRET_KEY_SIZE ] {
84- let SecretKey ( dat) = self ;
85- dat
86- }
87- }
88-
89- impl < I > ops:: Index < I > for SecretKey
90- where
91- [ u8 ] : ops:: Index < I > ,
92- {
93- type Output = <[ u8 ] as ops:: Index < I > >:: Output ;
94-
95- #[ inline]
96- fn index ( & self , index : I ) -> & Self :: Output { & self . 0 [ index] }
97- }
98-
99- impl ffi:: CPtr for SecretKey {
100- type Target = u8 ;
101-
102- fn as_c_ptr ( & self ) -> * const Self :: Target {
103- let SecretKey ( dat) = self ;
104- dat. as_ptr ( )
105- }
106-
107- fn as_mut_c_ptr ( & mut self ) -> * mut Self :: Target {
108- let & mut SecretKey ( ref mut dat) = self ;
109- dat. as_mut_ptr ( )
110- }
111- }
112-
113- impl str:: FromStr for SecretKey {
114- type Err = Error ;
115- fn from_str ( s : & str ) -> Result < SecretKey , Error > {
116- let mut res = [ 0u8 ; constants:: SECRET_KEY_SIZE ] ;
117- match from_hex ( s, & mut res) {
118- Ok ( constants:: SECRET_KEY_SIZE ) => SecretKey :: from_byte_array ( res) ,
119- _ => Err ( Error :: InvalidSecretKey ) ,
120- }
121- }
122- }
123-
12428/// Public key - used to verify ECDSA signatures and to do Taproot tweaks.
12529///
12630/// # Serde support
@@ -184,239 +88,6 @@ impl str::FromStr for PublicKey {
18488 }
18589}
18690
187- impl SecretKey {
188- /// Generates a new random secret key.
189- ///
190- /// # Examples
191- ///
192- /// ```
193- /// # #[cfg(all(feature = "std", feature = "rand"))] {
194- /// use secp256k1::{rand, SecretKey};
195- /// let secret_key = SecretKey::new(&mut rand::rng());
196- /// # }
197- /// ```
198- #[ inline]
199- #[ cfg( feature = "rand" ) ]
200- pub fn new < R : rand:: Rng + ?Sized > ( rng : & mut R ) -> SecretKey {
201- let mut data = crate :: random_32_bytes ( rng) ;
202- unsafe {
203- while ffi:: secp256k1_ec_seckey_verify (
204- ffi:: secp256k1_context_no_precomp,
205- data. as_c_ptr ( ) ,
206- ) == 0
207- {
208- data = crate :: random_32_bytes ( rng) ;
209- }
210- }
211- SecretKey ( data)
212- }
213-
214- /// Converts a 32-byte slice to a secret key.
215- ///
216- /// # Examples
217- ///
218- /// ```
219- /// use secp256k1::SecretKey;
220- /// let sk = SecretKey::from_slice(&[0xcd; 32]).expect("32 bytes, within curve order");
221- /// ```
222- #[ deprecated( since = "0.31.0" , note = "Use `from_byte_array` instead." ) ]
223- #[ inline]
224- pub fn from_slice ( data : & [ u8 ] ) -> Result < SecretKey , Error > {
225- match <[ u8 ; constants:: SECRET_KEY_SIZE ] >:: try_from ( data) {
226- Ok ( data) => Self :: from_byte_array ( data) ,
227- Err ( _) => Err ( InvalidSecretKey ) ,
228- }
229- }
230-
231- /// Converts a 32-byte array to a secret key.
232- ///
233- /// # Examples
234- ///
235- /// ```
236- /// use secp256k1::SecretKey;
237- /// let sk = SecretKey::from_byte_array([0xcd; 32]).expect("32 bytes, within curve order");
238- /// ```
239- #[ inline]
240- pub fn from_byte_array ( data : [ u8 ; constants:: SECRET_KEY_SIZE ] ) -> Result < SecretKey , Error > {
241- unsafe {
242- if ffi:: secp256k1_ec_seckey_verify ( ffi:: secp256k1_context_no_precomp, data. as_c_ptr ( ) )
243- == 0
244- {
245- return Err ( InvalidSecretKey ) ;
246- }
247- }
248- Ok ( SecretKey ( data) )
249- }
250-
251- /// Creates a new secret key using data from BIP-340 [`Keypair`].
252- ///
253- /// # Examples
254- ///
255- /// ```
256- /// # #[cfg(all(feature = "rand", feature = "std"))] {
257- /// use secp256k1::{rand, Secp256k1, SecretKey, Keypair};
258- ///
259- /// let secp = Secp256k1::new();
260- /// let keypair = Keypair::new(&secp, &mut rand::rng());
261- /// let secret_key = SecretKey::from_keypair(&keypair);
262- /// # }
263- /// ```
264- #[ inline]
265- pub fn from_keypair ( keypair : & Keypair ) -> Self {
266- let mut sk = [ 0u8 ; constants:: SECRET_KEY_SIZE ] ;
267- unsafe {
268- let ret = ffi:: secp256k1_keypair_sec (
269- ffi:: secp256k1_context_no_precomp,
270- sk. as_mut_c_ptr ( ) ,
271- keypair. as_c_ptr ( ) ,
272- ) ;
273- debug_assert_eq ! ( ret, 1 ) ;
274- }
275- SecretKey ( sk)
276- }
277-
278- /// Returns the secret key as a byte value.
279- #[ inline]
280- pub fn secret_bytes ( & self ) -> [ u8 ; constants:: SECRET_KEY_SIZE ] { self . 0 }
281-
282- /// Negates the secret key.
283- #[ inline]
284- #[ must_use = "you forgot to use the negated secret key" ]
285- pub fn negate ( mut self ) -> SecretKey {
286- unsafe {
287- let res = ffi:: secp256k1_ec_seckey_negate (
288- ffi:: secp256k1_context_no_precomp,
289- self . as_mut_c_ptr ( ) ,
290- ) ;
291- debug_assert_eq ! ( res, 1 ) ;
292- }
293- self
294- }
295-
296- /// Tweaks a [`SecretKey`] by adding `tweak` modulo the curve order.
297- ///
298- /// # Errors
299- ///
300- /// Returns an error if the resulting key would be invalid.
301- #[ inline]
302- pub fn add_tweak ( mut self , tweak : & Scalar ) -> Result < SecretKey , Error > {
303- unsafe {
304- if ffi:: secp256k1_ec_seckey_tweak_add (
305- ffi:: secp256k1_context_no_precomp,
306- self . as_mut_c_ptr ( ) ,
307- tweak. as_c_ptr ( ) ,
308- ) != 1
309- {
310- Err ( Error :: InvalidTweak )
311- } else {
312- Ok ( self )
313- }
314- }
315- }
316-
317- /// Tweaks a [`SecretKey`] by multiplying by `tweak` modulo the curve order.
318- ///
319- /// # Errors
320- ///
321- /// Returns an error if the resulting key would be invalid.
322- #[ inline]
323- pub fn mul_tweak ( mut self , tweak : & Scalar ) -> Result < SecretKey , Error > {
324- unsafe {
325- if ffi:: secp256k1_ec_seckey_tweak_mul (
326- ffi:: secp256k1_context_no_precomp,
327- self . as_mut_c_ptr ( ) ,
328- tweak. as_c_ptr ( ) ,
329- ) != 1
330- {
331- Err ( Error :: InvalidTweak )
332- } else {
333- Ok ( self )
334- }
335- }
336- }
337-
338- /// Constructs an ECDSA signature for `msg` using the global [`SECP256K1`] context.
339- #[ inline]
340- #[ cfg( feature = "global-context" ) ]
341- pub fn sign_ecdsa ( & self , msg : impl Into < Message > ) -> ecdsa:: Signature {
342- SECP256K1 . sign_ecdsa ( msg, self )
343- }
344-
345- /// Returns the [`Keypair`] for this [`SecretKey`].
346- ///
347- /// This is equivalent to using [`Keypair::from_secret_key`].
348- #[ inline]
349- pub fn keypair < C : Signing > ( & self , secp : & Secp256k1 < C > ) -> Keypair {
350- Keypair :: from_secret_key ( secp, self )
351- }
352-
353- /// Returns the [`PublicKey`] for this [`SecretKey`].
354- ///
355- /// This is equivalent to using [`PublicKey::from_secret_key`].
356- #[ inline]
357- pub fn public_key < C : Signing > ( & self , secp : & Secp256k1 < C > ) -> PublicKey {
358- PublicKey :: from_secret_key ( secp, self )
359- }
360-
361- /// Returns the [`XOnlyPublicKey`] (and its [`Parity`]) for this [`SecretKey`].
362- ///
363- /// This is equivalent to `XOnlyPublicKey::from_keypair(self.keypair(secp))`.
364- #[ inline]
365- pub fn x_only_public_key < C : Signing > ( & self , secp : & Secp256k1 < C > ) -> ( XOnlyPublicKey , Parity ) {
366- let kp = self . keypair ( secp) ;
367- XOnlyPublicKey :: from_keypair ( & kp)
368- }
369-
370- /// Constructor for unit testing.
371- #[ cfg( test) ]
372- #[ cfg( all( feature = "rand" , feature = "std" ) ) ]
373- pub fn test_random ( ) -> Self { Self :: new ( & mut rand:: rng ( ) ) }
374-
375- /// Constructor for unit testing.
376- #[ cfg( test) ]
377- #[ cfg( not( all( feature = "rand" , feature = "std" ) ) ) ]
378- pub fn test_random ( ) -> Self {
379- loop {
380- if let Ok ( ret) = Self :: from_byte_array ( crate :: test_random_32_bytes ( ) ) {
381- return ret;
382- }
383- }
384- }
385- }
386-
387- #[ cfg( feature = "serde" ) ]
388- impl serde:: Serialize for SecretKey {
389- fn serialize < S : serde:: Serializer > ( & self , s : S ) -> Result < S :: Ok , S :: Error > {
390- if s. is_human_readable ( ) {
391- let mut buf = [ 0u8 ; constants:: SECRET_KEY_SIZE * 2 ] ;
392- s. serialize_str ( crate :: to_hex ( & self . 0 , & mut buf) . expect ( "fixed-size hex serialization" ) )
393- } else {
394- let mut tuple = s. serialize_tuple ( constants:: SECRET_KEY_SIZE ) ?;
395- for byte in self . 0 . iter ( ) {
396- tuple. serialize_element ( byte) ?;
397- }
398- tuple. end ( )
399- }
400- }
401- }
402-
403- #[ cfg( feature = "serde" ) ]
404- impl < ' de > serde:: Deserialize < ' de > for SecretKey {
405- fn deserialize < D : serde:: Deserializer < ' de > > ( d : D ) -> Result < Self , D :: Error > {
406- if d. is_human_readable ( ) {
407- d. deserialize_str ( super :: serde_util:: FromStrVisitor :: new (
408- "a hex string representing 32 byte SecretKey" ,
409- ) )
410- } else {
411- let visitor = super :: serde_util:: Tuple32Visitor :: new (
412- "raw 32 bytes SecretKey" ,
413- SecretKey :: from_byte_array,
414- ) ;
415- d. deserialize_tuple ( constants:: SECRET_KEY_SIZE , visitor)
416- }
417- }
418- }
419-
42091impl PublicKey {
42192 /// Obtains a raw const pointer suitable for use with FFI functions.
42293 #[ inline]
0 commit comments