secp256k1/key/
secret.rs

1// SPDX-License-Identifier: CC0-1.0
2//! Secret signing keys.
3
4use core::{ops, str};
5
6#[cfg(feature = "serde")]
7use serde::ser::SerializeTuple;
8
9use crate::ffi::CPtr as _;
10use crate::{
11    constants, ecdsa, ffi, from_hex, Error, Keypair, Message, Parity, PublicKey, Scalar,
12    XOnlyPublicKey,
13};
14
15mod encapsulate {
16    use crate::constants::SECRET_KEY_SIZE;
17    use crate::ffi::{self, CPtr};
18    use crate::Error;
19
20    /// Secret key - a 256-bit key used to create ECDSA and Taproot signatures.
21    ///
22    /// This value should be generated using a [cryptographically secure pseudorandom number generator].
23    ///
24    /// # Side channel attacks
25    ///
26    /// We have attempted to reduce the side channel attack surface by implementing a constant time `eq`
27    /// method. For similar reasons we explicitly do not implement `PartialOrd`, `Ord`, or `Hash` on
28    /// `SecretKey`. If you really want to order secret keys then you can use `AsRef` to get at the
29    /// underlying bytes and compare them - however this is almost certainly a bad idea.
30    ///
31    /// # Serde support
32    ///
33    /// Implements de/serialization with the `serde` feature enabled. We treat the byte value as a tuple
34    /// of 32 `u8`s for non-human-readable formats. This representation is optimal for some formats
35    /// (e.g. [`bincode`]) however other formats may be less optimal (e.g. [`cbor`]).
36    ///
37    /// # Examples
38    ///
39    /// Basic usage:
40    ///
41    /// ```
42    /// # #[cfg(all(feature = "rand", feature = "std"))] {
43    /// use secp256k1::{rand, SecretKey};
44    ///
45    /// let secret_key = SecretKey::new(&mut rand::rng());
46    /// # }
47    /// ```
48    /// [`bincode`]: https://docs.rs/bincode
49    /// [`cbor`]: https://docs.rs/cbor
50    /// [cryptographically secure pseudorandom number generator]: https://en.wikipedia.org/wiki/Cryptographically_secure_pseudorandom_number_generator
51    #[derive(Copy, Clone)]
52    pub struct SecretKey([u8; SECRET_KEY_SIZE]);
53    // FIXME these two macro call should be moved outside of the encapsulate module
54    impl_display_secret!(SecretKey);
55    impl_non_secure_erase!(SecretKey, 0, [1u8; SECRET_KEY_SIZE]);
56
57    impl SecretKey {
58        /// Returns the secret key as a byte value.
59        ///
60        /// # Side channel attacks
61        ///
62        /// Using ordering functions (`PartialOrd`/`Ord`) on a reference to secret keys leaks data
63        /// because the implementations are not constant time. Doing so will make your code vulnerable
64        /// to side channel attacks. [`SecretKey::eq`] is implemented using a constant time algorithm,
65        /// please consider using it to do comparisons of secret keys.
66        #[inline]
67        pub fn to_secret_bytes(&self) -> [u8; SECRET_KEY_SIZE] { self.0 }
68
69        /// Returns a reference to the secret key as a byte array.
70        ///
71        /// See note on [`Self::to_secret_bytes`].
72        #[inline]
73        pub fn as_secret_bytes(&self) -> &[u8; SECRET_KEY_SIZE] { &self.0 }
74
75        /// Converts a 32-byte array to a secret key.
76        ///
77        /// See note on [`Self::to_secret_bytes`].
78        ///
79        /// # Errors
80        ///
81        /// Returns an error when the secret key is invalid: when it is all-zeros or would exceed
82        /// the curve order when interpreted as a big-endian unsigned integer.
83        ///
84        /// # Examples
85        ///
86        /// ```
87        /// use secp256k1::SecretKey;
88        /// let sk = SecretKey::from_byte_array([0xcd; 32]).expect("32 bytes, within curve order");
89        /// ```
90        #[inline]
91        pub fn from_secret_bytes(data: [u8; SECRET_KEY_SIZE]) -> Result<SecretKey, Error> {
92            crate::with_raw_global_context(
93                |ctx| unsafe {
94                    if ffi::secp256k1_ec_seckey_verify(ctx.as_ptr(), data.as_c_ptr()) == 0 {
95                        return Err(Error::InvalidSecretKey);
96                    }
97                    Ok(SecretKey(data))
98                },
99                None,
100            )
101        }
102    }
103
104    // Must be inside the `encapsulate` module since there is no way to obtain mutable
105    // access to the internal array outside of the module.
106    impl CPtr for SecretKey {
107        type Target = u8;
108
109        fn as_c_ptr(&self) -> *const Self::Target { self.as_secret_bytes().as_ptr() }
110
111        fn as_mut_c_ptr(&mut self) -> *mut Self::Target { self.0.as_mut_ptr() }
112    }
113}
114pub use encapsulate::SecretKey;
115
116impl PartialEq for SecretKey {
117    /// This implementation is designed to be constant time to help prevent side channel attacks.
118    #[inline]
119    fn eq(&self, other: &Self) -> bool {
120        let accum = self
121            .as_secret_bytes()
122            .iter()
123            .zip(other.as_secret_bytes())
124            .fold(0, |accum, (a, b)| accum | a ^ b);
125        unsafe { core::ptr::read_volatile(&accum) == 0 }
126    }
127}
128
129impl Eq for SecretKey {}
130
131impl AsRef<[u8; constants::SECRET_KEY_SIZE]> for SecretKey {
132    /// Gets a reference to the underlying array.
133    ///
134    /// See note on [`Self::to_secret_bytes`].
135    #[inline]
136    fn as_ref(&self) -> &[u8; constants::SECRET_KEY_SIZE] { self.as_secret_bytes() }
137}
138
139impl<I> ops::Index<I> for SecretKey
140where
141    [u8]: ops::Index<I>,
142{
143    type Output = <[u8] as ops::Index<I>>::Output;
144
145    #[inline]
146    fn index(&self, index: I) -> &Self::Output { &self.as_secret_bytes()[index] }
147}
148
149impl str::FromStr for SecretKey {
150    type Err = Error;
151    fn from_str(s: &str) -> Result<Self, Self::Err> {
152        let mut res = [0u8; constants::SECRET_KEY_SIZE];
153        match from_hex(s, &mut res) {
154            Ok(constants::SECRET_KEY_SIZE) => SecretKey::from_secret_bytes(res),
155            _ => Err(Error::InvalidSecretKey),
156        }
157    }
158}
159
160impl SecretKey {
161    /// Generates a new random secret key.
162    ///
163    /// # Examples
164    ///
165    /// ```
166    /// # #[cfg(all(feature = "std", feature =  "rand"))] {
167    /// use secp256k1::{rand, SecretKey};
168    /// let secret_key = SecretKey::new(&mut rand::rng());
169    /// # }
170    /// ```
171    #[inline]
172    #[cfg(feature = "rand")]
173    pub fn new<R: rand::Rng + ?Sized>(rng: &mut R) -> Self {
174        loop {
175            let data = crate::random_32_bytes(rng);
176            if let Ok(key) = Self::from_secret_bytes(data) {
177                return key;
178            }
179        }
180    }
181
182    /// Converts a 32-byte array to a secret key.
183    #[deprecated(since = "0.32.0", note = "use from_secret_bytes instead")]
184    pub fn from_byte_array(data: [u8; constants::SECRET_KEY_SIZE]) -> Result<SecretKey, Error> {
185        Self::from_secret_bytes(data)
186    }
187
188    /// Creates a new secret key using data from BIP-340 [`Keypair`].
189    ///
190    /// # Examples
191    ///
192    /// ```
193    /// # #[cfg(all(feature = "rand", feature = "std"))] {
194    /// use secp256k1::{rand, SecretKey, Keypair};
195    ///
196    /// let keypair = Keypair::new(&mut rand::rng());
197    /// let secret_key = SecretKey::from_keypair(&keypair);
198    /// # }
199    /// ```
200    #[inline]
201    pub fn from_keypair(keypair: &Keypair) -> Self {
202        let mut sk = [0u8; constants::SECRET_KEY_SIZE];
203        unsafe {
204            let ret = ffi::secp256k1_keypair_sec(
205                ffi::secp256k1_context_no_precomp,
206                sk.as_mut_c_ptr(),
207                keypair.as_c_ptr(),
208            );
209            debug_assert_eq!(ret, 1);
210        }
211        Self::from_secret_bytes(sk).expect("a valid Keypair has a valid SecretKey")
212    }
213
214    /// Returns the secret key as a byte value.
215    #[inline]
216    #[deprecated(since = "0.32.0", note = "use to_secret_bytes instead")]
217    pub fn secret_bytes(&self) -> [u8; constants::SECRET_KEY_SIZE] { self.to_secret_bytes() }
218
219    /// Negates the secret key.
220    #[inline]
221    #[must_use = "you forgot to use the negated secret key"]
222    pub fn negate(mut self) -> SecretKey {
223        unsafe {
224            let res = ffi::secp256k1_ec_seckey_negate(
225                ffi::secp256k1_context_no_precomp,
226                self.as_mut_c_ptr(),
227            );
228            debug_assert_eq!(res, 1);
229        }
230        self
231    }
232
233    /// Tweaks a [`SecretKey`] by adding `tweak` modulo the curve order.
234    ///
235    /// # Errors
236    ///
237    /// Returns an error if the resulting key would be invalid.
238    #[inline]
239    pub fn add_tweak(mut self, tweak: &Scalar) -> Result<SecretKey, Error> {
240        unsafe {
241            if ffi::secp256k1_ec_seckey_tweak_add(
242                ffi::secp256k1_context_no_precomp,
243                self.as_mut_c_ptr(),
244                tweak.as_c_ptr(),
245            ) != 1
246            {
247                Err(Error::InvalidTweak)
248            } else {
249                Ok(self)
250            }
251        }
252    }
253
254    /// Tweaks a [`SecretKey`] by multiplying by `tweak` modulo the curve order.
255    ///
256    /// # Errors
257    ///
258    /// Returns an error if the resulting key would be invalid.
259    #[inline]
260    pub fn mul_tweak(mut self, tweak: &Scalar) -> Result<SecretKey, Error> {
261        unsafe {
262            if ffi::secp256k1_ec_seckey_tweak_mul(
263                ffi::secp256k1_context_no_precomp,
264                self.as_mut_c_ptr(),
265                tweak.as_c_ptr(),
266            ) != 1
267            {
268                Err(Error::InvalidTweak)
269            } else {
270                Ok(self)
271            }
272        }
273    }
274
275    /// Constructs an ECDSA signature for `msg`.
276    #[inline]
277    pub fn sign_ecdsa(&self, msg: impl Into<Message>) -> ecdsa::Signature { ecdsa::sign(msg, self) }
278
279    /// Returns the [`Keypair`] for this [`SecretKey`].
280    ///
281    /// This is equivalent to using [`Keypair::from_secret_key`].
282    #[inline]
283    pub fn keypair(&self) -> Keypair { Keypair::from_secret_key(self) }
284
285    /// Returns the [`PublicKey`] for this [`SecretKey`].
286    ///
287    /// This is equivalent to using [`PublicKey::from_secret_key`].
288    #[inline]
289    pub fn public_key(&self) -> PublicKey { PublicKey::from_secret_key(self) }
290
291    /// Returns the [`XOnlyPublicKey`] (and its [`Parity`]) for this [`SecretKey`].
292    ///
293    /// This is equivalent to `XOnlyPublicKey::from_keypair(self.keypair(secp))`.
294    #[inline]
295    pub fn x_only_public_key(&self) -> (XOnlyPublicKey, Parity) {
296        let kp = self.keypair();
297        XOnlyPublicKey::from_keypair(&kp)
298    }
299
300    /// Constructor for unit testing.
301    #[cfg(test)]
302    #[cfg(all(feature = "rand", feature = "std"))]
303    pub fn test_random() -> Self { Self::new(&mut rand::rng()) }
304
305    /// Constructor for unit testing.
306    #[cfg(test)]
307    #[cfg(not(all(feature = "rand", feature = "std")))]
308    pub fn test_random() -> Self {
309        loop {
310            if let Ok(ret) = Self::from_secret_bytes(crate::test_random_32_bytes()) {
311                return ret;
312            }
313        }
314    }
315}
316
317#[cfg(feature = "serde")]
318impl serde::Serialize for SecretKey {
319    fn serialize<S: serde::Serializer>(&self, s: S) -> Result<S::Ok, S::Error> {
320        if s.is_human_readable() {
321            let mut buf = [0u8; constants::SECRET_KEY_SIZE * 2];
322            s.serialize_str(
323                crate::to_hex(self.as_secret_bytes(), &mut buf)
324                    .expect("fixed-size hex serialization"),
325            )
326        } else {
327            let mut tuple = s.serialize_tuple(constants::SECRET_KEY_SIZE)?;
328            for byte in self.as_secret_bytes().iter() {
329                tuple.serialize_element(byte)?;
330            }
331            tuple.end()
332        }
333    }
334}
335
336#[cfg(feature = "serde")]
337impl<'de> serde::Deserialize<'de> for SecretKey {
338    fn deserialize<D: serde::Deserializer<'de>>(d: D) -> Result<Self, D::Error> {
339        if d.is_human_readable() {
340            d.deserialize_str(crate::serde_util::FromStrVisitor::new(
341                "a hex string representing 32 byte SecretKey",
342            ))
343        } else {
344            let visitor =
345                crate::serde_util::Tuple32Visitor::new("raw 32 bytes SecretKey", |bytes| {
346                    SecretKey::from_secret_bytes(bytes)
347                });
348            d.deserialize_tuple(constants::SECRET_KEY_SIZE, visitor)
349        }
350    }
351}