use oxicrypto_core::{CryptoError, Mac};
use oxicrypto_mac::Poly1305Mac;
fn hex_decode(s: &str) -> Vec<u8> {
let s: String = s.chars().filter(|c| !c.is_whitespace()).collect();
(0..s.len())
.step_by(2)
.map(|i| u8::from_str_radix(&s[i..i + 2], 16).expect("valid hex digit"))
.collect()
}
fn to_hex(bytes: &[u8]) -> String {
bytes.iter().map(|b| format!("{:02x}", b)).collect()
}
#[test]
fn poly1305_rfc8439_s2_5_2() {
let key = hex_decode(
"85d6be7857556d337f4452fe42d506a8\
0103808afb0db2fd4abff6af4149f51b",
);
let msg = b"Cryptographic Forum Research Group";
let expected = "a8061dc1305136c6c22b8baf0c0127a9";
let mac = Poly1305Mac;
let mut out = [0u8; 16];
mac.mac(&key, msg, &mut out).expect("Poly1305 §2.5.2");
assert_eq!(to_hex(&out), expected, "RFC 8439 §2.5.2 tag mismatch");
}
#[test]
fn poly1305_rfc8439_a3_tv1_all_zeros() {
let key = [0u8; 32];
let msg = [0u8; 64];
let expected = "00000000000000000000000000000000";
let mac = Poly1305Mac;
let mut out = [0u8; 16];
mac.mac(&key, &msg, &mut out).expect("Poly1305 §A.3 TV#1");
assert_eq!(to_hex(&out), expected, "RFC 8439 §A.3 TV#1 tag mismatch");
}
#[test]
fn poly1305_zero_key_ff_data_all_zero_tag() {
let key = [0u8; 32];
let msg = [0xff_u8; 64];
let expected = "00000000000000000000000000000000";
let mac = Poly1305Mac;
let mut out = [0u8; 16];
mac.mac(&key, &msg, &mut out)
.expect("Poly1305 zero-key test");
assert_eq!(to_hex(&out), expected, "zero-key tag must be all zeros");
}
#[test]
fn poly1305_ff_key_zero_data() {
let key = [0xff_u8; 32];
let msg = [0u8; 64];
let expected = "49e2e7f920a5615e9d0c1d9426133fe9";
let mac = Poly1305Mac;
let mut out = [0u8; 16];
mac.mac(&key, &msg, &mut out)
.expect("Poly1305 0xff-key test");
assert_eq!(
to_hex(&out),
expected,
"0xff-key with zero data tag mismatch"
);
}
#[test]
fn poly1305_rfc8439_a3_tv4_counter_wrap() {
let key = hex_decode(
"02000000000000000000000000000000\
00000000000000000000000000000000",
);
let msg = hex_decode("ffffffffffffffffffffffffffffffff");
let expected = "03000000000000000000000000000000";
let mac = Poly1305Mac;
let mut out = [0u8; 16];
mac.mac(&key, &msg, &mut out).expect("Poly1305 §A.3 TV#4");
assert_eq!(to_hex(&out), expected, "RFC 8439 §A.3 TV#4 tag mismatch");
}
#[test]
fn poly1305_verify_accepts_correct_tag() {
let key = hex_decode(
"85d6be7857556d337f4452fe42d506a8\
0103808afb0db2fd4abff6af4149f51b",
);
let msg = b"Cryptographic Forum Research Group";
let expected = hex_decode("a8061dc1305136c6c22b8baf0c0127a9");
let mac = Poly1305Mac;
mac.verify(&key, msg, &expected)
.expect("verify must succeed for correct tag");
}
#[test]
fn poly1305_verify_rejects_tampered_tag() {
let key = hex_decode(
"85d6be7857556d337f4452fe42d506a8\
0103808afb0db2fd4abff6af4149f51b",
);
let msg = b"Cryptographic Forum Research Group";
let mut tag = hex_decode("a8061dc1305136c6c22b8baf0c0127a9");
tag[0] ^= 0x01;
let mac = Poly1305Mac;
assert_eq!(
mac.verify(&key, msg, &tag),
Err(CryptoError::InvalidTag),
"tampered tag must be rejected"
);
}
#[test]
fn poly1305_verify_rejects_wrong_tag_length() {
let key = [0u8; 32];
let msg = b"test";
let mac = Poly1305Mac;
let short_tag = [0u8; 15];
assert_eq!(
mac.verify(&key, msg, &short_tag),
Err(CryptoError::InvalidTag),
"15-byte tag must be rejected"
);
}
#[test]
fn poly1305_mac_rejects_short_key() {
let key = [0u8; 16]; let mac = Poly1305Mac;
let mut out = [0u8; 16];
assert_eq!(
mac.mac(&key, b"msg", &mut out),
Err(CryptoError::InvalidKey),
"16-byte key must be rejected"
);
}
#[test]
fn poly1305_mac_rejects_long_key() {
let key = [0u8; 33]; let mac = Poly1305Mac;
let mut out = [0u8; 16];
assert_eq!(
mac.mac(&key, b"msg", &mut out),
Err(CryptoError::InvalidKey),
"33-byte key must be rejected"
);
}
#[test]
fn poly1305_mac_rejects_short_output_buffer() {
let key = [0u8; 32];
let mac = Poly1305Mac;
let mut out = [0u8; 8]; assert_eq!(
mac.mac(&key, b"msg", &mut out),
Err(CryptoError::BufferTooSmall),
"8-byte output buffer must be rejected"
);
}