Skip to content

Commit 9b66c2a

Browse files
committed
feat: KeyPair::from_seckey_byte_array
Construct KeyPair directly from [u8; 32]. Deprecate KeyPair::from_seckey_slice and replace all of its calls with the new method.
1 parent b991ef2 commit 9b66c2a

File tree

3 files changed

+27
-15
lines changed

3 files changed

+27
-15
lines changed

src/key.rs

+23-11
Original file line numberDiff line numberDiff line change
@@ -859,16 +859,29 @@ impl Keypair {
859859
/// # Errors
860860
///
861861
/// [`Error::InvalidSecretKey`] if the slice is not exactly 32 bytes long,
862-
/// or if the encoded number exceeds the Secp256k1 field `p` value.
862+
/// or if the encoded number is an invalid scalar.
863+
#[deprecated(since = "TBD", note = "Use `from_seckey_byte_array` instead.")]
863864
#[inline]
864865
pub fn from_seckey_slice<C: Signing>(
865866
secp: &Secp256k1<C>,
866867
data: &[u8],
867868
) -> Result<Keypair, Error> {
868-
if data.is_empty() || data.len() != constants::SECRET_KEY_SIZE {
869-
return Err(Error::InvalidSecretKey);
869+
match <[u8; constants::SECRET_KEY_SIZE]>::try_from(data) {
870+
Ok(data) => Self::from_seckey_byte_array(secp, data),
871+
Err(_) => Err(Error::InvalidSecretKey),
870872
}
873+
}
871874

875+
/// Creates a [`Keypair`] directly from a secret key byte array.
876+
///
877+
/// # Errors
878+
///
879+
/// [`Error::InvalidSecretKey`] if the encoded number is an invalid scalar.
880+
#[inline]
881+
pub fn from_seckey_byte_array<C: Signing>(
882+
secp: &Secp256k1<C>,
883+
data: [u8; constants::SECRET_KEY_SIZE],
884+
) -> Result<Keypair, Error> {
872885
unsafe {
873886
let mut kp = ffi::Keypair::new();
874887
if ffi::secp256k1_keypair_create(secp.ctx.as_ptr(), &mut kp, data.as_c_ptr()) == 1 {
@@ -884,13 +897,12 @@ impl Keypair {
884897
/// # Errors
885898
///
886899
/// [`Error::InvalidSecretKey`] if the string does not consist of exactly 64 hex characters,
887-
/// or if the encoded number exceeds the Secp256k1 field `p` value.
900+
/// or if the encoded number is an invalid scalar.
888901
#[inline]
889902
pub fn from_seckey_str<C: Signing>(secp: &Secp256k1<C>, s: &str) -> Result<Keypair, Error> {
890903
let mut res = [0u8; constants::SECRET_KEY_SIZE];
891904
match from_hex(s, &mut res) {
892-
Ok(constants::SECRET_KEY_SIZE) =>
893-
Keypair::from_seckey_slice(secp, &res[0..constants::SECRET_KEY_SIZE]),
905+
Ok(constants::SECRET_KEY_SIZE) => Keypair::from_seckey_byte_array(secp, res),
894906
_ => Err(Error::InvalidSecretKey),
895907
}
896908
}
@@ -900,7 +912,7 @@ impl Keypair {
900912
/// # Errors
901913
///
902914
/// [`Error::InvalidSecretKey`] if the string does not consist of exactly 64 hex characters,
903-
/// or if the encoded number exceeds the Secp256k1 field `p` value.
915+
/// or if the encoded number is an invalid scalar.
904916
#[inline]
905917
#[cfg(feature = "global-context")]
906918
pub fn from_seckey_str_global(s: &str) -> Result<Keypair, Error> {
@@ -1117,7 +1129,7 @@ impl<'de> serde::Deserialize<'de> for Keypair {
11171129
let ctx = Secp256k1::signing_only();
11181130

11191131
#[allow(clippy::needless_borrow)]
1120-
Keypair::from_seckey_slice(&ctx, &data)
1132+
Keypair::from_seckey_byte_array(&ctx, data)
11211133
});
11221134
d.deserialize_tuple(constants::SECRET_KEY_SIZE, visitor)
11231135
}
@@ -1665,7 +1677,7 @@ mod test {
16651677
#[cfg(all(feature = "std", not(secp256k1_fuzz)))]
16661678
fn erased_keypair_is_valid() {
16671679
let s = Secp256k1::new();
1668-
let kp = Keypair::from_seckey_slice(&s, &[1u8; constants::SECRET_KEY_SIZE])
1680+
let kp = Keypair::from_seckey_byte_array(&s, [1u8; constants::SECRET_KEY_SIZE])
16691681
.expect("valid secret key");
16701682
let mut kp2 = kp;
16711683
kp2.non_secure_erase();
@@ -2272,7 +2284,7 @@ mod test {
22722284
];
22732285
static SK_STR: &str = "01010101010101010001020304050607ffff0000ffff00006363636363636363";
22742286

2275-
let sk = Keypair::from_seckey_slice(SECP256K1, &SK_BYTES).unwrap();
2287+
let sk = Keypair::from_seckey_byte_array(SECP256K1, SK_BYTES).unwrap();
22762288
#[rustfmt::skip]
22772289
assert_tokens(&sk.compact(), &[
22782290
Token::Tuple{ len: 32 },
@@ -2452,7 +2464,7 @@ mod test {
24522464

24532465
static PK_STR: &str = "18845781f631c48f1c9709e23092067d06837f30aa0cd0544ac887fe91ddd166";
24542466

2455-
let kp = Keypair::from_seckey_slice(crate::SECP256K1, &SK_BYTES).unwrap();
2467+
let kp = Keypair::from_seckey_byte_array(crate::SECP256K1, SK_BYTES).unwrap();
24562468
let (pk, _parity) = XOnlyPublicKey::from_keypair(&kp);
24572469

24582470
#[rustfmt::skip]

src/schnorr.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -393,7 +393,7 @@ mod tests {
393393
0x63, 0x63, 0x63, 0x63,
394394
];
395395

396-
let kp = Keypair::from_seckey_slice(&secp, &SK_BYTES).expect("sk");
396+
let kp = Keypair::from_seckey_byte_array(&secp, SK_BYTES).expect("sk");
397397

398398
// In fuzzing mode secret->public key derivation is different, so
399399
// hard-code the expected result.
@@ -473,7 +473,7 @@ mod tests {
473473
let s = Secp256k1::new();
474474

475475
let msg = [1; 32];
476-
let keypair = Keypair::from_seckey_slice(&s, &[2; 32]).unwrap();
476+
let keypair = Keypair::from_seckey_byte_array(&s, [2; 32]).unwrap();
477477
let aux = [3u8; 32];
478478
let sig = s.sign_schnorr_with_aux_rand(&msg, &keypair, &aux);
479479
static SIG_BYTES: [u8; constants::SCHNORR_SIGNATURE_SIZE] = [
@@ -706,7 +706,7 @@ mod tests {
706706
} in vectors
707707
{
708708
if let (Some(secret_key), Some(aux_rand)) = (secret_key, aux_rand) {
709-
let keypair = Keypair::from_seckey_slice(&secp, &secret_key).unwrap();
709+
let keypair = Keypair::from_seckey_byte_array(&secp, secret_key).unwrap();
710710
assert_eq!(keypair.x_only_public_key().0.serialize(), public_key);
711711
let sig = secp.sign_schnorr_with_aux_rand(&message, &keypair, &aux_rand);
712712
assert_eq!(sig.to_byte_array(), signature);

tests/serde.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ fn bincode_public_key() {
6161
#[cfg(feature = "global-context")]
6262
fn bincode_keypair() {
6363
let secp = Secp256k1::new();
64-
let kp = Keypair::from_seckey_slice(&secp, &SK_BYTES).expect("failed to create keypair");
64+
let kp = Keypair::from_seckey_byte_array(&secp, SK_BYTES).expect("failed to create keypair");
6565
let ser = bincode::serialize(&kp).unwrap();
6666

6767
assert_eq!(ser, SK_BYTES);

0 commit comments

Comments
 (0)