@@ -292,6 +292,31 @@ impl SecretKey {
292
292
pub fn sign_ecdsa ( & self , msg : Message ) -> ecdsa:: Signature {
293
293
SECP256K1 . sign_ecdsa ( & msg, self )
294
294
}
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
+ }
295
320
}
296
321
297
322
#[ cfg( feature = "serde" ) ]
@@ -418,6 +443,20 @@ impl PublicKey {
418
443
}
419
444
}
420
445
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
+
421
460
#[ inline]
422
461
/// Serializes the key as a byte-encoded pair of values. In compressed form the y-coordinate is
423
462
/// represented by only a single bit, as x determines it up to one bit.
@@ -589,6 +628,25 @@ impl PublicKey {
589
628
}
590
629
}
591
630
}
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
+ }
592
650
}
593
651
594
652
impl CPtr for PublicKey {
@@ -866,9 +924,27 @@ impl KeyPair {
866
924
}
867
925
}
868
926
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`].
870
946
#[ inline]
871
- pub fn public_key ( & self ) -> XOnlyPublicKey {
947
+ pub fn x_only_public_key ( & self ) -> ( XOnlyPublicKey , Parity ) {
872
948
XOnlyPublicKey :: from_keypair ( self )
873
949
}
874
950
@@ -1014,9 +1090,9 @@ impl XOnlyPublicKey {
1014
1090
& mut self . 0
1015
1091
}
1016
1092
1017
- /// Creates a new Schnorr public key from a Schnorr key pair .
1093
+ /// Returns the [`XOnlyPublicKey`] (and it's [`Parity`]) for `keypair` .
1018
1094
#[ inline]
1019
- pub fn from_keypair ( keypair : & KeyPair ) -> XOnlyPublicKey {
1095
+ pub fn from_keypair ( keypair : & KeyPair ) -> ( XOnlyPublicKey , Parity ) {
1020
1096
let mut pk_parity = 0 ;
1021
1097
unsafe {
1022
1098
let mut xonly_pk = ffi:: XOnlyPublicKey :: new ( ) ;
@@ -1027,7 +1103,9 @@ impl XOnlyPublicKey {
1027
1103
keypair. as_ptr ( ) ,
1028
1104
) ;
1029
1105
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)
1031
1109
}
1032
1110
}
1033
1111
@@ -1098,7 +1176,7 @@ impl XOnlyPublicKey {
1098
1176
/// thread_rng().fill_bytes(&mut tweak);
1099
1177
///
1100
1178
/// 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 ();
1102
1180
/// public_key.tweak_add_assign(&secp, &tweak).expect("Improbable to fail with a randomly generated tweak");
1103
1181
/// # }
1104
1182
/// ```
@@ -1163,7 +1241,7 @@ impl XOnlyPublicKey {
1163
1241
/// thread_rng().fill_bytes(&mut tweak);
1164
1242
///
1165
1243
/// 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 ();
1167
1245
/// let original = public_key;
1168
1246
/// let parity = public_key.tweak_add_assign(&secp, &tweak).expect("Improbable to fail with a randomly generated tweak");
1169
1247
/// assert!(original.tweak_add_check(&secp, &public_key, parity, tweak));
@@ -1189,6 +1267,14 @@ impl XOnlyPublicKey {
1189
1267
err == 1
1190
1268
}
1191
1269
}
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
+ }
1192
1278
}
1193
1279
1194
1280
/// Represents the parity passed between FFI function calls.
@@ -1978,12 +2064,15 @@ mod test {
1978
2064
thread_rng ( ) . fill_bytes ( & mut tweak) ;
1979
2065
1980
2066
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 ( ) ;
1982
2068
1983
2069
let orig_pk = pk;
1984
2070
kp. tweak_add_assign ( & s, & tweak) . expect ( "Tweak error" ) ;
1985
2071
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) ;
1987
2076
assert ! ( orig_pk. tweak_add_check( & s, & pk, parity, tweak) ) ;
1988
2077
}
1989
2078
}
@@ -2052,4 +2141,150 @@ mod test {
2052
2141
assert_tokens ( & sk. readable ( ) , & [ Token :: Str ( SK_STR ) ] ) ;
2053
2142
assert_tokens ( & sk. readable ( ) , & [ Token :: String ( SK_STR ) ] ) ;
2054
2143
}
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
+ }
2055
2290
}
0 commit comments