#![crate_type = "lib"]
#![crate_name = "keccak_rust"]
mod keccak_f;
use keccak_f::*;
mod sponge;
use sponge::*;
pub type BitsWidth = usize;
pub type Rate = usize;
pub type Capacity = usize;
pub type Security = (Rate, Capacity);
pub type Byte = u8;
pub type State = [[u64; 5]; 5];
pub type BytesVec = Vec<Byte>;
pub type BytesArr = [Byte];
pub type PermutationsNum = usize;
static RATES: [usize; 4] = [1152, 1088, 832, 576];
static CAPACITIES: [usize; 4] = [448, 512, 768, 1024];
static PERMUTATIONS_NUM: [usize; 7] = [12, 14, 16, 18, 20, 22, 24];
static ROUND_CONSTANTS: [u64; 24] = [
0x0000000000000001,
0x0000000000008082,
0x800000000000808A,
0x8000000080008000,
0x000000000000808B,
0x0000000080000001,
0x8000000080008081,
0x8000000000008009,
0x000000000000008A,
0x0000000000000088,
0x0000000080008009,
0x000000008000000A,
0x000000008000808B,
0x800000000000008B,
0x8000000000008089,
0x8000000000008003,
0x8000000000008002,
0x8000000000000080,
0x000000000000800A,
0x800000008000000A,
0x8000000080008081,
0x8000000000008080,
0x0000000080000001,
0x8000000080008008,
];
static ROTATION_CONSTANTS: State = [
[0, 36, 3, 41, 18],
[1, 44, 10, 45, 2],
[62, 6, 43, 15, 61],
[28, 55, 25, 21, 56],
[27, 20, 39, 8, 14],
];
pub enum StateBitsWidth {
F25,
F50,
F100,
F200,
F400,
F800,
F1600,
Custom(BitsWidth),
}
pub enum SecurityLevel {
SHA224,
SHA256,
SHA384,
SHA512,
Custom(Security),
}
pub struct Keccak {
state: State,
sponge: Sponge,
}
impl Keccak {
pub fn new(security: SecurityLevel, width: StateBitsWidth) -> Keccak {
let security_level = match security {
SecurityLevel::SHA224 => (RATES[0], CAPACITIES[0]),
SecurityLevel::SHA256 => (RATES[1], CAPACITIES[1]),
SecurityLevel::SHA384 => (RATES[2], CAPACITIES[2]),
SecurityLevel::SHA512 => (RATES[3], CAPACITIES[3]),
SecurityLevel::Custom(security) => (security.0, security.1),
};
Keccak {
state: [[0; 5]; 5],
sponge: Sponge::new(security_level.0 / 8, security_level.1 / 8, width),
}
}
pub fn append(&mut self, input: &BytesArr) {
let padding_total = self.sponge.rate - (input.len() % self.sponge.rate);
let mut padding: Vec<Byte>;
if padding_total == 1 {
padding = vec![0x81];
} else {
padding = vec![];
padding.push(0x01);
for _ in 0..(padding_total - 2) {
padding.push(0x00);
}
padding.push(0x80);
}
let padded_input: &BytesArr = &[input, &padding].concat();
self.sponge.absorb(&mut self.state, padded_input);
}
pub fn hash(&mut self) -> BytesVec {
self.sponge.squeeze(&mut self.state)
}
}