@@ -134,9 +134,9 @@ impl SecretKey {
134134 }
135135 }
136136
137- /// Creates a new secret key using data from BIP-340 [`::schnorrsig:: KeyPair`]
137+ /// Creates a new secret key using data from BIP-340 [`KeyPair`]
138138 #[ inline]
139- pub fn from_keypair ( keypair : & :: schnorrsig :: KeyPair ) -> Self {
139+ pub fn from_keypair ( keypair : & KeyPair ) -> Self {
140140 let mut sk = [ 0u8 ; constants:: SECRET_KEY_SIZE ] ;
141141 unsafe {
142142 let ret = ffi:: secp256k1_keypair_sec (
@@ -297,9 +297,9 @@ impl PublicKey {
297297 }
298298 }
299299
300- /// Creates a new compressed public key key using data from BIP-340 [`::schnorrsig:: KeyPair`]
300+ /// Creates a new compressed public key key using data from BIP-340 [`KeyPair`]
301301 #[ inline]
302- pub fn from_keypair ( keypair : & :: schnorrsig :: KeyPair ) -> Self {
302+ pub fn from_keypair ( keypair : & KeyPair ) -> Self {
303303 unsafe {
304304 let mut pk = ffi:: PublicKey :: new ( ) ;
305305 let ret = ffi:: secp256k1_keypair_pub (
@@ -505,6 +505,175 @@ impl Ord for PublicKey {
505505 }
506506}
507507
508+ /// Opaque data structure that holds a keypair consisting of a secret and a public key.
509+ #[ derive( Clone ) ]
510+ pub struct KeyPair ( ffi:: KeyPair ) ;
511+ impl_display_secret ! ( KeyPair ) ;
512+
513+ impl KeyPair {
514+ /// Obtains a raw const pointer suitable for use with FFI functions
515+ #[ inline]
516+ pub fn as_ptr ( & self ) -> * const ffi:: KeyPair {
517+ & self . 0
518+ }
519+
520+ /// Obtains a raw mutable pointer suitable for use with FFI functions
521+ #[ inline]
522+ pub fn as_mut_ptr ( & mut self ) -> * mut ffi:: KeyPair {
523+ & mut self . 0
524+ }
525+
526+ /// Creates a Schnorr KeyPair directly from generic Secp256k1 secret key
527+ ///
528+ /// # Panic
529+ ///
530+ /// Panics if internal representation of the provided [`SecretKey`] does not hold correct secret
531+ /// key value obtained from Secp256k1 library previously, specifically when secret key value is
532+ /// out-of-range (0 or in excess of the group order).
533+ #[ inline]
534+ pub fn from_secret_key < C : Signing > (
535+ secp : & Secp256k1 < C > ,
536+ sk : SecretKey ,
537+ ) -> KeyPair {
538+ unsafe {
539+ let mut kp = ffi:: KeyPair :: new ( ) ;
540+ if ffi:: secp256k1_keypair_create ( secp. ctx , & mut kp, sk. as_c_ptr ( ) ) == 1 {
541+ KeyPair ( kp)
542+ } else {
543+ panic ! ( "the provided secret key is invalid: it is corrupted or was not produced by Secp256k1 library" )
544+ }
545+ }
546+ }
547+
548+ /// Creates a Schnorr KeyPair directly from a secret key slice.
549+ ///
550+ /// # Errors
551+ ///
552+ /// [`Error::InvalidSecretKey`] if the provided data has an incorrect length, exceeds Secp256k1
553+ /// field `p` value or the corresponding public key is not even.
554+ #[ inline]
555+ pub fn from_seckey_slice < C : Signing > (
556+ secp : & Secp256k1 < C > ,
557+ data : & [ u8 ] ,
558+ ) -> Result < KeyPair , Error > {
559+ if data. is_empty ( ) || data. len ( ) != constants:: SECRET_KEY_SIZE {
560+ return Err ( Error :: InvalidSecretKey ) ;
561+ }
562+
563+ unsafe {
564+ let mut kp = ffi:: KeyPair :: new ( ) ;
565+ if ffi:: secp256k1_keypair_create ( secp. ctx , & mut kp, data. as_c_ptr ( ) ) == 1 {
566+ Ok ( KeyPair ( kp) )
567+ } else {
568+ Err ( Error :: InvalidSecretKey )
569+ }
570+ }
571+ }
572+
573+ /// Creates a Schnorr KeyPair directly from a secret key string
574+ ///
575+ /// # Errors
576+ ///
577+ /// [`Error::InvalidSecretKey`] if corresponding public key for the provided secret key is not even.
578+ #[ inline]
579+ pub fn from_seckey_str < C : Signing > ( secp : & Secp256k1 < C > , s : & str ) -> Result < KeyPair , Error > {
580+ let mut res = [ 0u8 ; constants:: SECRET_KEY_SIZE ] ;
581+ match from_hex ( s, & mut res) {
582+ Ok ( constants:: SECRET_KEY_SIZE ) => {
583+ KeyPair :: from_seckey_slice ( secp, & res[ 0 ..constants:: SECRET_KEY_SIZE ] )
584+ }
585+ _ => Err ( Error :: InvalidPublicKey ) ,
586+ }
587+ }
588+
589+ /// Creates a new random secret key. Requires compilation with the "rand" feature.
590+ #[ inline]
591+ #[ cfg( any( test, feature = "rand" ) ) ]
592+ pub fn new < R : Rng + ?Sized , C : Signing > ( secp : & Secp256k1 < C > , rng : & mut R ) -> KeyPair {
593+ let mut random_32_bytes = || {
594+ let mut ret = [ 0u8 ; 32 ] ;
595+ rng. fill_bytes ( & mut ret) ;
596+ ret
597+ } ;
598+ let mut data = random_32_bytes ( ) ;
599+ unsafe {
600+ let mut keypair = ffi:: KeyPair :: new ( ) ;
601+ while ffi:: secp256k1_keypair_create ( secp. ctx , & mut keypair, data. as_c_ptr ( ) ) == 0 {
602+ data = random_32_bytes ( ) ;
603+ }
604+ KeyPair ( keypair)
605+ }
606+ }
607+
608+ /// Serialize the key pair as a secret key byte value
609+ #[ inline]
610+ pub fn serialize_secret ( & self ) -> [ u8 ; constants:: SECRET_KEY_SIZE ] {
611+ * SecretKey :: from_keypair ( self ) . as_ref ( )
612+ }
613+
614+ /// Tweak a keypair by adding the given tweak to the secret key and updating the public key
615+ /// accordingly.
616+ ///
617+ /// Will return an error if the resulting key would be invalid or if the tweak was not a 32-byte
618+ /// length slice.
619+ ///
620+ /// NB: Will not error if the tweaked public key has an odd value and can't be used for
621+ /// BIP 340-342 purposes.
622+ // TODO: Add checked implementation
623+ #[ inline]
624+ pub fn tweak_add_assign < C : Verification > (
625+ & mut self ,
626+ secp : & Secp256k1 < C > ,
627+ tweak : & [ u8 ] ,
628+ ) -> Result < ( ) , Error > {
629+ if tweak. len ( ) != 32 {
630+ return Err ( Error :: InvalidTweak ) ;
631+ }
632+
633+ unsafe {
634+ let err = ffi:: secp256k1_keypair_xonly_tweak_add (
635+ secp. ctx ,
636+ & mut self . 0 ,
637+ tweak. as_c_ptr ( ) ,
638+ ) ;
639+
640+ if err == 1 {
641+ Ok ( ( ) )
642+ } else {
643+ Err ( Error :: InvalidTweak )
644+ }
645+ }
646+ }
647+ }
648+
649+ impl From < KeyPair > for SecretKey {
650+ #[ inline]
651+ fn from ( pair : KeyPair ) -> Self {
652+ SecretKey :: from_keypair ( & pair)
653+ }
654+ }
655+
656+ impl < ' a > From < & ' a KeyPair > for SecretKey {
657+ #[ inline]
658+ fn from ( pair : & ' a KeyPair ) -> Self {
659+ SecretKey :: from_keypair ( pair)
660+ }
661+ }
662+
663+ impl From < KeyPair > for PublicKey {
664+ #[ inline]
665+ fn from ( pair : KeyPair ) -> Self {
666+ PublicKey :: from_keypair ( & pair)
667+ }
668+ }
669+
670+ impl < ' a > From < & ' a KeyPair > for PublicKey {
671+ #[ inline]
672+ fn from ( pair : & ' a KeyPair ) -> Self {
673+ PublicKey :: from_keypair ( pair)
674+ }
675+ }
676+
508677#[ cfg( test) ]
509678mod test {
510679 use Secp256k1 ;
0 commit comments