@@ -25,6 +25,9 @@ use crate::Error::{self, InvalidPublicKey, InvalidPublicKeySum, InvalidSecretKey
2525use crate :: ffi:: { self , CPtr , impl_array_newtype} ;
2626use crate :: ffi:: types:: c_uint;
2727
28+ #[ cfg( feature = "serde" ) ]
29+ use serde:: ser:: SerializeTuple ;
30+
2831#[ cfg( feature = "global-context" ) ]
2932use crate :: { Message , ecdsa, SECP256K1 } ;
3033#[ cfg( all( feature = "global-context" , feature = "rand-std" ) ) ]
@@ -33,6 +36,12 @@ use crate::Scalar;
3336
3437/// Secret 256-bit key used as `x` in an ECDSA signature.
3538///
39+ /// # Serde support
40+ ///
41+ /// Implements de/serialization with the `serde` feature enabled. We treat the byte value as a tuple
42+ /// of 32 `u8`s for non-human-readable formats. This representation is optimal for for some formats
43+ /// (e.g. [`bincode`]) however other formats may be less optimal (e.g. [`cbor`]).
44+ ///
3645/// # Examples
3746///
3847/// Basic usage:
@@ -45,6 +54,8 @@ use crate::Scalar;
4554/// let secret_key = SecretKey::new(&mut rand::thread_rng());
4655/// # }
4756/// ```
57+ /// [`bincode`]: https://docs.rs/bincode
58+ /// [`cbor`]: https://docs.rs/cbor
4859pub struct SecretKey ( [ u8 ; constants:: SECRET_KEY_SIZE ] ) ;
4960impl_array_newtype ! ( SecretKey , u8 , constants:: SECRET_KEY_SIZE ) ;
5061impl_display_secret ! ( SecretKey ) ;
@@ -68,6 +79,12 @@ pub const ONE_KEY: SecretKey = SecretKey([0, 0, 0, 0, 0, 0, 0, 0,
6879
6980/// A Secp256k1 public key, used for verification of signatures.
7081///
82+ /// # Serde support
83+ ///
84+ /// Implements de/serialization with the `serde` feature enabled. We treat the byte value as a tuple
85+ /// of 33 `u8`s for non-human-readable formats. This representation is optimal for for some formats
86+ /// (e.g. [`bincode`]) however other formats may be less optimal (e.g. [`cbor`]).
87+ ///
7188/// # Examples
7289///
7390/// Basic usage:
@@ -81,6 +98,8 @@ pub const ONE_KEY: SecretKey = SecretKey([0, 0, 0, 0, 0, 0, 0, 0,
8198/// let public_key = PublicKey::from_secret_key(&secp, &secret_key);
8299/// # }
83100/// ```
101+ /// [`bincode`]: https://docs.rs/bincode
102+ /// [`cbor`]: https://docs.rs/cbor
84103#[ derive( Copy , Clone , PartialEq , Eq , Debug , Hash ) ]
85104#[ repr( transparent) ]
86105pub struct PublicKey ( ffi:: PublicKey ) ;
@@ -315,7 +334,11 @@ impl serde::Serialize for SecretKey {
315334 let mut buf = [ 0u8 ; constants:: SECRET_KEY_SIZE * 2 ] ;
316335 s. serialize_str ( crate :: to_hex ( & self . 0 , & mut buf) . expect ( "fixed-size hex serialization" ) )
317336 } else {
318- s. serialize_bytes ( & self [ ..] )
337+ let mut tuple = s. serialize_tuple ( constants:: SECRET_KEY_SIZE ) ?;
338+ for byte in self . 0 . iter ( ) {
339+ tuple. serialize_element ( byte) ?;
340+ }
341+ tuple. end ( )
319342 }
320343 }
321344}
@@ -329,10 +352,11 @@ impl<'de> serde::Deserialize<'de> for SecretKey {
329352 "a hex string representing 32 byte SecretKey"
330353 ) )
331354 } else {
332- d . deserialize_bytes ( super :: serde_util:: BytesVisitor :: new (
355+ let visitor = super :: serde_util:: Tuple32Visitor :: new (
333356 "raw 32 bytes SecretKey" ,
334357 SecretKey :: from_slice
335- ) )
358+ ) ;
359+ d. deserialize_tuple ( constants:: SECRET_KEY_SIZE , visitor)
336360 }
337361 }
338362}
@@ -649,7 +673,11 @@ impl serde::Serialize for PublicKey {
649673 if s. is_human_readable ( ) {
650674 s. collect_str ( self )
651675 } else {
652- s. serialize_bytes ( & self . serialize ( ) )
676+ let mut tuple = s. serialize_tuple ( constants:: PUBLIC_KEY_SIZE ) ?;
677+ for byte in self . serialize ( ) . iter ( ) { // Serialize in compressed form.
678+ tuple. serialize_element ( & byte) ?;
679+ }
680+ tuple. end ( )
653681 }
654682 }
655683}
@@ -663,10 +691,11 @@ impl<'de> serde::Deserialize<'de> for PublicKey {
663691 "an ASCII hex string representing a public key"
664692 ) )
665693 } else {
666- d . deserialize_bytes ( super :: serde_util:: BytesVisitor :: new (
667- "a bytestring representing a public key" ,
694+ let visitor = super :: serde_util:: Tuple33Visitor :: new (
695+ "33 bytes compressed public key" ,
668696 PublicKey :: from_slice
669- ) )
697+ ) ;
698+ d. deserialize_tuple ( constants:: PUBLIC_KEY_SIZE , visitor)
670699 }
671700 }
672701}
@@ -687,13 +716,10 @@ impl Ord for PublicKey {
687716///
688717/// # Serde support
689718///
690- /// [`Serialize`] and [`Deserialize`] are not implemented for this type, even with the `serde`
691- /// feature active. This is due to security considerations, see the [`serde_keypair`] documentation
692- /// for details.
693- ///
694- /// If the `serde` and `global-context` features are active `KeyPair`s can be serialized and
695- /// deserialized by annotating them with `#[serde(with = "secp256k1::serde_keypair")]`
696- /// inside structs or enums for which [`Serialize`] and [`Deserialize`] are being derived.
719+ /// Implements de/serialization with the `serde` and_`global-context` features enabled. Serializes
720+ /// the secret bytes only. We treat the byte value as a tuple of 32 `u8`s for non-human-readable
721+ /// formats. This representation is optimal for for some formats (e.g. [`bincode`]) however other
722+ /// formats may be less optimal (e.g. [`cbor`]). For human-readable formats we use a hex string.
697723///
698724/// # Examples
699725///
@@ -708,8 +734,8 @@ impl Ord for PublicKey {
708734/// let key_pair = KeyPair::from_secret_key(&secp, &secret_key);
709735/// # }
710736/// ```
711- /// [`Deserialize `]: serde::Deserialize
712- /// [`Serialize `]: serde::Serialize
737+ /// [`bincode `]: https://docs.rs/bincode
738+ /// [`cbor `]: https://docs.rs/cbor
713739#[ derive( Copy , Clone , PartialEq , Eq , PartialOrd , Ord , Hash ) ]
714740pub struct KeyPair ( ffi:: KeyPair ) ;
715741impl_display_secret ! ( KeyPair ) ;
@@ -966,7 +992,11 @@ impl serde::Serialize for KeyPair {
966992 s. serialize_str ( crate :: to_hex ( & self . secret_bytes ( ) , & mut buf)
967993 . expect ( "fixed-size hex serialization" ) )
968994 } else {
969- s. serialize_bytes ( & self . 0 [ ..] )
995+ let mut tuple = s. serialize_tuple ( constants:: SECRET_KEY_SIZE ) ?;
996+ for byte in self . secret_bytes ( ) . iter ( ) {
997+ tuple. serialize_element ( & byte) ?;
998+ }
999+ tuple. end ( )
9701000 }
9711001 }
9721002}
@@ -980,19 +1010,26 @@ impl<'de> serde::Deserialize<'de> for KeyPair {
9801010 "a hex string representing 32 byte KeyPair"
9811011 ) )
9821012 } else {
983- d . deserialize_bytes ( super :: serde_util:: BytesVisitor :: new (
1013+ let visitor = super :: serde_util:: Tuple32Visitor :: new (
9841014 "raw 32 bytes KeyPair" ,
9851015 |data| unsafe {
9861016 let ctx = Secp256k1 :: from_raw_all ( ffi:: secp256k1_context_no_precomp as * mut ffi:: Context ) ;
9871017 KeyPair :: from_seckey_slice ( & ctx, data)
9881018 }
989- ) )
1019+ ) ;
1020+ d. deserialize_tuple ( constants:: SECRET_KEY_SIZE , visitor)
9901021 }
9911022 }
9921023}
9931024
9941025/// An x-only public key, used for verification of Schnorr signatures and serialized according to BIP-340.
9951026///
1027+ /// # Serde support
1028+ ///
1029+ /// Implements de/serialization with the `serde` feature enabled. We treat the byte value as a tuple
1030+ /// of 32 `u8`s for non-human-readable formats. This representation is optimal for for some formats
1031+ /// (e.g. [`bincode`]) however other formats may be less optimal (e.g. [`cbor`]).
1032+ ///
9961033/// # Examples
9971034///
9981035/// Basic usage:
@@ -1006,6 +1043,8 @@ impl<'de> serde::Deserialize<'de> for KeyPair {
10061043/// let xonly = XOnlyPublicKey::from_keypair(&key_pair);
10071044/// # }
10081045/// ```
1046+ /// [`bincode`]: https://docs.rs/bincode
1047+ /// [`cbor`]: https://docs.rs/cbor
10091048#[ derive( Copy , Clone , PartialEq , Eq , Debug , PartialOrd , Ord , Hash ) ]
10101049pub struct XOnlyPublicKey ( ffi:: XOnlyPublicKey ) ;
10111050
@@ -1429,7 +1468,11 @@ impl serde::Serialize for XOnlyPublicKey {
14291468 if s. is_human_readable ( ) {
14301469 s. collect_str ( self )
14311470 } else {
1432- s. serialize_bytes ( & self . serialize ( ) )
1471+ let mut tuple = s. serialize_tuple ( constants:: SCHNORR_PUBLIC_KEY_SIZE ) ?;
1472+ for byte in self . serialize ( ) . iter ( ) {
1473+ tuple. serialize_element ( & byte) ?;
1474+ }
1475+ tuple. end ( )
14331476 }
14341477 }
14351478}
@@ -1443,10 +1486,11 @@ impl<'de> serde::Deserialize<'de> for XOnlyPublicKey {
14431486 "a hex string representing 32 byte schnorr public key"
14441487 ) )
14451488 } else {
1446- d . deserialize_bytes ( super :: serde_util:: BytesVisitor :: new (
1489+ let visitor = super :: serde_util:: Tuple32Visitor :: new (
14471490 "raw 32 bytes schnorr public key" ,
14481491 XOnlyPublicKey :: from_slice
1449- ) )
1492+ ) ;
1493+ d. deserialize_tuple ( constants:: SCHNORR_PUBLIC_KEY_SIZE , visitor)
14501494 }
14511495 }
14521496}
@@ -1492,6 +1536,8 @@ pub mod serde_keypair {
14921536#[ cfg( test) ]
14931537#[ allow( unused_imports) ]
14941538mod test {
1539+ use super :: * ;
1540+
14951541 use core:: str:: FromStr ;
14961542
14971543 #[ cfg( any( feature = "alloc" , feature = "std" ) ) ]
@@ -1949,6 +1995,7 @@ mod test {
19491995 static SK_STR : & ' static str = "\
19501996 01010101010101010001020304050607ffff0000ffff00006363636363636363\
19511997 ";
1998+ #[ cfg( fuzzing) ]
19521999 static PK_BYTES : [ u8 ; 33 ] = [
19532000 0x02 ,
19542001 0x18 , 0x84 , 0x57 , 0x81 , 0xf6 , 0x31 , 0xc4 , 0x8f ,
@@ -1971,22 +2018,32 @@ mod test {
19712018 #[ cfg( fuzzing) ]
19722019 let pk = PublicKey :: from_slice ( & PK_BYTES ) . expect ( "pk" ) ;
19732020
1974- assert_tokens ( & sk. compact ( ) , & [ Token :: BorrowedBytes ( & SK_BYTES [ ..] ) ] ) ;
1975- assert_tokens ( & sk. compact ( ) , & [ Token :: Bytes ( & SK_BYTES ) ] ) ;
1976- assert_tokens ( & sk. compact ( ) , & [ Token :: ByteBuf ( & SK_BYTES ) ] ) ;
2021+ assert_tokens ( & sk. compact ( ) , & [
2022+ Token :: Tuple { len : 32 } ,
2023+ Token :: U8 ( 1 ) , Token :: U8 ( 1 ) , Token :: U8 ( 1 ) , Token :: U8 ( 1 ) , Token :: U8 ( 1 ) , Token :: U8 ( 1 ) , Token :: U8 ( 1 ) , Token :: U8 ( 1 ) ,
2024+ Token :: U8 ( 0 ) , Token :: U8 ( 1 ) , Token :: U8 ( 2 ) , Token :: U8 ( 3 ) , Token :: U8 ( 4 ) , Token :: U8 ( 5 ) , Token :: U8 ( 6 ) , Token :: U8 ( 7 ) ,
2025+ Token :: U8 ( 0xff ) , Token :: U8 ( 0xff ) , Token :: U8 ( 0 ) , Token :: U8 ( 0 ) , Token :: U8 ( 0xff ) , Token :: U8 ( 0xff ) , Token :: U8 ( 0 ) , Token :: U8 ( 0 ) ,
2026+ Token :: U8 ( 99 ) , Token :: U8 ( 99 ) , Token :: U8 ( 99 ) , Token :: U8 ( 99 ) , Token :: U8 ( 99 ) , Token :: U8 ( 99 ) , Token :: U8 ( 99 ) , Token :: U8 ( 99 ) ,
2027+ Token :: TupleEnd
2028+ ] ) ;
19772029
19782030 assert_tokens ( & sk. readable ( ) , & [ Token :: BorrowedStr ( SK_STR ) ] ) ;
19792031 assert_tokens ( & sk. readable ( ) , & [ Token :: Str ( SK_STR ) ] ) ;
19802032 assert_tokens ( & sk. readable ( ) , & [ Token :: String ( SK_STR ) ] ) ;
19812033
1982- assert_tokens ( & pk. compact ( ) , & [ Token :: BorrowedBytes ( & PK_BYTES [ ..] ) ] ) ;
1983- assert_tokens ( & pk. compact ( ) , & [ Token :: Bytes ( & PK_BYTES ) ] ) ;
1984- assert_tokens ( & pk. compact ( ) , & [ Token :: ByteBuf ( & PK_BYTES ) ] ) ;
2034+ assert_tokens ( & pk. compact ( ) , & [
2035+ Token :: Tuple { len : 33 } ,
2036+ Token :: U8 ( 0x02 ) ,
2037+ Token :: U8 ( 0x18 ) , Token :: U8 ( 0x84 ) , Token :: U8 ( 0x57 ) , Token :: U8 ( 0x81 ) , Token :: U8 ( 0xf6 ) , Token :: U8 ( 0x31 ) , Token :: U8 ( 0xc4 ) , Token :: U8 ( 0x8f ) ,
2038+ Token :: U8 ( 0x1c ) , Token :: U8 ( 0x97 ) , Token :: U8 ( 0x09 ) , Token :: U8 ( 0xe2 ) , Token :: U8 ( 0x30 ) , Token :: U8 ( 0x92 ) , Token :: U8 ( 0x06 ) , Token :: U8 ( 0x7d ) ,
2039+ Token :: U8 ( 0x06 ) , Token :: U8 ( 0x83 ) , Token :: U8 ( 0x7f ) , Token :: U8 ( 0x30 ) , Token :: U8 ( 0xaa ) , Token :: U8 ( 0x0c ) , Token :: U8 ( 0xd0 ) , Token :: U8 ( 0x54 ) ,
2040+ Token :: U8 ( 0x4a ) , Token :: U8 ( 0xc8 ) , Token :: U8 ( 0x87 ) , Token :: U8 ( 0xfe ) , Token :: U8 ( 0x91 ) , Token :: U8 ( 0xdd ) , Token :: U8 ( 0xd1 ) , Token :: U8 ( 0x66 ) ,
2041+ Token :: TupleEnd
2042+ ] ) ;
19852043
19862044 assert_tokens ( & pk. readable ( ) , & [ Token :: BorrowedStr ( PK_STR ) ] ) ;
19872045 assert_tokens ( & pk. readable ( ) , & [ Token :: Str ( PK_STR ) ] ) ;
19882046 assert_tokens ( & pk. readable ( ) , & [ Token :: String ( PK_STR ) ] ) ;
1989-
19902047 }
19912048
19922049 #[ test]
@@ -2066,10 +2123,14 @@ mod test {
20662123 ";
20672124
20682125 let sk = KeyPairWrapper ( KeyPair :: from_seckey_slice ( & crate :: SECP256K1 , & SK_BYTES ) . unwrap ( ) ) ;
2069-
2070- assert_tokens ( & sk. compact ( ) , & [ Token :: BorrowedBytes ( & SK_BYTES [ ..] ) ] ) ;
2071- assert_tokens ( & sk. compact ( ) , & [ Token :: Bytes ( & SK_BYTES ) ] ) ;
2072- assert_tokens ( & sk. compact ( ) , & [ Token :: ByteBuf ( & SK_BYTES ) ] ) ;
2126+ assert_tokens ( & sk. compact ( ) , & [
2127+ Token :: Tuple { len : 32 } ,
2128+ Token :: U8 ( 1 ) , Token :: U8 ( 1 ) , Token :: U8 ( 1 ) , Token :: U8 ( 1 ) , Token :: U8 ( 1 ) , Token :: U8 ( 1 ) , Token :: U8 ( 1 ) , Token :: U8 ( 1 ) ,
2129+ Token :: U8 ( 0 ) , Token :: U8 ( 1 ) , Token :: U8 ( 2 ) , Token :: U8 ( 3 ) , Token :: U8 ( 4 ) , Token :: U8 ( 5 ) , Token :: U8 ( 6 ) , Token :: U8 ( 7 ) ,
2130+ Token :: U8 ( 0xff ) , Token :: U8 ( 0xff ) , Token :: U8 ( 0 ) , Token :: U8 ( 0 ) , Token :: U8 ( 0xff ) , Token :: U8 ( 0xff ) , Token :: U8 ( 0 ) , Token :: U8 ( 0 ) ,
2131+ Token :: U8 ( 99 ) , Token :: U8 ( 99 ) , Token :: U8 ( 99 ) , Token :: U8 ( 99 ) , Token :: U8 ( 99 ) , Token :: U8 ( 99 ) , Token :: U8 ( 99 ) , Token :: U8 ( 99 ) ,
2132+ Token :: TupleEnd
2133+ ] ) ;
20732134
20742135 assert_tokens ( & sk. readable ( ) , & [ Token :: BorrowedStr ( SK_STR ) ] ) ;
20752136 assert_tokens ( & sk. readable ( ) , & [ Token :: Str ( SK_STR ) ] ) ;
@@ -2221,4 +2282,38 @@ mod test {
22212282
22222283 assert_eq ! ( got, want)
22232284 }
2285+
2286+ #[ test]
2287+ #[ cfg( not( fuzzing) ) ]
2288+ #[ cfg( all( feature = "global-context" , feature = "serde" ) ) ]
2289+ fn test_serde_x_only_pubkey ( ) {
2290+ use serde_test:: { Configure , Token , assert_tokens} ;
2291+
2292+ static SK_BYTES : [ u8 ; 32 ] = [
2293+ 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 ,
2294+ 0 , 1 , 2 , 3 , 4 , 5 , 6 , 7 ,
2295+ 0xff , 0xff , 0 , 0 , 0xff , 0xff , 0 , 0 ,
2296+ 99 , 99 , 99 , 99 , 99 , 99 , 99 , 99
2297+ ] ;
2298+
2299+ static PK_STR : & ' static str = "\
2300+ 18845781f631c48f1c9709e23092067d06837f30aa0cd0544ac887fe91ddd166\
2301+ ";
2302+
2303+ let kp = KeyPair :: from_seckey_slice ( & crate :: SECP256K1 , & SK_BYTES ) . unwrap ( ) ;
2304+ let ( pk, _parity) = XOnlyPublicKey :: from_keypair ( & kp) ;
2305+
2306+ assert_tokens ( & pk. compact ( ) , & [
2307+ Token :: Tuple { len : 32 } ,
2308+ Token :: U8 ( 0x18 ) , Token :: U8 ( 0x84 ) , Token :: U8 ( 0x57 ) , Token :: U8 ( 0x81 ) , Token :: U8 ( 0xf6 ) , Token :: U8 ( 0x31 ) , Token :: U8 ( 0xc4 ) , Token :: U8 ( 0x8f ) ,
2309+ Token :: U8 ( 0x1c ) , Token :: U8 ( 0x97 ) , Token :: U8 ( 0x09 ) , Token :: U8 ( 0xe2 ) , Token :: U8 ( 0x30 ) , Token :: U8 ( 0x92 ) , Token :: U8 ( 0x06 ) , Token :: U8 ( 0x7d ) ,
2310+ Token :: U8 ( 0x06 ) , Token :: U8 ( 0x83 ) , Token :: U8 ( 0x7f ) , Token :: U8 ( 0x30 ) , Token :: U8 ( 0xaa ) , Token :: U8 ( 0x0c ) , Token :: U8 ( 0xd0 ) , Token :: U8 ( 0x54 ) ,
2311+ Token :: U8 ( 0x4a ) , Token :: U8 ( 0xc8 ) , Token :: U8 ( 0x87 ) , Token :: U8 ( 0xfe ) , Token :: U8 ( 0x91 ) , Token :: U8 ( 0xdd ) , Token :: U8 ( 0xd1 ) , Token :: U8 ( 0x66 ) ,
2312+ Token :: TupleEnd
2313+ ] ) ;
2314+
2315+ assert_tokens ( & pk. readable ( ) , & [ Token :: BorrowedStr ( PK_STR ) ] ) ;
2316+ assert_tokens ( & pk. readable ( ) , & [ Token :: Str ( PK_STR ) ] ) ;
2317+ assert_tokens ( & pk. readable ( ) , & [ Token :: String ( PK_STR ) ] ) ;
2318+ }
22242319}
0 commit comments