Skip to content

Commit 1661f57

Browse files
committed
Add from_byte_array functions
Functions have been added to PrivateKey, PublicKey and XOnlyPublicKey to allow the creation of a key directly from a byte array.
1 parent 18654c3 commit 1661f57

File tree

1 file changed

+72
-18
lines changed

1 file changed

+72
-18
lines changed

src/key.rs

Lines changed: 72 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -203,7 +203,7 @@ impl SecretKey {
203203
SecretKey(data)
204204
}
205205

206-
/// Converts a `SECRET_KEY_SIZE`-byte slice to a secret key.
206+
/// Converts a 32-byte slice to a secret key.
207207
///
208208
/// # Examples
209209
///
@@ -214,22 +214,31 @@ impl SecretKey {
214214
#[inline]
215215
pub fn from_slice(data: &[u8]) -> Result<SecretKey, Error> {
216216
match <[u8; constants::SECRET_KEY_SIZE]>::try_from(data) {
217-
Ok(data) => {
218-
unsafe {
219-
if ffi::secp256k1_ec_seckey_verify(
220-
ffi::secp256k1_context_no_precomp,
221-
data.as_c_ptr(),
222-
) == 0
223-
{
224-
return Err(InvalidSecretKey);
225-
}
226-
}
227-
Ok(SecretKey(data))
228-
}
217+
Ok(data) => Self::from_byte_array(&data),
229218
Err(_) => Err(InvalidSecretKey),
230219
}
231220
}
232221

222+
/// Converts a 32-byte array to a secret key.
223+
///
224+
/// # Examples
225+
///
226+
/// ```
227+
/// use secp256k1::SecretKey;
228+
/// let sk = SecretKey::from_byte_array(&[0xcd; 32]).expect("32 bytes, within curve order");
229+
/// ```
230+
#[inline]
231+
pub fn from_byte_array(data: &[u8; constants::SECRET_KEY_SIZE]) -> Result<SecretKey, Error> {
232+
unsafe {
233+
if ffi::secp256k1_ec_seckey_verify(ffi::secp256k1_context_no_precomp, data.as_c_ptr())
234+
== 0
235+
{
236+
return Err(InvalidSecretKey);
237+
}
238+
}
239+
Ok(SecretKey(*data))
240+
}
241+
233242
/// Creates a new secret key using data from BIP-340 [`Keypair`].
234243
///
235244
/// # Examples
@@ -442,17 +451,50 @@ impl PublicKey {
442451
/// Creates a public key directly from a slice.
443452
#[inline]
444453
pub fn from_slice(data: &[u8]) -> Result<PublicKey, Error> {
445-
if data.is_empty() {
446-
return Err(Error::InvalidPublicKey);
454+
match data.len() {
455+
constants::PUBLIC_KEY_SIZE => PublicKey::from_byte_array_compressed(
456+
&<[u8; constants::PUBLIC_KEY_SIZE]>::try_from(data).unwrap(),
457+
),
458+
constants::UNCOMPRESSED_PUBLIC_KEY_SIZE => PublicKey::from_byte_array_uncompressed(
459+
&<[u8; constants::UNCOMPRESSED_PUBLIC_KEY_SIZE]>::try_from(data).unwrap(),
460+
),
461+
_ => Err(InvalidPublicKey),
462+
}
463+
}
464+
465+
/// Creates a public key from a serialized array in compressed format.
466+
#[inline]
467+
pub fn from_byte_array_compressed(
468+
data: &[u8; constants::PUBLIC_KEY_SIZE],
469+
) -> Result<PublicKey, Error> {
470+
unsafe {
471+
let mut pk = ffi::PublicKey::new();
472+
if ffi::secp256k1_ec_pubkey_parse(
473+
ffi::secp256k1_context_no_precomp,
474+
&mut pk,
475+
data.as_c_ptr(),
476+
constants::PUBLIC_KEY_SIZE,
477+
) == 1
478+
{
479+
Ok(PublicKey(pk))
480+
} else {
481+
Err(InvalidPublicKey)
482+
}
447483
}
484+
}
448485

486+
/// Creates a public key from a serialized array in uncompressed format.
487+
#[inline]
488+
pub fn from_byte_array_uncompressed(
489+
data: &[u8; constants::UNCOMPRESSED_PUBLIC_KEY_SIZE],
490+
) -> Result<PublicKey, Error> {
449491
unsafe {
450492
let mut pk = ffi::PublicKey::new();
451493
if ffi::secp256k1_ec_pubkey_parse(
452494
ffi::secp256k1_context_no_precomp,
453495
&mut pk,
454496
data.as_c_ptr(),
455-
data.len(),
497+
constants::UNCOMPRESSED_PUBLIC_KEY_SIZE,
456498
) == 1
457499
{
458500
Ok(PublicKey(pk))
@@ -1163,10 +1205,22 @@ impl XOnlyPublicKey {
11631205
/// slice does not represent a valid Secp256k1 point x coordinate.
11641206
#[inline]
11651207
pub fn from_slice(data: &[u8]) -> Result<XOnlyPublicKey, Error> {
1166-
if data.is_empty() || data.len() != constants::SCHNORR_PUBLIC_KEY_SIZE {
1167-
return Err(Error::InvalidPublicKey);
1208+
match <[u8; constants::SCHNORR_PUBLIC_KEY_SIZE]>::try_from(data) {
1209+
Ok(data) => Self::from_byte_array(&data),
1210+
Err(_) => Err(InvalidPublicKey),
11681211
}
1212+
}
11691213

1214+
/// Creates a schnorr public key directly from a byte array.
1215+
///
1216+
/// # Errors
1217+
///
1218+
/// Returns [`Error::InvalidPublicKey`] if the array does not represent a valid Secp256k1 point
1219+
/// x coordinate.
1220+
#[inline]
1221+
pub fn from_byte_array(
1222+
data: &[u8; constants::SCHNORR_PUBLIC_KEY_SIZE],
1223+
) -> Result<XOnlyPublicKey, Error> {
11701224
unsafe {
11711225
let mut pk = ffi::XOnlyPublicKey::new();
11721226
if ffi::secp256k1_xonly_pubkey_parse(

0 commit comments

Comments
 (0)