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