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