@@ -511,6 +511,18 @@ impl Ord for PublicKey {
511
511
}
512
512
513
513
/// Opaque data structure that holds a keypair consisting of a secret and a public key.
514
+ ///
515
+ /// # Serde support
516
+ /// [`Serialize`] and [`Deserialize`] are not implemented for this type, even with the `serde`
517
+ /// feature active. This is due to security considerations, see the [`serde_keypair`] documentation
518
+ /// for details.
519
+ ///
520
+ /// If the `serde` and `global-context[-less-secure]` features are active `KeyPair`s can be serialized and
521
+ /// deserialized by annotating them with `#[serde(with = "secp256k1::serde_keypair")]`
522
+ /// inside structs or enums for which [`Serialize`] and [`Deserialize`] are being derived.
523
+ ///
524
+ /// [`Deserialize`]: serde::Deserialize
525
+ /// [`Serialize`]: serde::Serialize
514
526
// Should secrets implement Copy: https://github.com/rust-bitcoin/rust-secp256k1/issues/363
515
527
#[ derive( Copy , Clone , PartialEq , Eq , PartialOrd , Ord , Hash ) ]
516
528
pub struct KeyPair ( ffi:: KeyPair ) ;
@@ -1031,6 +1043,45 @@ impl<'de> ::serde::Deserialize<'de> for XOnlyPublicKey {
1031
1043
}
1032
1044
}
1033
1045
1046
+ /// Serde implementation for the [`KeyPair`] type.
1047
+ ///
1048
+ /// Only the secret key part of the [`KeyPair`] is serialized using the [`SecretKey`] serde
1049
+ /// implementation, meaning the public key has to be regenerated on deserialization.
1050
+ ///
1051
+ /// **Attention:** The deserialization algorithm uses the [global context] to generate the public key
1052
+ /// belonging to the secret key to form a [`KeyPair`]. The typical caveats regarding use of the
1053
+ /// [global context] with secret data apply.
1054
+ ///
1055
+ /// [`SecretKey`]: crate::SecretKey
1056
+ /// [global context]: crate::SECP256K1
1057
+ #[ cfg( all( feature = "global-context-less-secure" , feature = "serde" ) ) ]
1058
+ pub mod serde_keypair {
1059
+ use serde:: { Deserialize , Deserializer , Serialize , Serializer } ;
1060
+ use key:: KeyPair ;
1061
+ use key:: SecretKey ;
1062
+
1063
+ #[ allow( missing_docs) ]
1064
+ pub fn serialize < S > ( key : & KeyPair , serializer : S ) -> Result < S :: Ok , S :: Error >
1065
+ where
1066
+ S : Serializer ,
1067
+ {
1068
+ SecretKey :: from_keypair ( key) . serialize ( serializer)
1069
+ }
1070
+
1071
+ #[ allow( missing_docs) ]
1072
+ pub fn deserialize < ' de , D > ( deserializer : D ) -> Result < KeyPair , D :: Error >
1073
+ where
1074
+ D : Deserializer < ' de > ,
1075
+ {
1076
+ let secret_key = SecretKey :: deserialize ( deserializer) ?;
1077
+
1078
+ Ok ( KeyPair :: from_secret_key (
1079
+ & crate :: SECP256K1 ,
1080
+ secret_key,
1081
+ ) )
1082
+ }
1083
+ }
1084
+
1034
1085
#[ cfg( test) ]
1035
1086
mod test {
1036
1087
use super :: * ;
@@ -1582,4 +1633,51 @@ mod test {
1582
1633
assert_eq ! ( pk1. serialize( ) [ ..] , kpk1. serialize( ) [ 1 ..] ) ;
1583
1634
assert_eq ! ( pk2. serialize( ) [ ..] , kpk2. serialize( ) [ 1 ..] ) ;
1584
1635
}
1636
+
1637
+ #[ test]
1638
+ #[ cfg( all( feature = "global-context-less-secure" , feature = "serde" ) ) ]
1639
+ fn test_serde_keypair ( ) {
1640
+ use serde:: { Deserialize , Deserializer , Serialize , Serializer } ;
1641
+ use serde_test:: { Configure , Token , assert_tokens} ;
1642
+ use super :: serde_keypair;
1643
+ use key:: KeyPair ;
1644
+
1645
+ // Normally users would derive the serde traits, but we can't easily enable the serde macros
1646
+ // here, so they are implemented manually to be able to test the behaviour.
1647
+ #[ derive( Debug , Copy , Clone , Eq , PartialEq ) ]
1648
+ struct KeyPairWrapper ( KeyPair ) ;
1649
+
1650
+ impl < ' de > Deserialize < ' de > for KeyPairWrapper {
1651
+ fn deserialize < D > ( deserializer : D ) -> Result < Self , D :: Error >
1652
+ where D : Deserializer < ' de > {
1653
+ serde_keypair:: deserialize ( deserializer) . map ( KeyPairWrapper )
1654
+ }
1655
+ }
1656
+
1657
+ impl Serialize for KeyPairWrapper {
1658
+ fn serialize < S > ( & self , serializer : S ) -> Result < S :: Ok , S :: Error > where S : Serializer {
1659
+ serde_keypair:: serialize ( & self . 0 , serializer)
1660
+ }
1661
+ }
1662
+
1663
+ static SK_BYTES : [ u8 ; 32 ] = [
1664
+ 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 ,
1665
+ 0 , 1 , 2 , 3 , 4 , 5 , 6 , 7 ,
1666
+ 0xff , 0xff , 0 , 0 , 0xff , 0xff , 0 , 0 ,
1667
+ 99 , 99 , 99 , 99 , 99 , 99 , 99 , 99
1668
+ ] ;
1669
+ static SK_STR : & ' static str = "\
1670
+ 01010101010101010001020304050607ffff0000ffff00006363636363636363\
1671
+ ";
1672
+
1673
+ let sk = KeyPairWrapper ( KeyPair :: from_seckey_slice ( & crate :: SECP256K1 , & SK_BYTES ) . unwrap ( ) ) ;
1674
+
1675
+ assert_tokens ( & sk. compact ( ) , & [ Token :: BorrowedBytes ( & SK_BYTES [ ..] ) ] ) ;
1676
+ assert_tokens ( & sk. compact ( ) , & [ Token :: Bytes ( & SK_BYTES ) ] ) ;
1677
+ assert_tokens ( & sk. compact ( ) , & [ Token :: ByteBuf ( & SK_BYTES ) ] ) ;
1678
+
1679
+ assert_tokens ( & sk. readable ( ) , & [ Token :: BorrowedStr ( SK_STR ) ] ) ;
1680
+ assert_tokens ( & sk. readable ( ) , & [ Token :: Str ( SK_STR ) ] ) ;
1681
+ assert_tokens ( & sk. readable ( ) , & [ Token :: String ( SK_STR ) ] ) ;
1682
+ }
1585
1683
}
0 commit comments