Skip to content

Commit ed63126

Browse files
authored
Add timing-resistant-secret-traits feature for PartialEq/Hash (#232)
Derived implementations of `PartialEq` and `Hash` are susceptible to timing side channels that make them unsuitable for secret types. This change introduces timing-safe implementations of `PartialEq` and `Hash` to all secret types that compare/hash, respectively, the SHA-256 hash of the secret rather than the secret itself. Because these implementations are significantly more computationally expensive than ordinary `PartialEq` and `Hash` implementations, they're behind a non-default `timing-resistant-secret-traits` feature flag.
1 parent 8e66503 commit ed63126

File tree

2 files changed

+19
-0
lines changed

2 files changed

+19
-0
lines changed

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ default = ["reqwest", "rustls-tls"]
1919
pkce-plain = []
2020
native-tls = ["reqwest/native-tls"]
2121
rustls-tls = ["reqwest/rustls-tls"]
22+
timing-resistant-secret-traits = []
2223

2324
[dependencies]
2425
base64 = "0.13"

src/types.rs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
use std::convert::Into;
22
use std::fmt::Error as FormatterError;
33
use std::fmt::{Debug, Formatter};
4+
#[cfg(feature = "timing-resistant-secret-traits")]
5+
use std::hash::{Hash, Hasher};
46
use std::ops::Deref;
57

68
use rand::{thread_rng, Rng};
@@ -148,6 +150,7 @@ macro_rules! new_secret_type {
148150
$(
149151
#[$attr]
150152
)*
153+
#[cfg_attr(feature = "timing-resistant-secret-traits", derive(Eq))]
151154
pub struct $name($type);
152155
impl $name {
153156
$($item)*
@@ -170,6 +173,21 @@ macro_rules! new_secret_type {
170173
write!(f, concat!(stringify!($name), "([redacted])"))
171174
}
172175
}
176+
177+
#[cfg(feature = "timing-resistant-secret-traits")]
178+
impl PartialEq for $name {
179+
fn eq(&self, other: &Self) -> bool {
180+
Sha256::digest(&self.0) == Sha256::digest(&other.0)
181+
}
182+
}
183+
184+
#[cfg(feature = "timing-resistant-secret-traits")]
185+
impl Hash for $name {
186+
fn hash<H: Hasher>(&self, state: &mut H) {
187+
Sha256::digest(&self.0).hash(state)
188+
}
189+
}
190+
173191
};
174192
}
175193

0 commit comments

Comments
 (0)