@@ -76,6 +76,18 @@ impl str::FromStr for Signature {
76
76
}
77
77
78
78
/// Opaque data structure that holds a keypair consisting of a secret and a public key.
79
+ ///
80
+ /// # Serde support
81
+ /// [`Serialize`] and [`Deserialize`] are not implemented for this type, even with the `serde`
82
+ /// feature active. This is due to security considerations, see the [`serde_keypair`] documentation
83
+ /// for details.
84
+ ///
85
+ /// If the `serde` and `global-context[-less-secure]` features are active `KeyPair`s can be serialized and
86
+ /// deserialized by annotating them with `#[serde(with = "secp256k1::schnorrsig::serde_keypair")]`
87
+ /// inside structs or enums for which [`Serialize`] and [`Deserialize`] are being derived.
88
+ ///
89
+ /// [`Deserialize`]: serde::Deserialize
90
+ /// [`Serialize`]: serde::Serialize
79
91
#[ derive( Copy , Clone , PartialEq , Eq , Debug , PartialOrd , Ord , Hash ) ]
80
92
pub struct KeyPair ( ffi:: KeyPair ) ;
81
93
@@ -596,6 +608,45 @@ impl<C: Signing> Secp256k1<C> {
596
608
}
597
609
}
598
610
611
+ /// Serde implementation for the [`KeyPair`] type.
612
+ ///
613
+ /// Only the secret key part of the [`KeyPair`] is serialized using the [`SecretKey`] serde
614
+ /// implementation, meaning the public key has to be regenerated on deserialization.
615
+ ///
616
+ /// **Attention:** The deserialization algorithm uses the [global context] to generate the public key
617
+ /// belonging to the secret key to form a [`KeyPair`]. The typical caveats regarding use of the
618
+ /// [global context] with secret data apply.
619
+ ///
620
+ /// [`SecretKey`]: crate::SecretKey
621
+ /// [global context]: crate::SECP256K1
622
+ #[ cfg( all( feature = "global-context-less-secure" , feature = "serde" ) ) ]
623
+ pub mod serde_keypair {
624
+ use serde:: { Deserialize , Deserializer , Serialize , Serializer } ;
625
+ use schnorrsig:: KeyPair ;
626
+ use SecretKey ;
627
+
628
+ #[ allow( missing_docs) ]
629
+ pub fn serialize < S > ( key : & KeyPair , serializer : S ) -> Result < S :: Ok , S :: Error >
630
+ where
631
+ S : Serializer ,
632
+ {
633
+ SecretKey :: from_keypair ( key) . serialize ( serializer)
634
+ }
635
+
636
+ #[ allow( missing_docs) ]
637
+ pub fn deserialize < ' de , D > ( deserializer : D ) -> Result < KeyPair , D :: Error >
638
+ where
639
+ D : Deserializer < ' de > ,
640
+ {
641
+ let secret_key = SecretKey :: deserialize ( deserializer) ?;
642
+
643
+ Ok ( KeyPair :: from_secret_key (
644
+ & crate :: SECP256K1 ,
645
+ secret_key,
646
+ ) )
647
+ }
648
+ }
649
+
599
650
#[ cfg( test) ]
600
651
mod tests {
601
652
use super :: super :: Error :: InvalidPublicKey ;
@@ -935,4 +986,50 @@ mod tests {
935
986
assert_eq ! ( pk1. serialize( ) [ ..] , kpk1. serialize( ) [ 1 ..] ) ;
936
987
assert_eq ! ( pk2. serialize( ) [ ..] , kpk2. serialize( ) [ 1 ..] ) ;
937
988
}
989
+
990
+ #[ test]
991
+ #[ cfg( all( feature = "global-context-less-secure" , feature = "serde" ) ) ]
992
+ fn test_serde_keypair ( ) {
993
+ use serde:: { Deserialize , Deserializer , Serialize , Serializer } ;
994
+ use serde_test:: { Configure , Token , assert_tokens} ;
995
+ use super :: serde_keypair;
996
+
997
+ // Normally users would derive the serde traits, but we can't easily enable the serde macros
998
+ // here, so they are implemented manually to be able to test the behaviour.
999
+ #[ derive( Debug , Copy , Clone , Eq , PartialEq ) ]
1000
+ struct KeyPairWrapper ( KeyPair ) ;
1001
+
1002
+ impl < ' de > Deserialize < ' de > for KeyPairWrapper {
1003
+ fn deserialize < D > ( deserializer : D ) -> Result < Self , D :: Error >
1004
+ where D : Deserializer < ' de > {
1005
+ serde_keypair:: deserialize ( deserializer) . map ( KeyPairWrapper )
1006
+ }
1007
+ }
1008
+
1009
+ impl Serialize for KeyPairWrapper {
1010
+ fn serialize < S > ( & self , serializer : S ) -> Result < S :: Ok , S :: Error > where S : Serializer {
1011
+ serde_keypair:: serialize ( & self . 0 , serializer)
1012
+ }
1013
+ }
1014
+
1015
+ static SK_BYTES : [ u8 ; 32 ] = [
1016
+ 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 ,
1017
+ 0 , 1 , 2 , 3 , 4 , 5 , 6 , 7 ,
1018
+ 0xff , 0xff , 0 , 0 , 0xff , 0xff , 0 , 0 ,
1019
+ 99 , 99 , 99 , 99 , 99 , 99 , 99 , 99
1020
+ ] ;
1021
+ static SK_STR : & ' static str = "\
1022
+ 01010101010101010001020304050607ffff0000ffff00006363636363636363\
1023
+ ";
1024
+
1025
+ let sk = KeyPairWrapper ( KeyPair :: from_seckey_slice ( & crate :: SECP256K1 , & SK_BYTES ) . unwrap ( ) ) ;
1026
+
1027
+ assert_tokens ( & sk. compact ( ) , & [ Token :: BorrowedBytes ( & SK_BYTES [ ..] ) ] ) ;
1028
+ assert_tokens ( & sk. compact ( ) , & [ Token :: Bytes ( & SK_BYTES ) ] ) ;
1029
+ assert_tokens ( & sk. compact ( ) , & [ Token :: ByteBuf ( & SK_BYTES ) ] ) ;
1030
+
1031
+ assert_tokens ( & sk. readable ( ) , & [ Token :: BorrowedStr ( SK_STR ) ] ) ;
1032
+ assert_tokens ( & sk. readable ( ) , & [ Token :: Str ( SK_STR ) ] ) ;
1033
+ assert_tokens ( & sk. readable ( ) , & [ Token :: String ( SK_STR ) ] ) ;
1034
+ }
938
1035
}
0 commit comments