dcrypt-algorithms 1.2.3

Cryptographic primitives for the dcrypt library
Documentation
use super::*;
use crate::types::Tag;
use hex;
use rand::{rngs::StdRng, RngCore, SeedableRng};

fn rfc_key() -> [u8; 32] {
    hex::decode("85d6be7857556d337f4452fe42d506a80103808afb0db2fd4abff6af4149f51b")
        .unwrap()
        .try_into()
        .unwrap()
}

#[test]
fn test_poly1305_rfc8439_vector() {
    let key = rfc_key();
    let mut p = Poly1305::new(&key).unwrap();
    let msg = b"Cryptographic Forum Research Group";
    p.update(msg).unwrap();
    assert_eq!(
        p.finalize(),
        Tag::<16>::from_slice(&hex::decode("a8061dc1305136c6c22b8baf0c0127a9").unwrap()).unwrap()
    );
}

#[test]
fn test_empty_message() {
    let key = rfc_key();
    let tag = Poly1305::new(&key).unwrap().finalize();
    let mut expected = [0u8; 16];
    expected.copy_from_slice(&key[16..32]);
    assert_eq!(tag, Tag::<16>::new(expected));
}

#[test]
fn test_chunked_vs_single_update() {
    let key = rfc_key();
    let msg: Vec<u8> = b"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789".to_vec();
    let mut p1 = Poly1305::new(&key).unwrap();
    p1.update(&msg).unwrap();
    let mut p2 = Poly1305::new(&key).unwrap();
    for b in &msg {
        p2.update(&[*b]).unwrap();
    }
    assert_eq!(p1.finalize(), p2.finalize());
}

#[test]
fn test_hello_message() {
    let key = rfc_key();
    let mut p = Poly1305::new(&key).unwrap();
    p.update(b"Hello").unwrap();
    assert_eq!(
        p.finalize(),
        Tag::<16>::from_slice(&hex::decode("f74f694dcdf0d5131ed59f4b4e760495").unwrap()).unwrap()
    );
}

#[test]
fn test_single_block_message() {
    let key = rfc_key();
    let mut p = Poly1305::new(&key).unwrap();
    p.update(b"0123456789ABCDEF").unwrap();
    assert_eq!(
        p.finalize(),
        Tag::<16>::from_slice(&hex::decode("e70d564ce526627cb2f56c7657604601").unwrap()).unwrap()
    );
}

#[test]
fn test_multi_block_message() {
    let key = rfc_key();
    let msg = b"0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF";
    let mut p = Poly1305::new(&key).unwrap();
    p.update(msg).unwrap();
    assert_eq!(
        p.finalize(),
        Tag::<16>::from_slice(&hex::decode("8253fca07713cc36043e7aed25d35085").unwrap()).unwrap()
    );
}

#[test]
fn test_poly1305_rfc8439_vector2() {
    let mut key = [0u8; 32];
    key[16..32].copy_from_slice(&hex::decode("36e5f6b5c5e06070f0efca96227a863e").unwrap());
    let mut p = Poly1305::new(&key).unwrap();
    let text = b"Any submission to the IETF intended by the Contributor for \
publication as all or part of an IETF Internet-Draft or RFC";
    p.update(text).unwrap();
    assert_eq!(
        p.finalize(),
        Tag::<16>::from_slice(&hex::decode("36e5f6b5c5e06070f0efca96227a863e").unwrap()).unwrap()
    );
}

#[test]
fn test_poly1305_rfc8439_vector5() {
    let mut key = [0u8; 32];
    key[0] = 0x02;
    let mut p = Poly1305::new(&key).unwrap();
    p.update(&[0xFFu8; 16]).unwrap();
    assert_eq!(
        p.finalize(),
        Tag::<16>::from_slice(&hex::decode("03000000000000000000000000000000").unwrap()).unwrap()
    );
}

#[test]
fn test_poly1305_rfc8439_vector6() {
    let mut key = [0u8; 32];
    key[0] = 0x02;
    for b in &mut key[16..32] {
        *b = 0xFF;
    }
    let mut p = Poly1305::new(&key).unwrap();
    let mut block = [0u8; 16];
    block[0] = 0x02;
    p.update(&block).unwrap();
    assert_eq!(
        p.finalize(),
        Tag::<16>::from_slice(&hex::decode("03000000000000000000000000000000").unwrap()).unwrap()
    );
}

