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>
2.7 KiB
2.7 KiB
M4a task 01: SHA-1 in proto
Branch: m4a (run git switch m4a; git status --short must be empty, otherwise stop)
Commit subject: proto: sha1, for the WebSocket handshake check
Goal
gatewayd speaks WebSocket to Mattermost. The server proves it understood the handshake by
sending back the SHA-1 of our key (RFC 6455, section 4.2.2), so we need SHA-1. It lives in
proto, which has no dependencies of its own. It is used for that check and nothing else: it must
never protect anything.
Files
- Copy:
crates/proto/tests/sha1.rs, and the skeletoncrates/proto/src/sha1.rs - Modify:
crates/proto/src/lib.rs(pub mod sha1;),docs/implementer-log.md
Interface (in the skeleton)
pub fn sha1(data: &[u8]) -> [u8; 20]; // written: new, update, finish
pub struct Sha1 { state: [u32; 5], block: [u8; 64], filled: usize, length: u64 }
impl Sha1 {
pub fn new() -> Sha1; // written: the five initial words
pub fn update(&mut self, data: &[u8]); // todo
pub fn finish(self) -> [u8; 20]; // todo
fn compress(&mut self, block: &[u8; 64]); // todo
}
length counts bits fed so far. Each todo!() has its steps above it. No indexing that can go
out of bounds: w[i] on the fixed [u32; 80] inside compress is fine; slicing data or block
by a computed range is not (use get, get_mut, split_at). Use as_chunks::<4>() to read
big-endian words.
Steps
- 1. Copy.
git switch m4a, thencp docs/plans/M4a/files/crates/proto/tests/sha1.rs crates/proto/tests/andcp docs/plans/M4a/files/crates/proto/src/sha1.rs crates/proto/src/. Addpub mod sha1;tocrates/proto/src/lib.rs. - 2. See it fail.
cargo test -p proto --test sha1. Expected: it compiles, and 4 tests fail withnot yet implemented. - 3. Fill the three functions, one at a time:
compress, thenupdate, thenfinish. Runcargo check -p protoafter each. - 4. See it pass.
cargo test -p proto --test sha1. Expected: 4 passed. The tests include FIPS 180 and RFC 3174 vectors, a millionas, the lengths around the 64-byte block where the padding changes shape (checked withsha1sum), and the RFC 6455 handshake example; every case is also fed in pieces. - 5. Run the gate.
cargo fmt --all, thenmake gate. Expected last line:gate: ok. - 6. Log and commit.
git add crates/proto docs/implementer-log.md Cargo.lock && git commit
Done when
cargo test -p proto --test sha1passes;make gateprintsgate: ok.
Stop and report if
- A test vector fails and you cannot find why after checking
compressagainst the comment twice.