1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
//! Correlation robust AES hash.
//!
//! This implementation of a correlation robust AES hash function
//! is based on the findings of <https://eprint.iacr.org/2019/074>.
use crate::util::Block;
use aes::cipher::{BlockEncrypt, Key, KeyInit};
use aes::Aes128;
use once_cell::sync::Lazy;

pub struct AesHash {
    aes: Aes128,
}

impl AesHash {
    /// Create a new `AesHash` with the given key.
    pub fn new(key: &Key<Aes128>) -> Self {
        Self {
            aes: Aes128::new(key),
        }
    }

    /// Compute the correlation robust hash of a block.
    ///
    /// # Warning: only secure in semi-honest setting!
    /// See <https://eprint.iacr.org/2019/074> for details.
    pub fn cr_hash_block(&self, x: Block) -> Block {
        let mut x_enc = x.into();
        self.aes.encrypt_block(&mut x_enc);
        x ^ x_enc.into()
    }

    /// Compute the correlation robust hashes of multiple blocks.
    ///
    /// Warning: only secure in semi-honest setting!
    /// See <https://eprint.iacr.org/2019/074> for details.
    pub fn cr_hash_blocks<const N: usize>(&self, x: &[Block; N]) -> [Block; N] {
        let mut blocks = x.map(|blk| blk.into());
        self.aes.encrypt_blocks(&mut blocks);

        let mut blocks = blocks.map(|enc_blk| enc_blk.into());
        for (enc_x, x) in blocks.iter_mut().zip(x) {
            *enc_x ^= *x;
        }
        blocks
    }

    pub fn cr_hash_slice_mut(&self, x: &mut [Block]) {
        let mut encrypted = vec![Default::default(); x.len()];
        self.aes
            .encrypt_blocks_b2b(Block::cast_slice(x), &mut encrypted)
            .unwrap();
        x.iter_mut()
            .zip(encrypted)
            .for_each(|(x, x_enc)| *x ^= x_enc.into());
    }
}

/// An `AesHash` with a fixed key.
pub static FIXED_KEY_HASH: Lazy<AesHash> = Lazy::new(|| {
    // TODO: Is it sufficient to just choose some random key? This one was generated
    //  by just using `rand::thread_rng().gen()`
    let key = 193502124791825095790518994062991136444_u128
        .to_le_bytes()
        .into();
    AesHash::new(&key)
});