From 674ceb54c8c7a61fa076dc40dac87854ce9496d2 Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Tue, 30 Nov 2021 23:24:50 +0000 Subject: [PATCH 1/2] `impl ConstantTimeEq for {Extended}SpendingKey` --- src/keys.rs | 6 ++++++ src/zip32.rs | 11 +++++++++++ 2 files changed, 17 insertions(+) diff --git a/src/keys.rs b/src/keys.rs index 1f25df6c..0ea88c4c 100644 --- a/src/keys.rs +++ b/src/keys.rs @@ -35,6 +35,12 @@ const ZIP32_PURPOSE: u32 = 32; #[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)] pub struct SpendingKey([u8; 32]); +impl ConstantTimeEq for SpendingKey { + fn ct_eq(&self, other: &Self) -> Choice { + self.to_bytes().ct_eq(other.to_bytes()) + } +} + impl SpendingKey { /// Generates a random spending key. /// diff --git a/src/zip32.rs b/src/zip32.rs index d6a6db8c..7ebafc7e 100644 --- a/src/zip32.rs +++ b/src/zip32.rs @@ -6,6 +6,7 @@ use std::{ }; use blake2b_simd::Params as Blake2bParams; +use subtle::{Choice, ConstantTimeEq}; use crate::{ keys::{FullViewingKey, SpendingKey}, @@ -101,6 +102,16 @@ pub(crate) struct ExtendedSpendingKey { sk: SpendingKey, } +impl ConstantTimeEq for ExtendedSpendingKey { + fn ct_eq(&self, rhs: &Self) -> Choice { + self.depth.ct_eq(&rhs.depth) + & self.parent_fvk_tag.0.ct_eq(&rhs.parent_fvk_tag.0) + & self.child_index.0.ct_eq(&rhs.child_index.0) + & self.chain_code.0.ct_eq(&rhs.chain_code.0) + & self.sk.ct_eq(&rhs.sk) + } +} + impl std::cmp::PartialEq for ExtendedSpendingKey { fn eq(&self, rhs: &ExtendedSpendingKey) -> bool { self.depth == rhs.depth From 37f1bba99813e91a51af25fc01104d00f58037f5 Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Tue, 30 Nov 2021 23:25:35 +0000 Subject: [PATCH 2/2] Remove `PartialEq, PartialOrd` impls from `{Extended}SpendingKey` --- src/keys.rs | 2 +- src/zip32.rs | 27 +++++++++------------------ 2 files changed, 10 insertions(+), 19 deletions(-) diff --git a/src/keys.rs b/src/keys.rs index 0ea88c4c..2c9d7b34 100644 --- a/src/keys.rs +++ b/src/keys.rs @@ -32,7 +32,7 @@ const ZIP32_PURPOSE: u32 = 32; /// Defined in [Zcash Protocol Spec ยง 4.2.3: Orchard Key Components][orchardkeycomponents]. /// /// [orchardkeycomponents]: https://zips.z.cash/protocol/nu5.pdf#orchardkeycomponents -#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)] +#[derive(Debug, Copy, Clone)] pub struct SpendingKey([u8; 32]); impl ConstantTimeEq for SpendingKey { diff --git a/src/zip32.rs b/src/zip32.rs index 7ebafc7e..31b9ef7c 100644 --- a/src/zip32.rs +++ b/src/zip32.rs @@ -112,16 +112,6 @@ impl ConstantTimeEq for ExtendedSpendingKey { } } -impl std::cmp::PartialEq for ExtendedSpendingKey { - fn eq(&self, rhs: &ExtendedSpendingKey) -> bool { - self.depth == rhs.depth - && self.parent_fvk_tag == rhs.parent_fvk_tag - && self.child_index == rhs.child_index - && self.chain_code == rhs.chain_code - && self.sk == rhs.sk - } -} - #[allow(non_snake_case)] impl ExtendedSpendingKey { /// Returns the spending key of the child key corresponding to @@ -240,16 +230,17 @@ mod tests { let xsk_m = ExtendedSpendingKey::master(&seed).unwrap(); let xsk_5h = xsk_m.derive_child(5.try_into().unwrap()).unwrap(); - assert_eq!( - ExtendedSpendingKey::from_path(&seed, &[5.try_into().unwrap()]).unwrap(), - xsk_5h - ); + assert!(bool::from( + ExtendedSpendingKey::from_path(&seed, &[5.try_into().unwrap()]) + .unwrap() + .ct_eq(&xsk_5h) + )); let xsk_5h_7 = xsk_5h.derive_child(7.try_into().unwrap()).unwrap(); - assert_eq!( + assert!(bool::from( ExtendedSpendingKey::from_path(&seed, &[5.try_into().unwrap(), 7.try_into().unwrap()]) - .unwrap(), - xsk_5h_7 - ); + .unwrap() + .ct_eq(&xsk_5h_7) + )); } }