From fe504ac71e330d715997e348e1cb5867c0a3df86 Mon Sep 17 00:00:00 2001 From: Denis Varlakov Date: Thu, 8 Feb 2024 14:30:35 +0100 Subject: [PATCH 1/2] Add `serde` support --- Cargo.lock | 106 +++++++++++++++++++++++++++++++++++++++++++++++++++++ Cargo.toml | 3 ++ src/lib.rs | 44 ++++++++++++++++++++++ 3 files changed, 153 insertions(+) diff --git a/Cargo.lock b/Cargo.lock index 82a66b6..9ff229c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -72,6 +72,41 @@ dependencies = [ "typenum", ] +[[package]] +name = "darling" +version = "0.20.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc5d6b04b3fd0ba9926f945895de7d806260a2d7431ba82e7edaecb043c4c6b8" +dependencies = [ + "darling_core", + "darling_macro", +] + +[[package]] +name = "darling_core" +version = "0.20.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04e48a959bcd5c761246f5d090ebc2fbf7b9cd527a492b07a67510c108f1e7e3" +dependencies = [ + "fnv", + "ident_case", + "proc-macro2", + "quote", + "strsim", + "syn 2.0.41", +] + +[[package]] +name = "darling_macro" +version = "0.20.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d1545d67a2149e1d93b7e5c7752dce5a7426eb5d1357ddcfd89336b94444f77" +dependencies = [ + "darling_core", + "quote", + "syn 2.0.41", +] + [[package]] name = "der" version = "0.7.8" @@ -164,6 +199,12 @@ dependencies = [ "subtle", ] +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + [[package]] name = "generic-array" version = "0.14.7" @@ -184,8 +225,11 @@ dependencies = [ "generic-ec-core", "generic-ec-curves", "getrandom", + "hex", "phantom-type", "rand_core", + "serde", + "serde_with", "subtle", "zeroize", ] @@ -198,6 +242,7 @@ checksum = "1193740c17f0324ea5d7db0635230f7538e5d33e0f9732af92d3f9fd4b87663e" dependencies = [ "generic-array", "rand_core", + "serde", "subtle", "zeroize", ] @@ -241,6 +286,12 @@ dependencies = [ "subtle", ] +[[package]] +name = "hex" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" + [[package]] name = "hex-literal" version = "0.4.1" @@ -256,6 +307,12 @@ dependencies = [ "digest", ] +[[package]] +name = "ident_case" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" + [[package]] name = "k256" version = "0.13.2" @@ -412,6 +469,48 @@ dependencies = [ "zeroize", ] +[[package]] +name = "serde" +version = "1.0.193" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25dd9975e68d0cb5aa1120c288333fc98731bd1dd12f561e468ea4728c042b89" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.193" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43576ca501357b9b071ac53cdc7da8ef0cbd9493d8df094cd821777ea6e894d3" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.41", +] + +[[package]] +name = "serde_with" +version = "2.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07ff71d2c147a7b57362cead5e22f772cd52f6ab31cfcd9edcd7f6aeb2a0afbe" +dependencies = [ + "serde", + "serde_with_macros", +] + +[[package]] +name = "serde_with_macros" +version = "2.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "881b6f881b17d13214e5d494c939ebab463d01264ce1811e9d4ac3a882e7695f" +dependencies = [ + "darling", + "proc-macro2", + "quote", + "syn 2.0.41", +] + [[package]] name = "sha2" version = "0.10.8" @@ -441,6 +540,7 @@ dependencies = [ "generic-ec", "hex-literal", "hmac", + "serde", "sha2", "subtle", ] @@ -455,6 +555,12 @@ dependencies = [ "der", ] +[[package]] +name = "strsim" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" + [[package]] name = "subtle" version = "2.5.0" diff --git a/Cargo.toml b/Cargo.toml index c25a2ae..e036bd0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -13,6 +13,8 @@ sha2 = { version = "0.10", default-features = false } subtle = { version = "2", default-features = false } generic-array = "0.14" +serde = { version = "1", default-features = false, features = ["derive"], optional = true } + [dev-dependencies] hex-literal = "0.4" @@ -21,6 +23,7 @@ std = [] curve-secp256k1 = ["generic-ec/curve-secp256k1"] curve-secp256r1 = ["generic-ec/curve-secp256r1"] all-curves = ["curve-secp256k1", "curve-secp256r1"] +serde = ["dep:serde", "generic-ec/serde"] [[test]] name = "test_vectors" diff --git a/src/lib.rs b/src/lib.rs index 4002c39..aa9b1f9 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -86,6 +86,8 @@ pub const H: u32 = 1 << 31; /// Child index, whether hardened or not #[derive(Clone, Copy, Debug)] +#[cfg_attr(feature = "serde", derive(serde::Serialize), serde(into = "u32"))] +#[cfg_attr(feature = "serde", derive(serde::Deserialize), serde(from = "u32"))] pub enum ChildIndex { /// Hardened index Hardened(HardenedIndex), @@ -95,14 +97,23 @@ pub enum ChildIndex { /// Child index in range $2^{31} \le i < 2^{32}$ corresponing to a hardened wallet #[derive(Clone, Copy, Debug)] +#[cfg_attr(feature = "serde", derive(serde::Serialize), serde(into = "u32"))] +#[cfg_attr(feature = "serde", derive(serde::Deserialize), serde(try_from = "u32"))] pub struct HardenedIndex(u32); /// Child index in range $0 \le i < 2^{31}$ corresponing to a non-hardened wallet #[derive(Clone, Copy, Debug)] +#[cfg_attr(feature = "serde", derive(serde::Serialize), serde(into = "u32"))] +#[cfg_attr(feature = "serde", derive(serde::Deserialize), serde(try_from = "u32"))] pub struct NonHardenedIndex(u32); /// Extended public key #[derive(Clone, Copy, Debug)] +#[cfg_attr( + feature = "serde", + derive(serde::Serialize, serde::Deserialize), + serde(bound = "") +)] pub struct ExtendedPublicKey { /// The public key that can be used for signature verification pub public_key: Point, @@ -112,6 +123,11 @@ pub struct ExtendedPublicKey { /// Extended secret key #[derive(Clone, Debug)] +#[cfg_attr( + feature = "serde", + derive(serde::Serialize, serde::Deserialize), + serde(bound = "") +)] pub struct ExtendedSecretKey { /// The secret key that can be used for signing pub secret_key: SecretScalar, @@ -121,6 +137,11 @@ pub struct ExtendedSecretKey { /// Pair of extended secret and public keys #[derive(Clone, Debug)] +#[cfg_attr( + feature = "serde", + derive(serde::Serialize, serde::Deserialize), + serde(bound = "") +)] pub struct ExtendedKeyPair { public_key: ExtendedPublicKey, secret_key: ExtendedSecretKey, @@ -131,6 +152,11 @@ pub struct ExtendedKeyPair { /// It contains an already derived child public key as it needs to be derived /// in process of calculating the shift value #[derive(Clone, Copy, Debug)] +#[cfg_attr( + feature = "serde", + derive(serde::Serialize, serde::Deserialize), + serde(bound = "") +)] pub struct DerivedShift { /// Derived shift pub shift: Scalar, @@ -200,6 +226,24 @@ impl TryFrom for NonHardenedIndex { } } } +impl From for u32 { + fn from(value: ChildIndex) -> Self { + match value { + ChildIndex::Hardened(v) => v.0, + ChildIndex::NonHardened(v) => v.0, + } + } +} +impl From for u32 { + fn from(value: HardenedIndex) -> Self { + value.0 + } +} +impl From for u32 { + fn from(value: NonHardenedIndex) -> Self { + value.0 + } +} impl core::str::FromStr for ChildIndex { type Err = core::num::ParseIntError; fn from_str(s: &str) -> Result { From 2c5658732fd4e3a3e9037e9b4e4a216924098af9 Mon Sep 17 00:00:00 2001 From: Denis Varlakov Date: Tue, 13 Feb 2024 08:47:19 +0100 Subject: [PATCH 2/2] Change serde implementation for key pair --- src/lib.rs | 26 +++++++++++++++++++++----- 1 file changed, 21 insertions(+), 5 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index aa9b1f9..a025815 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -137,11 +137,6 @@ pub struct ExtendedSecretKey { /// Pair of extended secret and public keys #[derive(Clone, Debug)] -#[cfg_attr( - feature = "serde", - derive(serde::Serialize, serde::Deserialize), - serde(bound = "") -)] pub struct ExtendedKeyPair { public_key: ExtendedPublicKey, secret_key: ExtendedSecretKey, @@ -305,6 +300,27 @@ impl ExtendedKeyPair { } } +#[cfg(feature = "serde")] +impl serde::Serialize for ExtendedKeyPair { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + self.secret_key.serialize(serializer) + } +} + +#[cfg(feature = "serde")] +impl<'de, E: Curve> serde::Deserialize<'de> for ExtendedKeyPair { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + let secret_key = ExtendedSecretKey::::deserialize(deserializer)?; + Ok(secret_key.into()) + } +} + /// Marker for a curve supported by SLIP10 specs and this library /// /// Only implement this trait for the curves that are supported by SLIP10 specs.