@@ -292,6 +292,31 @@ impl SecretKey {
292292 pub fn sign_ecdsa ( & self , msg : Message ) -> ecdsa:: Signature {
293293 SECP256K1 . sign_ecdsa ( & msg, self )
294294 }
295+
296+ /// Returns the [`KeyPair`] for this [`SecretKey`].
297+ ///
298+ /// This is equivalent to using [`KeyPair::from_secret_key`].
299+ #[ inline]
300+ pub fn keypair < C : Signing > ( & self , secp : & Secp256k1 < C > ) -> KeyPair {
301+ KeyPair :: from_secret_key ( secp, self )
302+ }
303+
304+ /// Returns the [`PublicKey`] for this [`SecretKey`].
305+ ///
306+ /// This is equivalent to using [`PublicKey::from_secret_key`].
307+ #[ inline]
308+ pub fn public_key < C : Signing > ( & self , secp : & Secp256k1 < C > ) -> PublicKey {
309+ PublicKey :: from_secret_key ( secp, self )
310+ }
311+
312+ /// Returns the [`XOnlyPublicKey`] (and it's [`Parity`]) for this [`SecretKey`].
313+ ///
314+ /// This is equivalent to `XOnlyPublicKey::from_keypair(self.keypair(secp))`.
315+ #[ inline]
316+ pub fn x_only_public_key < C : Signing > ( & self , secp : & Secp256k1 < C > ) -> ( XOnlyPublicKey , Parity ) {
317+ let kp = self . keypair ( secp) ;
318+ XOnlyPublicKey :: from_keypair ( & kp)
319+ }
295320}
296321
297322#[ cfg( feature = "serde" ) ]
@@ -418,6 +443,20 @@ impl PublicKey {
418443 }
419444 }
420445
446+ /// Creates a [`PublicKey`] using the key material from `pk` combined with the `parity`.
447+ pub fn from_x_only_public_key ( pk : XOnlyPublicKey , parity : Parity ) -> PublicKey {
448+ let mut buf = [ 0u8 ; 33 ] ;
449+
450+ // First byte of a compressed key should be `0x02 AND parity`.
451+ buf[ 0 ] = match parity {
452+ Parity :: Even => 0x02 ,
453+ Parity :: Odd => 0x03 ,
454+ } ;
455+ buf[ 1 ..] . clone_from_slice ( & pk. serialize ( ) ) ;
456+
457+ PublicKey :: from_slice ( & buf) . expect ( "we know the buffer is valid" )
458+ }
459+
421460 #[ inline]
422461 /// Serializes the key as a byte-encoded pair of values. In compressed form the y-coordinate is
423462 /// represented by only a single bit, as x determines it up to one bit.
@@ -589,6 +628,25 @@ impl PublicKey {
589628 }
590629 }
591630 }
631+
632+ /// Returns the [`XOnlyPublicKey`] (and it's [`Parity`]) for this [`PublicKey`].
633+ #[ inline]
634+ pub fn x_only_public_key ( & self ) -> ( XOnlyPublicKey , Parity ) {
635+ let mut pk_parity = 0 ;
636+ unsafe {
637+ let mut xonly_pk = ffi:: XOnlyPublicKey :: new ( ) ;
638+ let ret = ffi:: secp256k1_xonly_pubkey_from_pubkey (
639+ ffi:: secp256k1_context_no_precomp,
640+ & mut xonly_pk,
641+ & mut pk_parity,
642+ self . as_ptr ( ) ,
643+ ) ;
644+ debug_assert_eq ! ( ret, 1 ) ;
645+ let parity = Parity :: from_i32 ( pk_parity) . expect ( "should not panic, pk_parity is 0 or 1" ) ;
646+
647+ ( XOnlyPublicKey ( xonly_pk) , parity)
648+ }
649+ }
592650}
593651
594652impl CPtr for PublicKey {
@@ -674,7 +732,7 @@ impl Ord for PublicKey {
674732///
675733/// let secp = Secp256k1::new();
676734/// let (secret_key, public_key) = secp.generate_keypair(&mut rand::thread_rng());
677- /// let key_pair = KeyPair::from_secret_key(&secp, secret_key);
735+ /// let key_pair = KeyPair::from_secret_key(&secp, & secret_key);
678736/// # }
679737/// ```
680738/// [`Deserialize`]: serde::Deserialize
@@ -700,7 +758,7 @@ impl KeyPair {
700758 #[ inline]
701759 pub fn from_secret_key < C : Signing > (
702760 secp : & Secp256k1 < C > ,
703- sk : SecretKey ,
761+ sk : & SecretKey ,
704762 ) -> KeyPair {
705763 unsafe {
706764 let mut kp = ffi:: KeyPair :: new ( ) ;
@@ -860,9 +918,27 @@ impl KeyPair {
860918 }
861919 }
862920
863- /// Gets the [XOnlyPublicKey] for this [KeyPair].
921+ /// Returns the [`SecretKey`] for this [`KeyPair`].
922+ ///
923+ /// This is equivalent to using [`SecretKey::from_keypair`].
924+ #[ inline]
925+ pub fn secret_key ( & self ) -> SecretKey {
926+ SecretKey :: from_keypair ( self )
927+ }
928+
929+ /// Returns the [`PublicKey`] for this [`KeyPair`].
930+ ///
931+ /// This is equivalent to using [`PublicKey::from_keypair`].
932+ #[ inline]
933+ pub fn public_key ( & self ) -> PublicKey {
934+ PublicKey :: from_keypair ( self )
935+ }
936+
937+ /// Returns the [`XOnlyPublicKey`] (and it's [`Parity`]) for this [`KeyPair`].
938+ ///
939+ /// This is equivalent to using [`XOnlyPublicKey::from_keypair`].
864940 #[ inline]
865- pub fn public_key ( & self ) -> XOnlyPublicKey {
941+ pub fn x_only_public_key ( & self ) -> ( XOnlyPublicKey , Parity ) {
866942 XOnlyPublicKey :: from_keypair ( self )
867943 }
868944
@@ -1008,9 +1084,9 @@ impl XOnlyPublicKey {
10081084 & mut self . 0
10091085 }
10101086
1011- /// Creates a new Schnorr public key from a Schnorr key pair .
1087+ /// Returns the [`XOnlyPublicKey`] (and it's [`Parity`]) for `keypair` .
10121088 #[ inline]
1013- pub fn from_keypair ( keypair : & KeyPair ) -> XOnlyPublicKey {
1089+ pub fn from_keypair ( keypair : & KeyPair ) -> ( XOnlyPublicKey , Parity ) {
10141090 let mut pk_parity = 0 ;
10151091 unsafe {
10161092 let mut xonly_pk = ffi:: XOnlyPublicKey :: new ( ) ;
@@ -1021,7 +1097,9 @@ impl XOnlyPublicKey {
10211097 keypair. as_ptr ( ) ,
10221098 ) ;
10231099 debug_assert_eq ! ( ret, 1 ) ;
1024- XOnlyPublicKey ( xonly_pk)
1100+ let parity = Parity :: from_i32 ( pk_parity) . expect ( "should not panic, pk_parity is 0 or 1" ) ;
1101+
1102+ ( XOnlyPublicKey ( xonly_pk) , parity)
10251103 }
10261104 }
10271105
@@ -1092,7 +1170,7 @@ impl XOnlyPublicKey {
10921170 /// thread_rng().fill_bytes(&mut tweak);
10931171 ///
10941172 /// let mut key_pair = KeyPair::new(&secp, &mut thread_rng());
1095- /// let mut public_key = key_pair.public_key ();
1173+ /// let ( mut public_key, _parity) = key_pair.x_only_public_key ();
10961174 /// public_key.tweak_add_assign(&secp, &tweak).expect("Improbable to fail with a randomly generated tweak");
10971175 /// # }
10981176 /// ```
@@ -1105,6 +1183,7 @@ impl XOnlyPublicKey {
11051183 return Err ( Error :: InvalidTweak ) ;
11061184 }
11071185
1186+ let mut pk_parity = 0 ;
11081187 unsafe {
11091188 let mut pubkey = ffi:: PublicKey :: new ( ) ;
11101189 let mut err = ffi:: secp256k1_xonly_pubkey_tweak_add (
@@ -1117,18 +1196,17 @@ impl XOnlyPublicKey {
11171196 return Err ( Error :: InvalidTweak ) ;
11181197 }
11191198
1120- let mut parity: :: secp256k1_sys:: types:: c_int = 0 ;
11211199 err = ffi:: secp256k1_xonly_pubkey_from_pubkey (
11221200 secp. ctx ,
11231201 & mut self . 0 ,
1124- & mut parity ,
1202+ & mut pk_parity ,
11251203 & pubkey,
11261204 ) ;
11271205 if err == 0 {
11281206 return Err ( Error :: InvalidPublicKey ) ;
11291207 }
11301208
1131- Parity :: from_i32 ( parity ) . map_err ( Into :: into)
1209+ Parity :: from_i32 ( pk_parity ) . map_err ( Into :: into)
11321210 }
11331211 }
11341212
@@ -1157,7 +1235,7 @@ impl XOnlyPublicKey {
11571235 /// thread_rng().fill_bytes(&mut tweak);
11581236 ///
11591237 /// let mut key_pair = KeyPair::new(&secp, &mut thread_rng());
1160- /// let mut public_key = key_pair.public_key ();
1238+ /// let ( mut public_key, _) = key_pair.x_only_public_key ();
11611239 /// let original = public_key;
11621240 /// let parity = public_key.tweak_add_assign(&secp, &tweak).expect("Improbable to fail with a randomly generated tweak");
11631241 /// assert!(original.tweak_add_check(&secp, &public_key, parity, tweak));
@@ -1183,6 +1261,14 @@ impl XOnlyPublicKey {
11831261 err == 1
11841262 }
11851263 }
1264+
1265+ /// Returns the [`PublicKey`] for this [`XOnlyPublicKey`].
1266+ ///
1267+ /// This is equivalent to using [`PublicKey::from_xonly_and_parity(self, parity)`].
1268+ #[ inline]
1269+ pub fn public_key ( & self , parity : Parity ) -> PublicKey {
1270+ PublicKey :: from_x_only_public_key ( * self , parity)
1271+ }
11861272}
11871273
11881274/// Represents the parity passed between FFI function calls.
@@ -1420,7 +1506,7 @@ pub mod serde_keypair {
14201506
14211507 Ok ( KeyPair :: from_secret_key (
14221508 & :: SECP256K1 ,
1423- secret_key,
1509+ & secret_key,
14241510 ) )
14251511 }
14261512}
@@ -1972,12 +2058,15 @@ mod test {
19722058 thread_rng ( ) . fill_bytes ( & mut tweak) ;
19732059
19742060 let mut kp = KeyPair :: new ( & s, & mut thread_rng ( ) ) ;
1975- let mut pk = kp. public_key ( ) ;
2061+ let ( mut pk, _parity ) = kp. x_only_public_key ( ) ;
19762062
19772063 let orig_pk = pk;
19782064 kp. tweak_add_assign ( & s, & tweak) . expect ( "Tweak error" ) ;
19792065 let parity = pk. tweak_add_assign ( & s, & tweak) . expect ( "Tweak error" ) ;
1980- assert_eq ! ( XOnlyPublicKey :: from_keypair( & kp) , pk) ;
2066+
2067+ let ( back, _) = XOnlyPublicKey :: from_keypair ( & kp) ;
2068+
2069+ assert_eq ! ( back, pk) ;
19812070 assert ! ( orig_pk. tweak_add_check( & s, & pk, parity, tweak) ) ;
19822071 }
19832072 }
@@ -2046,4 +2135,150 @@ mod test {
20462135 assert_tokens ( & sk. readable ( ) , & [ Token :: Str ( SK_STR ) ] ) ;
20472136 assert_tokens ( & sk. readable ( ) , & [ Token :: String ( SK_STR ) ] ) ;
20482137 }
2138+
2139+ #[ cfg( all( not( fuzzing) , any( feature = "alloc" , feature = "std" ) ) ) ]
2140+ fn keys ( ) -> ( SecretKey , PublicKey , KeyPair , XOnlyPublicKey ) {
2141+ let secp = Secp256k1 :: new ( ) ;
2142+
2143+ static SK_BYTES : [ u8 ; 32 ] = [
2144+ 0x01 , 0x01 , 0x01 , 0x01 , 0x01 , 0x01 , 0x01 , 0x01 ,
2145+ 0x00 , 0x01 , 0x02 , 0x03 , 0x04 , 0x05 , 0x06 , 0x07 ,
2146+ 0xff , 0xff , 0x00 , 0x00 , 0xff , 0xff , 0x00 , 0x00 ,
2147+ 0x63 , 0x63 , 0x63 , 0x63 , 0x63 , 0x63 , 0x63 , 0x63 ,
2148+ ] ;
2149+
2150+ static PK_BYTES : [ u8 ; 32 ] = [
2151+ 0x18 , 0x84 , 0x57 , 0x81 , 0xf6 , 0x31 , 0xc4 , 0x8f ,
2152+ 0x1c , 0x97 , 0x09 , 0xe2 , 0x30 , 0x92 , 0x06 , 0x7d ,
2153+ 0x06 , 0x83 , 0x7f , 0x30 , 0xaa , 0x0c , 0xd0 , 0x54 ,
2154+ 0x4a , 0xc8 , 0x87 , 0xfe , 0x91 , 0xdd , 0xd1 , 0x66
2155+ ] ;
2156+
2157+ let mut pk_bytes = [ 0u8 ; 33 ] ;
2158+ pk_bytes[ 0 ] = 0x02 ; // Use positive Y co-ordinate.
2159+ pk_bytes[ 1 ..] . clone_from_slice ( & PK_BYTES ) ;
2160+
2161+ let sk = SecretKey :: from_slice ( & SK_BYTES ) . expect ( "failed to parse sk bytes" ) ;
2162+ let pk = PublicKey :: from_slice ( & pk_bytes) . expect ( "failed to create pk from iterator" ) ;
2163+ let kp = KeyPair :: from_secret_key ( & secp, & sk) ;
2164+ let xonly = XOnlyPublicKey :: from_slice ( & PK_BYTES ) . expect ( "failed to get xonly from slice" ) ;
2165+
2166+ ( sk, pk, kp, xonly)
2167+ }
2168+
2169+ #[ test]
2170+ #[ cfg( all( not( fuzzing) , any( feature = "alloc" , feature = "std" ) ) ) ]
2171+ fn convert_public_key_to_xonly_public_key ( ) {
2172+ let ( _sk, pk, _kp, want) = keys ( ) ;
2173+ let ( got, parity) = pk. x_only_public_key ( ) ;
2174+
2175+ assert_eq ! ( parity, Parity :: Even ) ;
2176+ assert_eq ! ( got, want)
2177+ }
2178+
2179+ #[ test]
2180+ #[ cfg( all( not( fuzzing) , any( feature = "alloc" , feature = "std" ) ) ) ]
2181+ fn convert_secret_key_to_public_key ( ) {
2182+ let secp = Secp256k1 :: new ( ) ;
2183+
2184+ let ( sk, want, _kp, _xonly) = keys ( ) ;
2185+ let got = sk. public_key ( & secp) ;
2186+
2187+ assert_eq ! ( got, want)
2188+ }
2189+
2190+ #[ test]
2191+ #[ cfg( all( not( fuzzing) , any( feature = "alloc" , feature = "std" ) ) ) ]
2192+ fn convert_secret_key_to_x_only_public_key ( ) {
2193+ let secp = Secp256k1 :: new ( ) ;
2194+
2195+ let ( sk, _pk, _kp, want) = keys ( ) ;
2196+ let ( got, parity) = sk. x_only_public_key ( & secp) ;
2197+
2198+ assert_eq ! ( parity, Parity :: Even ) ;
2199+ assert_eq ! ( got, want)
2200+ }
2201+
2202+ #[ test]
2203+ #[ cfg( all( not( fuzzing) , any( feature = "alloc" , feature = "std" ) ) ) ]
2204+ fn convert_keypair_to_public_key ( ) {
2205+ let ( _sk, want, kp, _xonly) = keys ( ) ;
2206+ let got = kp. public_key ( ) ;
2207+
2208+ assert_eq ! ( got, want)
2209+ }
2210+
2211+ #[ test]
2212+ #[ cfg( all( not( fuzzing) , any( feature = "alloc" , feature = "std" ) ) ) ]
2213+ fn convert_keypair_to_x_only_public_key ( ) {
2214+ let ( _sk, _pk, kp, want) = keys ( ) ;
2215+ let ( got, parity) = kp. x_only_public_key ( ) ;
2216+
2217+ assert_eq ! ( parity, Parity :: Even ) ;
2218+ assert_eq ! ( got, want)
2219+ }
2220+
2221+ // SecretKey -> KeyPair -> SecretKey
2222+ #[ test]
2223+ #[ cfg( all( not( fuzzing) , any( feature = "alloc" , feature = "std" ) ) ) ]
2224+ fn roundtrip_secret_key_via_keypair ( ) {
2225+ let secp = Secp256k1 :: new ( ) ;
2226+ let ( sk, _pk, _kp, _xonly) = keys ( ) ;
2227+
2228+ let kp = sk. keypair ( & secp) ;
2229+ let back = kp. secret_key ( ) ;
2230+
2231+ assert_eq ! ( back, sk)
2232+ }
2233+
2234+ // KeyPair -> SecretKey -> KeyPair
2235+ #[ test]
2236+ #[ cfg( all( not( fuzzing) , any( feature = "alloc" , feature = "std" ) ) ) ]
2237+ fn roundtrip_keypair_via_secret_key ( ) {
2238+ let secp = Secp256k1 :: new ( ) ;
2239+ let ( _sk, _pk, kp, _xonly) = keys ( ) ;
2240+
2241+ let sk = kp. secret_key ( ) ;
2242+ let back = sk. keypair ( & secp) ;
2243+
2244+ assert_eq ! ( back, kp)
2245+ }
2246+
2247+ // XOnlyPublicKey -> PublicKey -> XOnlyPublicKey
2248+ #[ test]
2249+ #[ cfg( all( not( fuzzing) , any( feature = "alloc" , feature = "std" ) ) ) ]
2250+ fn roundtrip_x_only_public_key_via_public_key ( ) {
2251+ let ( _sk, _pk, _kp, xonly) = keys ( ) ;
2252+
2253+ let pk = xonly. public_key ( Parity :: Even ) ;
2254+ let ( back, parity) = pk. x_only_public_key ( ) ;
2255+
2256+ assert_eq ! ( parity, Parity :: Even ) ;
2257+ assert_eq ! ( back, xonly)
2258+ }
2259+
2260+ // PublicKey -> XOnlyPublicKey -> PublicKey
2261+ #[ test]
2262+ #[ cfg( all( not( fuzzing) , any( feature = "alloc" , feature = "std" ) ) ) ]
2263+ fn roundtrip_public_key_via_x_only_public_key ( ) {
2264+ let ( _sk, pk, _kp, _xonly) = keys ( ) ;
2265+
2266+ let ( xonly, parity) = pk. x_only_public_key ( ) ;
2267+ let back = xonly. public_key ( parity) ;
2268+
2269+ assert_eq ! ( back, pk)
2270+ }
2271+
2272+ #[ test]
2273+ fn public_key_from_x_only_public_key_and_odd_parity ( ) {
2274+ let s = "18845781f631c48f1c9709e23092067d06837f30aa0cd0544ac887fe91ddd166" ;
2275+ let mut want = String :: from ( "03" ) ;
2276+ want. push_str ( s) ;
2277+
2278+ let xonly = XOnlyPublicKey :: from_str ( s) . expect ( "failed to parse xonly pubkey string" ) ;
2279+ let pk = xonly. public_key ( Parity :: Odd ) ;
2280+ let got = format ! ( "{}" , pk) ;
2281+
2282+ assert_eq ! ( got, want)
2283+ }
20492284}
0 commit comments