Skip to main content

reddb_server/crypto/
const_time.rs

1//! Constant-time byte-slice comparison.
2//!
3//! Defends against timing oracles when comparing secrets (auth
4//! tokens, MAC tags, password hashes). Returns `false` if the
5//! lengths differ without leaking which prefix matched. Centralised
6//! so every site that compares secret material uses the same
7//! audited routine.
8
9#[inline]
10pub fn constant_time_eq(a: &[u8], b: &[u8]) -> bool {
11    if a.len() != b.len() {
12        return false;
13    }
14    let mut diff = 0u8;
15    for (x, y) in a.iter().zip(b.iter()) {
16        diff |= x ^ y;
17    }
18    diff == 0
19}
20
21#[cfg(test)]
22mod tests {
23    use super::*;
24
25    #[test]
26    fn equal_slices_match() {
27        assert!(constant_time_eq(b"hello", b"hello"));
28    }
29
30    #[test]
31    fn different_content_fails() {
32        assert!(!constant_time_eq(b"hello", b"world"));
33    }
34
35    #[test]
36    fn different_lengths_fail_without_panic() {
37        assert!(!constant_time_eq(b"x", b"xx"));
38        assert!(!constant_time_eq(b"", b"x"));
39    }
40
41    #[test]
42    fn empty_slices_match() {
43        assert!(constant_time_eq(b"", b""));
44    }
45}