Files
boxmaker/docs/plans/M4a/files/crates/proto/tests/sha1.rs
T
kyleandClaude Opus 5.5 0339dc13b2 Plan M4a: gatewayd in 15 tasks, with skeletons and given tests
Each task's tests were run against a reference at its end state; the end states were replayed
from master in order with the gate at each step (650 to 762 tests); each skeleton compiles
against its tests and fails them. The reference is kept off this machine. Lessons T27 (every
wait in a test has a limit) and T28 (mutate the reference before hand-over) come from this work.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-23 19:05:44 -07:00

79 lines
2.4 KiB
Rust

//! SHA-1 against FIPS 180 and RFC 3174 vectors, and against `sha1sum` for the lengths around the
//! 64-byte block where padding changes shape. Every case is also fed in pieces. Do not edit.
use proto::sha1::{Sha1, sha1};
fn hex(bytes: &[u8]) -> String {
bytes.iter().map(|b| format!("{b:02x}")).collect()
}
fn check(data: &[u8], want: &str) {
assert_eq!(hex(&sha1(data)), want, "whole, {} bytes", data.len());
for split in [
0,
1,
data.len() / 2,
data.len().saturating_sub(1),
data.len(),
] {
let split = split.min(data.len());
let mut h = Sha1::new();
h.update(&data[..split]);
h.update(&data[split..]);
assert_eq!(hex(&h.finish()), want, "split at {split} of {}", data.len());
}
let mut h = Sha1::new();
for b in data {
h.update(&[*b]);
}
assert_eq!(hex(&h.finish()), want, "byte by byte, {} bytes", data.len());
}
#[test]
fn standard_vectors() {
check(b"", "da39a3ee5e6b4b0d3255bfef95601890afd80709");
check(b"abc", "a9993e364706816aba3e25717850c26c9cd0d89d");
check(
b"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq",
"84983e441c3bd26ebaae4aa1f95129e5e54670f1",
);
check(
b"The quick brown fox jumps over the lazy dog",
"2fd4e1c67a2d28fced849ee1bb76e7391b93eb12",
);
}
#[test]
fn a_million_a() {
let data = vec![b'a'; 1_000_000];
assert_eq!(
hex(&sha1(&data)),
"34aa973cd4c4daa4f61eeb2bdbad27316534016f"
);
}
#[test]
fn lengths_around_the_block_boundary() {
// `printf 'a%.0s' $(seq N) | sha1sum`, N = 55, 56, 63, 64, 65, 119, 120.
let cases = [
(55, "c1c8bbdc22796e28c0e15163d20899b65621d65a"),
(56, "c2db330f6083854c99d4b5bfb6e8f29f201be699"),
(63, "03f09f5b158a7a8cdad920bddc29b81c18a551f5"),
(64, "0098ba824b5c16427bd7a1122a5a442a25ec644d"),
(65, "11655326c708d70319be2610e8a57d9a5b959d3b"),
(119, "ee971065aaa017e0632a8ca6c77bb3bf8b1dfc56"),
(120, "f34c1488385346a55709ba056ddd08280dd4c6d6"),
];
for (n, want) in cases {
check(&vec![b'a'; n], want);
}
}
#[test]
fn the_websocket_handshake_example() {
// RFC 6455, section 1.3: the key and the GUID give this digest (its base64 is
// "s3pPLMBiTxaQ9kYGzzhZRbK+xOo=").
let digest = sha1(b"dGhlIHNhbXBsZSBub25jZQ==258EAFA5-E914-47DA-95CA-C5AB0DC85B11");
assert_eq!(hex(&digest), "b37a4f2cc0624f1690f64606cf385945b2bec4ea");
}