#[test]
fn test_poly1305_rfc8439_vector7() {
    let mut key = [0u8; 32];
    key[0] = 0x01;
    let mut p = Poly1305::new(&key).unwrap();
    p.update(&[0xFFu8; 16]).unwrap();
    let mut b2 = [0xFFu8; 16];
    b2[0] = 0xF0;
    p.update(&b2).unwrap();
    let mut b3 = [0u8; 16];
    b3[0] = 0x11;
    p.update(&b3).unwrap();
    assert_eq!(
        p.finalize(),
        Tag::<16>::from_slice(&hex::decode("05000000000000000000000000000000").unwrap()).unwrap()
    );
}

#[test]
fn test_poly1305_rfc8439_vector8() {
    let mut key = [0u8; 32];
    key[0] = 0x01;
    let mut p = Poly1305::new(&key).unwrap();
    p.update(&[0xFFu8; 16]).unwrap();
    let mut b2 = [0xFEu8; 16];
    b2[0] = 0xFB;
    p.update(&b2).unwrap();
    p.update(&[0x01u8; 16]).unwrap();
    assert_eq!(
        p.finalize(),
        Tag::<16>::from_slice(&hex::decode("00000000000000000000000000000000").unwrap()).unwrap()
    );
}

#[test]
fn test_poly1305_rfc8439_vector10() {
    let mut key = [0u8; 32];
    key[..16].copy_from_slice(&hex::decode("01000000000000000400000000000000").unwrap());
    let data = hex::decode(
        "e33594d7505e43b90000000000000000\
         3394d7505e4379cd0100000000000000\
         00000000000000000000000000000000\
         01000000000000000000000000000000",
    )
    .unwrap();
    let mut p = Poly1305::new(&key).unwrap();
    p.update(&data).unwrap();
    assert_eq!(
        p.finalize(),
        Tag::<16>::from_slice(&hex::decode("14000000000000005500000000000000").unwrap()).unwrap()
    );
}

#[test]
fn test_poly1305_rfc8439_vector11() {
    let mut key = [0u8; 32];
    key[..16].copy_from_slice(&hex::decode("01000000000000000400000000000000").unwrap());
    let data = hex::decode(
        "e33594d7505e43b90000000000000000\
         3394d7505e4379cd0100000000000000\
         00000000000000000000000000000000",
    )
    .unwrap();
    let mut p = Poly1305::new(&key).unwrap();
    p.update(&data).unwrap();
    assert_eq!(
        p.finalize(),
        Tag::<16>::from_slice(&hex::decode("13000000000000000000000000000000").unwrap()).unwrap()
    );
}

#[test]
fn random_vs_chunked_update() {
    let mut rng = StdRng::seed_from_u64(0x123456789ABCDEF0);
    for _ in 0..1_000 {
        let mut key = [0u8; 32];
        rng.fill_bytes(&mut key);
        let msg_len = (rng.next_u32() % 256) as usize;
        let mut msg = vec![0u8; msg_len];
        rng.fill_bytes(&mut msg);
        let mut p1 = Poly1305::new(&key).unwrap();
        p1.update(&msg).unwrap();
        let mut p2 = Poly1305::new(&key).unwrap();
        let mut off = 0;
        while off < msg_len {
            let c = ((rng.next_u32() % 16) + 1) as usize;
            let end = usize::min(off + c, msg_len);
            p2.update(&msg[off..end]).unwrap();
            off = end;
        }
        assert_eq!(p1.finalize(), p2.finalize());
    }
}

#[test]
fn random_empty_update() {
    let mut rng = StdRng::seed_from_u64(0x0FEDCBA987654321);
    for _ in 0..100 {
        let mut key = [0u8; 32];
        rng.fill_bytes(&mut key);
        let mut p = Poly1305::new(&key).unwrap();
        p.update(&[]).unwrap();
        p.update(&[]).unwrap();
        let mut expected = [0u8; 16];
        expected.copy_from_slice(&key[16..32]);
        assert_eq!(p.finalize(), Tag::<16>::new(expected));
    }
}