Creating SecretKey and PublicKey from BIP-340 KeyPair
This commit is contained in:
parent
4652ab6116
commit
aa6bdaff3c
|
@ -518,6 +518,20 @@ extern "C" {
|
||||||
internal_pubkey: *const XOnlyPublicKey,
|
internal_pubkey: *const XOnlyPublicKey,
|
||||||
tweak32: *const c_uchar,
|
tweak32: *const c_uchar,
|
||||||
) -> c_int;
|
) -> c_int;
|
||||||
|
|
||||||
|
#[cfg_attr(not(rust_secp_no_symbol_renaming), link_name = "rustsecp256k1_v0_4_1_keypair_sec")]
|
||||||
|
pub fn secp256k1_keypair_sec(
|
||||||
|
cx: *const Context,
|
||||||
|
output_seckey: *mut c_uchar,
|
||||||
|
keypair: *const KeyPair
|
||||||
|
) -> c_int;
|
||||||
|
|
||||||
|
#[cfg_attr(not(rust_secp_no_symbol_renaming), link_name = "rustsecp256k1_v0_4_1_keypair_pub")]
|
||||||
|
pub fn secp256k1_keypair_pub(
|
||||||
|
cx: *const Context,
|
||||||
|
output_pubkey: *mut PublicKey,
|
||||||
|
keypair: *const KeyPair
|
||||||
|
) -> c_int;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A reimplementation of the C function `secp256k1_context_create` in rust.
|
/// A reimplementation of the C function `secp256k1_context_create` in rust.
|
||||||
|
|
|
@ -27,7 +27,7 @@ use constants;
|
||||||
use ffi::{self, CPtr};
|
use ffi::{self, CPtr};
|
||||||
|
|
||||||
/// Secret 256-bit key used as `x` in an ECDSA signature
|
/// Secret 256-bit key used as `x` in an ECDSA signature
|
||||||
pub struct SecretKey([u8; constants::SECRET_KEY_SIZE]);
|
pub struct SecretKey(pub(crate) [u8; constants::SECRET_KEY_SIZE]);
|
||||||
impl_array_newtype!(SecretKey, u8, constants::SECRET_KEY_SIZE);
|
impl_array_newtype!(SecretKey, u8, constants::SECRET_KEY_SIZE);
|
||||||
impl_pretty_debug!(SecretKey);
|
impl_pretty_debug!(SecretKey);
|
||||||
|
|
||||||
|
@ -66,7 +66,7 @@ pub const ONE_KEY: SecretKey = SecretKey([0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
/// A Secp256k1 public key, used for verification of signatures
|
/// A Secp256k1 public key, used for verification of signatures
|
||||||
#[derive(Copy, Clone, PartialEq, Eq, Debug, Hash)]
|
#[derive(Copy, Clone, PartialEq, Eq, Debug, Hash)]
|
||||||
#[repr(transparent)]
|
#[repr(transparent)]
|
||||||
pub struct PublicKey(ffi::PublicKey);
|
pub struct PublicKey(pub(crate) ffi::PublicKey);
|
||||||
|
|
||||||
impl fmt::LowerHex for PublicKey {
|
impl fmt::LowerHex for PublicKey {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
|
|
@ -13,6 +13,7 @@ use core::{fmt, ptr, str};
|
||||||
use ffi::{self, CPtr};
|
use ffi::{self, CPtr};
|
||||||
use {constants, Secp256k1};
|
use {constants, Secp256k1};
|
||||||
use {Message, Signing, Verification};
|
use {Message, Signing, Verification};
|
||||||
|
use SecretKey;
|
||||||
|
|
||||||
/// Represents a Schnorr signature.
|
/// Represents a Schnorr signature.
|
||||||
pub struct Signature([u8; constants::SCHNORRSIG_SIGNATURE_SIZE]);
|
pub struct Signature([u8; constants::SCHNORRSIG_SIGNATURE_SIZE]);
|
||||||
|
@ -449,6 +450,38 @@ impl<'de> ::serde::Deserialize<'de> for PublicKey {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl SecretKey {
|
||||||
|
/// Creates a new secret key using data from BIP-340 [`KeyPair`]
|
||||||
|
pub fn from_keypair<V: Verification>(secp: &Secp256k1<V>, keypair: &KeyPair) -> Self {
|
||||||
|
let mut sk = [0; constants::SECRET_KEY_SIZE];
|
||||||
|
unsafe {
|
||||||
|
let ret = ffi::secp256k1_keypair_sec(
|
||||||
|
secp.ctx,
|
||||||
|
sk.as_mut_c_ptr(),
|
||||||
|
keypair.as_ptr()
|
||||||
|
);
|
||||||
|
debug_assert_eq!(ret, 1);
|
||||||
|
}
|
||||||
|
SecretKey(sk)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ::key::PublicKey {
|
||||||
|
/// Creates a new compressed public key key using data from BIP-340 [`KeyPair`]
|
||||||
|
pub fn from_keypair<C: Signing>(secp: &Secp256k1<C>, keypair: &KeyPair) -> Self {
|
||||||
|
unsafe {
|
||||||
|
let mut pk = ffi::PublicKey::new();
|
||||||
|
let ret = ffi::secp256k1_keypair_pub(
|
||||||
|
secp.ctx,
|
||||||
|
&mut pk,
|
||||||
|
keypair.as_ptr()
|
||||||
|
);
|
||||||
|
debug_assert_eq!(ret, 1);
|
||||||
|
::key::PublicKey(pk)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<C: Signing> Secp256k1<C> {
|
impl<C: Signing> Secp256k1<C> {
|
||||||
fn schnorrsig_sign_helper(
|
fn schnorrsig_sign_helper(
|
||||||
&self,
|
&self,
|
||||||
|
@ -573,6 +606,7 @@ mod tests {
|
||||||
|
|
||||||
#[cfg(target_arch = "wasm32")]
|
#[cfg(target_arch = "wasm32")]
|
||||||
use wasm_bindgen_test::wasm_bindgen_test as test;
|
use wasm_bindgen_test::wasm_bindgen_test as test;
|
||||||
|
use SecretKey;
|
||||||
|
|
||||||
macro_rules! hex_32 {
|
macro_rules! hex_32 {
|
||||||
($hex:expr) => {{
|
($hex:expr) => {{
|
||||||
|
@ -669,7 +703,7 @@ mod tests {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn pubkey_from_slice() {
|
fn test_pubkey_from_slice() {
|
||||||
assert_eq!(PublicKey::from_slice(&[]), Err(InvalidPublicKey));
|
assert_eq!(PublicKey::from_slice(&[]), Err(InvalidPublicKey));
|
||||||
assert_eq!(PublicKey::from_slice(&[1, 2, 3]), Err(InvalidPublicKey));
|
assert_eq!(PublicKey::from_slice(&[1, 2, 3]), Err(InvalidPublicKey));
|
||||||
let pk = PublicKey::from_slice(&[
|
let pk = PublicKey::from_slice(&[
|
||||||
|
@ -681,7 +715,7 @@ mod tests {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn pubkey_serialize_roundtrip() {
|
fn test_pubkey_serialize_roundtrip() {
|
||||||
let secp = Secp256k1::new();
|
let secp = Secp256k1::new();
|
||||||
let (_, pubkey) = secp.generate_schnorrsig_keypair(&mut thread_rng());
|
let (_, pubkey) = secp.generate_schnorrsig_keypair(&mut thread_rng());
|
||||||
let ser = pubkey.serialize();
|
let ser = pubkey.serialize();
|
||||||
|
@ -689,6 +723,19 @@ mod tests {
|
||||||
assert_eq!(pubkey, pubkey2);
|
assert_eq!(pubkey, pubkey2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_xonly_key_extraction() {
|
||||||
|
let secp = Secp256k1::new();
|
||||||
|
let sk_str = "688C77BC2D5AAFF5491CF309D4753B732135470D05B7B2CD21ADD0744FE97BEF";
|
||||||
|
let keypair = KeyPair::from_seckey_str(&secp, sk_str).unwrap();
|
||||||
|
let sk = SecretKey::from_keypair(&secp, &keypair);
|
||||||
|
assert_eq!(SecretKey::from_str(sk_str).unwrap(), sk);
|
||||||
|
let pk = ::key::PublicKey::from_keypair(&secp, &keypair);
|
||||||
|
assert_eq!(::key::PublicKey::from_secret_key(&secp, &sk), pk);
|
||||||
|
let xpk = PublicKey::from_keypair(&secp, &keypair);
|
||||||
|
assert_eq!(PublicKey::from(pk), xpk);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_pubkey_from_bad_slice() {
|
fn test_pubkey_from_bad_slice() {
|
||||||
// Bad sizes
|
// Bad sizes
|
||||||
|
|
Loading…
Reference in New Issue