1#![crate_type = "lib"]
2#![crate_name = "keccak_rust"]
3
4mod keccak_f;
5use keccak_f::*;
6
7mod sponge;
8use sponge::*;
9
10pub type BitsWidth = usize;
11
12pub type Rate = usize;
13pub type Capacity = usize;
14pub type Security = (Rate, Capacity);
15
16pub type Byte = u8;
17pub type State = [[u64; 5]; 5];
18pub type BytesVec = Vec<Byte>;
19pub type BytesArr = [Byte];
20
21pub type PermutationsNum = usize;
22
23static RATES: [usize; 4] = [1152, 1088, 832, 576];
25static CAPACITIES: [usize; 4] = [448, 512, 768, 1024];
26
27static PERMUTATIONS_NUM: [usize; 7] = [12, 14, 16, 18, 20, 22, 24];
29
30static ROUND_CONSTANTS: [u64; 24] = [
31 0x0000000000000001,
32 0x0000000000008082,
33 0x800000000000808A,
34 0x8000000080008000,
35 0x000000000000808B,
36 0x0000000080000001,
37 0x8000000080008081,
38 0x8000000000008009,
39 0x000000000000008A,
40 0x0000000000000088,
41 0x0000000080008009,
42 0x000000008000000A,
43 0x000000008000808B,
44 0x800000000000008B,
45 0x8000000000008089,
46 0x8000000000008003,
47 0x8000000000008002,
48 0x8000000000000080,
49 0x000000000000800A,
50 0x800000008000000A,
51 0x8000000080008081,
52 0x8000000000008080,
53 0x0000000080000001,
54 0x8000000080008008,
55];
56
57static ROTATION_CONSTANTS: State = [
58 [0, 36, 3, 41, 18],
59 [1, 44, 10, 45, 2],
60 [62, 6, 43, 15, 61],
61 [28, 55, 25, 21, 56],
62 [27, 20, 39, 8, 14],
63];
64
65pub enum StateBitsWidth {
66 F25,
67 F50,
68 F100,
69 F200,
70 F400,
71 F800,
72 F1600,
73 Custom(BitsWidth),
74}
75
76pub enum SecurityLevel {
77 SHA224,
78 SHA256,
79 SHA384,
80 SHA512,
81 Custom(Security),
82}
83
84pub struct Keccak {
108 state: State,
109 sponge: Sponge,
110}
111
112impl Keccak {
113 pub fn new(security: SecurityLevel, width: StateBitsWidth) -> Keccak {
130 let security_level = match security {
131 SecurityLevel::SHA224 => (RATES[0], CAPACITIES[0]),
132 SecurityLevel::SHA256 => (RATES[1], CAPACITIES[1]),
133 SecurityLevel::SHA384 => (RATES[2], CAPACITIES[2]),
134 SecurityLevel::SHA512 => (RATES[3], CAPACITIES[3]),
135 SecurityLevel::Custom(security) => (security.0, security.1),
136 };
137
138 Keccak {
139 state: [[0; 5]; 5],
140 sponge: Sponge::new(security_level.0 / 8, security_level.1 / 8, width),
142 }
143 }
144
145 pub fn append(&mut self, input: &BytesArr) {
147 let padding_total = self.sponge.rate - (input.len() % self.sponge.rate);
148 let mut padding: Vec<Byte>;
149
150 if padding_total == 1 {
151 padding = vec![0x81];
152 } else {
153 padding = vec![];
154 padding.push(0x01);
155
156 for _ in 0..(padding_total - 2) {
157 padding.push(0x00);
158 }
159
160 padding.push(0x80);
161 }
162
163 let padded_input: &BytesArr = &[input, &padding].concat();
164 self.sponge.absorb(&mut self.state, padded_input);
165 }
166
167 pub fn hash(&mut self) -> BytesVec {
169 self.sponge.squeeze(&mut self.state)
170 }
171}