@@ -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 {
@@ -866,9 +924,27 @@ impl KeyPair {
866924 }
867925 }
868926
869- /// Gets the [XOnlyPublicKey] for this [KeyPair].
927+ /// Returns the [`SecretKey`] for this [`KeyPair`].
928+ ///
929+ /// This is equivalent to using [`SecretKey::from_keypair`].
930+ #[ inline]
931+ pub fn secret_key ( & self ) -> SecretKey {
932+ SecretKey :: from_keypair ( self )
933+ }
934+
935+ /// Returns the [`PublicKey`] for this [`KeyPair`].
936+ ///
937+ /// This is equivalent to using [`PublicKey::from_keypair`].
938+ #[ inline]
939+ pub fn public_key ( & self ) -> PublicKey {
940+ PublicKey :: from_keypair ( self )
941+ }
942+
943+ /// Returns the [`XOnlyPublicKey`] (and it's [`Parity`]) for this [`KeyPair`].
944+ ///
945+ /// This is equivalent to using [`XOnlyPublicKey::from_keypair`].
870946 #[ inline]
871- pub fn public_key ( & self ) -> XOnlyPublicKey {
947+ pub fn x_only_public_key ( & self ) -> ( XOnlyPublicKey , Parity ) {
872948 XOnlyPublicKey :: from_keypair ( self )
873949 }
874950
@@ -1014,9 +1090,9 @@ impl XOnlyPublicKey {
10141090 & mut self . 0
10151091 }
10161092
1017- /// Creates a new Schnorr public key from a Schnorr key pair .
1093+ /// Returns the [`XOnlyPublicKey`] (and it's [`Parity`]) for `keypair` .
10181094 #[ inline]
1019- pub fn from_keypair ( keypair : & KeyPair ) -> XOnlyPublicKey {
1095+ pub fn from_keypair ( keypair : & KeyPair ) -> ( XOnlyPublicKey , Parity ) {
10201096 let mut pk_parity = 0 ;
10211097 unsafe {
10221098 let mut xonly_pk = ffi:: XOnlyPublicKey :: new ( ) ;
@@ -1027,7 +1103,9 @@ impl XOnlyPublicKey {
10271103 keypair. as_ptr ( ) ,
10281104 ) ;
10291105 debug_assert_eq ! ( ret, 1 ) ;
1030- XOnlyPublicKey ( xonly_pk)
1106+ let parity = Parity :: from_i32 ( pk_parity) . expect ( "should not panic, pk_parity is 0 or 1" ) ;
1107+
1108+ ( XOnlyPublicKey ( xonly_pk) , parity)
10311109 }
10321110 }
10331111
@@ -1098,7 +1176,7 @@ impl XOnlyPublicKey {
10981176 /// thread_rng().fill_bytes(&mut tweak);
10991177 ///
11001178 /// let mut key_pair = KeyPair::new(&secp, &mut thread_rng());
1101- /// let mut public_key = key_pair.public_key ();
1179+ /// let ( mut public_key, _parity) = key_pair.x_only_public_key ();
11021180 /// public_key.tweak_add_assign(&secp, &tweak).expect("Improbable to fail with a randomly generated tweak");
11031181 /// # }
11041182 /// ```
@@ -1163,7 +1241,7 @@ impl XOnlyPublicKey {
11631241 /// thread_rng().fill_bytes(&mut tweak);
11641242 ///
11651243 /// let mut key_pair = KeyPair::new(&secp, &mut thread_rng());
1166- /// let mut public_key = key_pair.public_key ();
1244+ /// let ( mut public_key, _) = key_pair.x_only_public_key ();
11671245 /// let original = public_key;
11681246 /// let parity = public_key.tweak_add_assign(&secp, &tweak).expect("Improbable to fail with a randomly generated tweak");
11691247 /// assert!(original.tweak_add_check(&secp, &public_key, parity, tweak));
@@ -1189,6 +1267,14 @@ impl XOnlyPublicKey {
11891267 err == 1
11901268 }
11911269 }
1270+
1271+ /// Returns the [`PublicKey`] for this [`XOnlyPublicKey`].
1272+ ///
1273+ /// This is equivalent to using [`PublicKey::from_xonly_and_parity(self, parity)`].
1274+ #[ inline]
1275+ pub fn public_key ( & self , parity : Parity ) -> PublicKey {
1276+ PublicKey :: from_x_only_public_key ( * self , parity)
1277+ }
11921278}
11931279
11941280/// Represents the parity passed between FFI function calls.
@@ -1978,12 +2064,15 @@ mod test {
19782064 thread_rng ( ) . fill_bytes ( & mut tweak) ;
19792065
19802066 let mut kp = KeyPair :: new ( & s, & mut thread_rng ( ) ) ;
1981- let mut pk = kp. public_key ( ) ;
2067+ let ( mut pk, _parity ) = kp. x_only_public_key ( ) ;
19822068
19832069 let orig_pk = pk;
19842070 kp. tweak_add_assign ( & s, & tweak) . expect ( "Tweak error" ) ;
19852071 let parity = pk. tweak_add_assign ( & s, & tweak) . expect ( "Tweak error" ) ;
1986- assert_eq ! ( XOnlyPublicKey :: from_keypair( & kp) , pk) ;
2072+
2073+ let ( back, _) = XOnlyPublicKey :: from_keypair ( & kp) ;
2074+
2075+ assert_eq ! ( back, pk) ;
19872076 assert ! ( orig_pk. tweak_add_check( & s, & pk, parity, tweak) ) ;
19882077 }
19892078 }
@@ -2052,4 +2141,150 @@ mod test {
20522141 assert_tokens ( & sk. readable ( ) , & [ Token :: Str ( SK_STR ) ] ) ;
20532142 assert_tokens ( & sk. readable ( ) , & [ Token :: String ( SK_STR ) ] ) ;
20542143 }
2144+
2145+ #[ cfg( all( not( fuzzing) , any( feature = "alloc" , feature = "std" ) ) ) ]
2146+ fn keys ( ) -> ( SecretKey , PublicKey , KeyPair , XOnlyPublicKey ) {
2147+ let secp = Secp256k1 :: new ( ) ;
2148+
2149+ static SK_BYTES : [ u8 ; 32 ] = [
2150+ 0x01 , 0x01 , 0x01 , 0x01 , 0x01 , 0x01 , 0x01 , 0x01 ,
2151+ 0x00 , 0x01 , 0x02 , 0x03 , 0x04 , 0x05 , 0x06 , 0x07 ,
2152+ 0xff , 0xff , 0x00 , 0x00 , 0xff , 0xff , 0x00 , 0x00 ,
2153+ 0x63 , 0x63 , 0x63 , 0x63 , 0x63 , 0x63 , 0x63 , 0x63 ,
2154+ ] ;
2155+
2156+ static PK_BYTES : [ u8 ; 32 ] = [
2157+ 0x18 , 0x84 , 0x57 , 0x81 , 0xf6 , 0x31 , 0xc4 , 0x8f ,
2158+ 0x1c , 0x97 , 0x09 , 0xe2 , 0x30 , 0x92 , 0x06 , 0x7d ,
2159+ 0x06 , 0x83 , 0x7f , 0x30 , 0xaa , 0x0c , 0xd0 , 0x54 ,
2160+ 0x4a , 0xc8 , 0x87 , 0xfe , 0x91 , 0xdd , 0xd1 , 0x66
2161+ ] ;
2162+
2163+ let mut pk_bytes = [ 0u8 ; 33 ] ;
2164+ pk_bytes[ 0 ] = 0x02 ; // Use positive Y co-ordinate.
2165+ pk_bytes[ 1 ..] . clone_from_slice ( & PK_BYTES ) ;
2166+
2167+ let sk = SecretKey :: from_slice ( & SK_BYTES ) . expect ( "failed to parse sk bytes" ) ;
2168+ let pk = PublicKey :: from_slice ( & pk_bytes) . expect ( "failed to create pk from iterator" ) ;
2169+ let kp = KeyPair :: from_secret_key ( & secp, & sk) ;
2170+ let xonly = XOnlyPublicKey :: from_slice ( & PK_BYTES ) . expect ( "failed to get xonly from slice" ) ;
2171+
2172+ ( sk, pk, kp, xonly)
2173+ }
2174+
2175+ #[ test]
2176+ #[ cfg( all( not( fuzzing) , any( feature = "alloc" , feature = "std" ) ) ) ]
2177+ fn convert_public_key_to_xonly_public_key ( ) {
2178+ let ( _sk, pk, _kp, want) = keys ( ) ;
2179+ let ( got, parity) = pk. x_only_public_key ( ) ;
2180+
2181+ assert_eq ! ( parity, Parity :: Even ) ;
2182+ assert_eq ! ( got, want)
2183+ }
2184+
2185+ #[ test]
2186+ #[ cfg( all( not( fuzzing) , any( feature = "alloc" , feature = "std" ) ) ) ]
2187+ fn convert_secret_key_to_public_key ( ) {
2188+ let secp = Secp256k1 :: new ( ) ;
2189+
2190+ let ( sk, want, _kp, _xonly) = keys ( ) ;
2191+ let got = sk. public_key ( & secp) ;
2192+
2193+ assert_eq ! ( got, want)
2194+ }
2195+
2196+ #[ test]
2197+ #[ cfg( all( not( fuzzing) , any( feature = "alloc" , feature = "std" ) ) ) ]
2198+ fn convert_secret_key_to_x_only_public_key ( ) {
2199+ let secp = Secp256k1 :: new ( ) ;
2200+
2201+ let ( sk, _pk, _kp, want) = keys ( ) ;
2202+ let ( got, parity) = sk. x_only_public_key ( & secp) ;
2203+
2204+ assert_eq ! ( parity, Parity :: Even ) ;
2205+ assert_eq ! ( got, want)
2206+ }
2207+
2208+ #[ test]
2209+ #[ cfg( all( not( fuzzing) , any( feature = "alloc" , feature = "std" ) ) ) ]
2210+ fn convert_keypair_to_public_key ( ) {
2211+ let ( _sk, want, kp, _xonly) = keys ( ) ;
2212+ let got = kp. public_key ( ) ;
2213+
2214+ assert_eq ! ( got, want)
2215+ }
2216+
2217+ #[ test]
2218+ #[ cfg( all( not( fuzzing) , any( feature = "alloc" , feature = "std" ) ) ) ]
2219+ fn convert_keypair_to_x_only_public_key ( ) {
2220+ let ( _sk, _pk, kp, want) = keys ( ) ;
2221+ let ( got, parity) = kp. x_only_public_key ( ) ;
2222+
2223+ assert_eq ! ( parity, Parity :: Even ) ;
2224+ assert_eq ! ( got, want)
2225+ }
2226+
2227+ // SecretKey -> KeyPair -> SecretKey
2228+ #[ test]
2229+ #[ cfg( all( not( fuzzing) , any( feature = "alloc" , feature = "std" ) ) ) ]
2230+ fn roundtrip_secret_key_via_keypair ( ) {
2231+ let secp = Secp256k1 :: new ( ) ;
2232+ let ( sk, _pk, _kp, _xonly) = keys ( ) ;
2233+
2234+ let kp = sk. keypair ( & secp) ;
2235+ let back = kp. secret_key ( ) ;
2236+
2237+ assert_eq ! ( back, sk)
2238+ }
2239+
2240+ // KeyPair -> SecretKey -> KeyPair
2241+ #[ test]
2242+ #[ cfg( all( not( fuzzing) , any( feature = "alloc" , feature = "std" ) ) ) ]
2243+ fn roundtrip_keypair_via_secret_key ( ) {
2244+ let secp = Secp256k1 :: new ( ) ;
2245+ let ( _sk, _pk, kp, _xonly) = keys ( ) ;
2246+
2247+ let sk = kp. secret_key ( ) ;
2248+ let back = sk. keypair ( & secp) ;
2249+
2250+ assert_eq ! ( back, kp)
2251+ }
2252+
2253+ // XOnlyPublicKey -> PublicKey -> XOnlyPublicKey
2254+ #[ test]
2255+ #[ cfg( all( not( fuzzing) , any( feature = "alloc" , feature = "std" ) ) ) ]
2256+ fn roundtrip_x_only_public_key_via_public_key ( ) {
2257+ let ( _sk, _pk, _kp, xonly) = keys ( ) ;
2258+
2259+ let pk = xonly. public_key ( Parity :: Even ) ;
2260+ let ( back, parity) = pk. x_only_public_key ( ) ;
2261+
2262+ assert_eq ! ( parity, Parity :: Even ) ;
2263+ assert_eq ! ( back, xonly)
2264+ }
2265+
2266+ // PublicKey -> XOnlyPublicKey -> PublicKey
2267+ #[ test]
2268+ #[ cfg( all( not( fuzzing) , any( feature = "alloc" , feature = "std" ) ) ) ]
2269+ fn roundtrip_public_key_via_x_only_public_key ( ) {
2270+ let ( _sk, pk, _kp, _xonly) = keys ( ) ;
2271+
2272+ let ( xonly, parity) = pk. x_only_public_key ( ) ;
2273+ let back = xonly. public_key ( parity) ;
2274+
2275+ assert_eq ! ( back, pk)
2276+ }
2277+
2278+ #[ test]
2279+ fn public_key_from_x_only_public_key_and_odd_parity ( ) {
2280+ let s = "18845781f631c48f1c9709e23092067d06837f30aa0cd0544ac887fe91ddd166" ;
2281+ let mut want = String :: from ( "03" ) ;
2282+ want. push_str ( s) ;
2283+
2284+ let xonly = XOnlyPublicKey :: from_str ( s) . expect ( "failed to parse xonly pubkey string" ) ;
2285+ let pk = xonly. public_key ( Parity :: Odd ) ;
2286+ let got = format ! ( "{}" , pk) ;
2287+
2288+ assert_eq ! ( got, want)
2289+ }
20552290}
0 commit comments