27 lines
1.1 KiB
Rust
27 lines
1.1 KiB
Rust
fn request_id_hash(sequence: u64) -> String {
|
|
// Same thread-local CSPRNG as before, now with no per-request SHA-256.
|
|
// XORing an increasing sequence into independent uniformly random bytes
|
|
// preserves the full 256-bit unpredictability and 64-hex-character shape.
|
|
// The sequence is still mixed in; this is not a predictable counter ID.
|
|
let mut token: [u8; 32] = rand::random();
|
|
for (byte, sequence_byte) in token[..8].iter_mut().zip(sequence.to_be_bytes()) {
|
|
*byte ^= sequence_byte;
|
|
}
|
|
request_id_hex(&token)
|
|
}
|
|
|
|
fn request_id_hex(digest: &[u8]) -> String {
|
|
const HEX: &[u8; 16] = b"0123456789abcdef";
|
|
// Encode two ASCII bytes per digest byte in one allocation; avoid 64
|
|
// separate String::push bounds checks for the 32-byte SHA-256 digest.
|
|
let mut encoded = vec![0u8; digest.len() * 2];
|
|
for (i, &byte) in digest.iter().enumerate() {
|
|
encoded[2 * i] = HEX[(byte >> 4) as usize];
|
|
encoded[2 * i + 1] = HEX[(byte & 0x0f) as usize];
|
|
}
|
|
String::from_utf8(encoded).expect("hex digits are always valid UTF-8")
|
|
}
|
|
|
|
#[cfg(test)]
|
|
include!("request_id/tests.rs");
|