entropy-auth 2026.7.31

Authentication and authorization for Entropy Softworks server and API projects
#![allow(missing_docs)]

//! Crypto test vectors exercised through the public API only.

use entropy_auth::{
    HmacSha256, Sha256, Sha512, base64_decode, base64_encode, constant_time_eq, hex_decode,
    hex_encode,
};

// --- SHA-256 Vectors ---

#[test]
fn sha256_nist_one_block_abc() {
    let hash = Sha256::digest(b"abc");
    assert_eq!(
        hex_encode(&hash),
        "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad",
    );
}

#[test]
fn sha256_empty_message() {
    let hash = Sha256::digest(b"");
    assert_eq!(
        hex_encode(&hash),
        "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
    );
}

#[test]
fn sha256_two_block_message() {
    let msg = b"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq";
    let hash = Sha256::digest(msg);
    assert_eq!(
        hex_encode(&hash),
        "248d6a61d20638b8e5c026930c3e6039a33ce45964ff2167f6ecedd419db06c1",
    );
}

#[test]
fn sha256_incremental_matches_one_shot() {
    let mut hasher = Sha256::new();
    hasher.update(b"ab");
    hasher.update(b"c");
    assert_eq!(
        hex_encode(&hasher.finalize()),
        "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad",
    );
}

// --- SHA-512 Vectors ---

#[test]
fn sha512_nist_one_block_abc() {
    let hash = Sha512::digest(b"abc");
    assert_eq!(
        hex_encode(&hash),
        "ddaf35a193617abacc417349ae20413112e6fa4e89a97ea20a9eeee64b55d39a\
         2192992a274fc1a836ba3c23a3feebbd454d4423643ce80e2a9ac94fa54ca49f",
    );
}

#[test]
fn sha512_empty_message() {
    let hash = Sha512::digest(b"");
    assert_eq!(
        hex_encode(&hash),
        "cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce\
         47d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3e",
    );
}

#[test]
fn sha512_incremental_matches_one_shot() {
    let mut hasher = Sha512::new();
    hasher.update(b"a");
    hasher.update(b"bc");
    assert_eq!(
        hex_encode(&hasher.finalize()),
        "ddaf35a193617abacc417349ae20413112e6fa4e89a97ea20a9eeee64b55d39a\
         2192992a274fc1a836ba3c23a3feebbd454d4423643ce80e2a9ac94fa54ca49f",
    );
}

// --- HMAC-SHA-256 Vectors ---

#[test]
fn hmac_sha256_rfc4231_test_case_2() {
    // Key  = "Jefe"
    // Data = "what do ya want for nothing?"
    let tag = HmacSha256::mac(b"Jefe", b"what do ya want for nothing?");
    assert_eq!(
        hex_encode(&tag),
        "5bdcc146bf60754e6a042426089575c75a003f089d2739839dec58b964ec3843",
    );
}

#[test]
fn hmac_sha256_verify_round_trip() {
    let key = b"test-key";
    let data = b"test-data";
    let tag = HmacSha256::mac(key, data);
    assert!(HmacSha256::verify(key, data, &tag));
}

#[test]
fn hmac_sha256_verify_rejects_tampered_tag() {
    let key = b"test-key";
    let data = b"test-data";
    let mut tag = HmacSha256::mac(key, data);
    tag[0] ^= 0x01;
    assert!(!HmacSha256::verify(key, data, &tag));
}

// --- Base64 Round-Trip ---

#[test]
fn base64_encode_decode_round_trip() {
    let original = b"The quick brown fox jumps over the lazy dog";
    let encoded = base64_encode(original);
    let decoded = base64_decode(&encoded).unwrap();
    assert_eq!(decoded, original);
}

#[test]
fn base64_round_trip_empty() {
    let encoded = base64_encode(b"");
    let decoded = base64_decode(&encoded).unwrap();
    assert_eq!(decoded, b"");
}

#[test]
fn base64_round_trip_binary_data() {
    let original: Vec<u8> = (0..=255).collect();
    let encoded = base64_encode(&original);
    let decoded = base64_decode(&encoded).unwrap();
    assert_eq!(decoded, original);
}

// --- Hex Round-Trip ---

#[test]
fn hex_encode_decode_round_trip() {
    let original = b"hello world";
    let encoded = hex_encode(original);
    let decoded = hex_decode(&encoded).unwrap();
    assert_eq!(decoded, original);
}

#[test]
fn hex_round_trip_empty() {
    let encoded = hex_encode(b"");
    let decoded = hex_decode(&encoded).unwrap();
    assert_eq!(decoded, b"");
}

#[test]
fn hex_round_trip_all_byte_values() {
    let original: Vec<u8> = (0..=255).collect();
    let encoded = hex_encode(&original);
    let decoded = hex_decode(&encoded).unwrap();
    assert_eq!(decoded, original);
}

// --- Constant-Time Equality ---

#[test]
fn constant_time_eq_equal_slices_returns_true() {
    assert!(constant_time_eq(b"identical", b"identical"));
}

#[test]
fn constant_time_eq_different_slices_returns_false() {
    assert!(!constant_time_eq(b"one-value", b"different"));
}

#[test]
fn constant_time_eq_different_lengths_returns_false() {
    assert!(!constant_time_eq(b"short", b"longer-string"));
}

#[test]
fn constant_time_eq_empty_slices_returns_true() {
    assert!(constant_time_eq(b"", b""));
}

#[test]
fn constant_time_eq_differ_at_last_byte() {
    assert!(!constant_time_eq(b"same-prefix-x", b"same-prefix-y"));
}