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>
79 lines
2.4 KiB
Rust
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");
|
|
}
|