use md5::{Digest, Md5};
#[inline]
pub fn compute_md5(data: &[u8]) -> [u8; 16] {
let mut context = Md5::new();
md5::Digest::update(&mut context, data);
context.finalize().into()
}
#[inline]
pub fn create_chacha_key(data: &[u8]) -> [u8; 32] {
let mut ret = [0u8; 32];
let mut context = Md5::new();
md5::Digest::update(&mut context, data);
let first_half: [u8; 16] = context.finalize_reset().into();
ret[0..16].copy_from_slice(&first_half);
md5::Digest::update(&mut context, first_half);
let second_half: [u8; 16] = context.finalize().into();
ret[16..].copy_from_slice(&second_half);
ret
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_compute_md5_empty() {
let result = compute_md5(b"");
assert_eq!(
result,
[
0xd4, 0x1d, 0x8c, 0xd9, 0x8f, 0x00, 0xb2, 0x04, 0xe9, 0x80, 0x09, 0x98, 0xec, 0xf8,
0x42, 0x7e
]
);
}
#[test]
fn test_compute_md5_hello() {
let result = compute_md5(b"hello");
assert_eq!(
result,
[
0x5d, 0x41, 0x40, 0x2a, 0xbc, 0x4b, 0x2a, 0x76, 0xb9, 0x71, 0x9d, 0x91, 0x10, 0x17,
0xc5, 0x92
]
);
}
#[test]
fn test_compute_md5_vmess_user_id() {
let user_id = b"test-user-id";
let magic = b"c48619fe-8f02-49e0-b9e9-edf763e17e21";
let mut combined = Vec::new();
combined.extend_from_slice(user_id);
combined.extend_from_slice(magic);
let result = compute_md5(&combined);
assert_eq!(result.len(), 16);
assert_ne!(result, [0u8; 16]);
}
#[test]
fn test_create_chacha_key_from_16_bytes() {
let input = [
0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e,
0x0f, 0x10,
];
let result = create_chacha_key(&input);
assert_eq!(result.len(), 32);
assert_eq!(&result[0..16], &compute_md5(&input));
assert_eq!(&result[16..32], &compute_md5(&result[0..16]));
}
#[test]
fn test_create_chacha_key_deterministic() {
let input = b"test-key-material";
let result1 = create_chacha_key(input);
let result2 = create_chacha_key(input);
assert_eq!(result1, result2);
}
#[test]
fn test_create_chacha_key_different_inputs() {
let result1 = create_chacha_key(b"key1");
let result2 = create_chacha_key(b"key2");
assert_ne!(result1, result2);
}
#[test]
fn test_create_chacha_key_empty() {
let result = create_chacha_key(b"");
assert_eq!(result.len(), 32);
assert_eq!(
&result[0..16],
&[
0xd4, 0x1d, 0x8c, 0xd9, 0x8f, 0x00, 0xb2, 0x04, 0xe9, 0x80, 0x09, 0x98, 0xec, 0xf8,
0x42, 0x7e
]
);
}
#[test]
fn test_create_chacha_key_matches_sing_vmess() {
let key = [0u8; 16];
let result = create_chacha_key(&key);
let first_half = compute_md5(&key);
let second_half = compute_md5(&first_half);
assert_eq!(&result[0..16], &first_half);
assert_eq!(&result[16..32], &second_half);
}
}