snowbridge_amcl/
hash256.rs

1/*
2Licensed to the Apache Software Foundation (ASF) under one
3or more contributor license agreements.  See the NOTICE file
4distributed with this work for additional information
5regarding copyright ownership.  The ASF licenses this file
6to you under the Apache License, Version 2.0 (the
7"License"); you may not use this file except in compliance
8with the License.  You may obtain a copy of the License at
9
10  http://www.apache.org/licenses/LICENSE-2.0
11
12Unless required by applicable law or agreed to in writing,
13software distributed under the License is distributed on an
14"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15KIND, either express or implied.  See the License for the
16specific language governing permissions and limitations
17under the License.
18*/
19use crate::std::{vec, Vec};
20
21const HASH256_H0: u32 = 0x6A09_E667;
22const HASH256_H1: u32 = 0xBB67_AE85;
23const HASH256_H2: u32 = 0x3C6E_F372;
24const HASH256_H3: u32 = 0xA54F_F53A;
25const HASH256_H4: u32 = 0x510E_527F;
26const HASH256_H5: u32 = 0x9B05_688C;
27const HASH256_H6: u32 = 0x1F83_D9AB;
28const HASH256_H7: u32 = 0x5BE0_CD19;
29
30const HASH256_K: [u32; 64] = [
31    0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
32    0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
33    0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
34    0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
35    0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
36    0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
37    0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
38    0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2,
39];
40
41/// The block size of each round.
42pub const BLOCK_SIZE: usize = 64;
43/// Hash Length in Bytes
44pub const HASH_BYTES: usize = 32;
45// Ipad Byte
46const IPAD_BYTE: u8 = 0x36;
47// Opad Byte
48const OPAD_BYTE: u8 = 0x5c;
49
50pub struct HASH256 {
51    length: [u32; 2],
52    h: [u32; 8],
53    w: [u32; 64],
54}
55
56impl HASH256 {
57    fn s(n: u32, x: u32) -> u32 {
58        return ((x) >> n) | ((x) << (32 - n));
59    }
60    fn r(n: u32, x: u32) -> u32 {
61        return (x) >> n;
62    }
63
64    fn ch(x: u32, y: u32, z: u32) -> u32 {
65        return (x & y) ^ (!(x) & z);
66    }
67
68    fn maj(x: u32, y: u32, z: u32) -> u32 {
69        return (x & y) ^ (x & z) ^ (y & z);
70    }
71    fn sig0(x: u32) -> u32 {
72        return HASH256::s(2, x) ^ HASH256::s(13, x) ^ HASH256::s(22, x);
73    }
74
75    fn sig1(x: u32) -> u32 {
76        return HASH256::s(6, x) ^ HASH256::s(11, x) ^ HASH256::s(25, x);
77    }
78
79    fn theta0(x: u32) -> u32 {
80        return HASH256::s(7, x) ^ HASH256::s(18, x) ^ HASH256::r(3, x);
81    }
82
83    fn theta1(x: u32) -> u32 {
84        return HASH256::s(17, x) ^ HASH256::s(19, x) ^ HASH256::r(10, x);
85    }
86
87    fn transform(&mut self) {
88        // basic transformation step
89        for j in 16..64 {
90            self.w[j] = HASH256::theta1(self.w[j - 2])
91                .wrapping_add(self.w[j - 7])
92                .wrapping_add(HASH256::theta0(self.w[j - 15]))
93                .wrapping_add(self.w[j - 16]);
94        }
95        let mut a = self.h[0];
96        let mut b = self.h[1];
97        let mut c = self.h[2];
98        let mut d = self.h[3];
99        let mut e = self.h[4];
100        let mut f = self.h[5];
101        let mut g = self.h[6];
102        let mut hh = self.h[7];
103        for j in 0..64 {
104            // 64 times - mush it up
105            let t1 = hh
106                .wrapping_add(HASH256::sig1(e))
107                .wrapping_add(HASH256::ch(e, f, g))
108                .wrapping_add(HASH256_K[j])
109                .wrapping_add(self.w[j]);
110            let t2 = HASH256::sig0(a).wrapping_add(HASH256::maj(a, b, c));
111            hh = g;
112            g = f;
113            f = e;
114            e = d.wrapping_add(t1);
115            d = c;
116            c = b;
117            b = a;
118            a = t1.wrapping_add(t2);
119        }
120        self.h[0] = self.h[0].wrapping_add(a);
121        self.h[1] = self.h[1].wrapping_add(b);
122        self.h[2] = self.h[2].wrapping_add(c);
123        self.h[3] = self.h[3].wrapping_add(d);
124        self.h[4] = self.h[4].wrapping_add(e);
125        self.h[5] = self.h[5].wrapping_add(f);
126        self.h[6] = self.h[6].wrapping_add(g);
127        self.h[7] = self.h[7].wrapping_add(hh);
128    }
129
130    /// Initialise Hash function
131    pub fn init(&mut self) {
132        // initialise
133        for i in 0..64 {
134            self.w[i] = 0
135        }
136        self.length[0] = 0;
137        self.length[1] = 0;
138        self.h[0] = HASH256_H0;
139        self.h[1] = HASH256_H1;
140        self.h[2] = HASH256_H2;
141        self.h[3] = HASH256_H3;
142        self.h[4] = HASH256_H4;
143        self.h[5] = HASH256_H5;
144        self.h[6] = HASH256_H6;
145        self.h[7] = HASH256_H7;
146    }
147
148    pub fn new() -> HASH256 {
149        let mut nh = HASH256 {
150            length: [0; 2],
151            h: [0; 8],
152            w: [0; 64],
153        };
154        nh.init();
155        return nh;
156    }
157
158    /// Process a single byte
159    pub fn process(&mut self, byt: u8) {
160        /* process the next message byte */
161        let cnt = ((self.length[0] / 32) % 16) as usize;
162        self.w[cnt] <<= 8;
163        self.w[cnt] |= (byt & 0xFF) as u32;
164        self.length[0] += 8;
165        if self.length[0] == 0 {
166            self.length[1] += 1;
167            self.length[0] = 0
168        }
169        if (self.length[0] % 512) == 0 {
170            self.transform()
171        }
172    }
173
174    /// Process an array of bytes
175    pub fn process_array(&mut self, b: &[u8]) {
176        for i in 0..b.len() {
177            self.process(b[i])
178        }
179    }
180
181    /// Process a 32-bit integer
182    pub fn process_num(&mut self, n: i32) {
183        self.process(((n >> 24) & 0xff) as u8);
184        self.process(((n >> 16) & 0xff) as u8);
185        self.process(((n >> 8) & 0xff) as u8);
186        self.process((n & 0xff) as u8);
187    }
188
189    /// Generate 32-byte Hash
190    pub fn hash(&mut self) -> [u8; HASH_BYTES] {
191        // pad message and finish - supply digest
192        let mut digest: [u8; 32] = [0; 32];
193        let len0 = self.length[0];
194        let len1 = self.length[1];
195        self.process(0x80);
196        while (self.length[0] % 512) != 448 {
197            self.process(0)
198        }
199        self.w[14] = len1;
200        self.w[15] = len0;
201        self.transform();
202        for i in 0..32 {
203            // convert to bytes
204            digest[i] = ((self.h[i / 4] >> (8 * (3 - i % 4))) & 0xff) as u8;
205        }
206        self.init();
207        return digest;
208    }
209
210    /// Generate a HMAC
211    ///
212    /// https://tools.ietf.org/html/rfc2104
213    pub fn hmac(key: &[u8], text: &[u8]) -> [u8; HASH_BYTES] {
214        let mut k = key.to_vec();
215
216        // Verify length of key < BLOCK_SIZE
217        if k.len() > BLOCK_SIZE {
218            // Reduce key to 32 bytes by hashing
219            let mut hash256 = HASH256::new();
220            hash256.init();
221            hash256.process_array(&k);
222            k = hash256.hash().to_vec();
223        }
224
225        // Prepare inner and outer paddings
226        // inner = (ipad XOR k)
227        // outer = (opad XOR k)
228        let mut inner = vec![IPAD_BYTE; BLOCK_SIZE];
229        let mut outer = vec![OPAD_BYTE; BLOCK_SIZE];
230        for (i, byte) in k.iter().enumerate() {
231            inner[i] = inner[i] ^ byte;
232            outer[i] = outer[i] ^ byte;
233        }
234
235        // Concatenate inner with text = (ipad XOR k || text)
236        inner.extend_from_slice(text);
237
238        // hash inner = H(ipad XOR k || text)
239        let mut hash256 = HASH256::new();
240        hash256.init();
241        hash256.process_array(&inner);
242        let inner = hash256.hash();
243
244        // Concatenate outer with hash of inner = (opad XOR k) || H(ipad XOR k || text)
245        outer.extend_from_slice(&inner);
246
247        // Final hash = H((opad XOR k) || H(ipad XOR k || text))
248        let mut hash256 = HASH256::new();
249        hash256.init();
250        hash256.process_array(&outer);
251        hash256.hash()
252    }
253
254    /// HKDF-Extract
255    ///
256    /// https://tools.ietf.org/html/rfc5869
257    pub fn hkdf_extract(salt: &[u8], ikm: &[u8]) -> [u8; HASH_BYTES] {
258        HASH256::hmac(salt, ikm)
259    }
260
261    /// HKDF-Extend
262    ///
263    /// https://tools.ietf.org/html/rfc5869
264    pub fn hkdf_extend(prk: &[u8], info: &[u8], l: u8) -> Vec<u8> {
265        // n = cieling(l / 32)
266        let mut n = l / (HASH_BYTES as u8);
267        if n * (HASH_BYTES as u8) < l {
268            n += 1;
269        }
270
271        let mut okm: Vec<u8> = vec![];
272        let mut previous = vec![]; // T(0) = []
273
274        for i in 0..n as usize {
275            // Concatenate (T(i) || info || i)
276            let mut text: Vec<u8> = previous;
277            text.extend_from_slice(info);
278            text.push((i + 1) as u8); // Note: i <= 254
279
280            // T(i+1) = HMAC(PRK, T(i) || info || i)
281            previous = HASH256::hmac(prk, &text).to_vec();
282            okm.extend_from_slice(&previous);
283        }
284
285        // Reduce length to size L
286        okm.resize(l as usize, 0);
287        okm
288    }
289}
290
291#[cfg(test)]
292mod tests {
293    use super::*;
294
295    #[test]
296    fn test_hmac_simple() {
297        let text = [0x0a];
298        let key = [0x0b];
299        let expected =
300            hex::decode("b1746117c186405d121d52866f48270fdeb2177d67f6922f0a031e0101658624")
301                .unwrap();
302
303        let output = HASH256::hmac(&key, &text);
304        assert_eq!(expected, output);
305    }
306
307    #[test]
308    fn test_hmac_empty() {
309        let text = [];
310        let key = [];
311        let expected =
312            hex::decode("b613679a0814d9ec772f95d778c35fc5ff1697c493715653c6c712144292c5ad")
313                .unwrap();
314
315        let output = HASH256::hmac(&key, &text);
316        assert_eq!(expected, output);
317    }
318
319    #[test]
320    fn test_hmac_32_byte_key() {
321        let text = [0x0a];
322        let key = hex::decode("abababababababababababababababababababababababababababababababab")
323            .unwrap();
324        let expected =
325            hex::decode("43997a72e7b3b1c19e5566c940d5f2961c96802b58a3da2acd19dcc1a90a8d05")
326                .unwrap();
327
328        let output = HASH256::hmac(&key, &text);
329        assert_eq!(expected, output);
330    }
331
332    #[test]
333    fn test_hmac_64_byte_key() {
334        let text = [0x0a];
335        let key = hex::decode("0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b").unwrap();
336        let expected =
337            hex::decode("93a88773df742079e3512f3d10f4f8ac674e24c4eda78df46c2376dd3946750b")
338                .unwrap();
339
340        let output = HASH256::hmac(&key, &text);
341        assert_eq!(expected, output);
342    }
343
344    #[test]
345    fn test_hmac_65_byte_key() {
346        let text = [0x0a];
347        let key = hex::decode("0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0B").unwrap();
348        let expected =
349            hex::decode("7c8dd5068bcff3347dd13a7493247444635b51cf000b18f37a74a55cec3413fb")
350                .unwrap();
351
352        let output = HASH256::hmac(&key, &text);
353        assert_eq!(expected, output);
354    }
355
356    #[test]
357    fn test_hmac_65_byte_text() {
358        let text = hex::decode("0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0B").unwrap();
359        let key = [0x0b];
360        let expected =
361            hex::decode("f04344808f2fcdafe1c20272a29b1ce4be00c916a2c14700b82b81c6eae9dd96")
362                .unwrap();
363
364        let output = HASH256::hmac(&key, &text);
365        assert_eq!(expected, output);
366    }
367
368    #[test]
369    fn test_hkdf_case_1() {
370        // From https://tools.ietf.org/html/rfc5869
371        let ikm = hex::decode("0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b").unwrap();
372        let salt = hex::decode("000102030405060708090a0b0c").unwrap();
373        let expected_prk =
374            hex::decode("077709362c2e32df0ddc3f0dc47bba6390b6c73bb50f9c3122ec844ad7c2b3e5")
375                .unwrap();
376
377        let output_prk = HASH256::hkdf_extract(&salt, &ikm).to_vec();
378        assert_eq!(expected_prk, output_prk);
379
380        let info = hex::decode("f0f1f2f3f4f5f6f7f8f9").unwrap();
381        let l = 42;
382        let expected_okm = hex::decode(
383            "3cb25f25faacd57a90434f64d0362f2a2d2d0a90cf1a5a4c5db02d56ecc4c5bf34007208d5b887185865",
384        )
385        .unwrap();
386
387        let output_okm = HASH256::hkdf_extend(&expected_prk, &info, l);
388        assert_eq!(expected_okm, output_okm);
389    }
390
391    #[test]
392    fn test_hkdf_case_2() {
393        // From https://tools.ietf.org/html/rfc5869
394        let ikm = hex::decode("000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f")
395            .unwrap();
396        let salt = hex::decode("606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeaf")
397            .unwrap();
398        let expected_prk =
399            hex::decode("06a6b88c5853361a06104c9ceb35b45cef760014904671014a193f40c15fc244")
400                .unwrap();
401
402        let output_prk = HASH256::hkdf_extract(&salt, &ikm).to_vec();
403        assert_eq!(expected_prk, output_prk);
404
405        let info = hex::decode("b0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff")
406            .unwrap();
407        let l = 82;
408        let expected_okm = hex::decode("b11e398dc80327a1c8e7f78c596a49344f012eda2d4efad8a050cc4c19afa97c59045a99cac7827271cb41c65e590e09da3275600c2f09b8367793a9aca3db71cc30c58179ec3e87c14c01d5c1f3434f1d87")
409            .unwrap();
410
411        let output_okm = HASH256::hkdf_extend(&expected_prk, &info, l);
412        assert_eq!(expected_okm, output_okm);
413    }
414
415    #[test]
416    fn test_hkdf_case_3() {
417        // From https://tools.ietf.org/html/rfc5869
418        let ikm = hex::decode("0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b").unwrap();
419        let salt = vec![];
420        let expected_prk =
421            hex::decode("19ef24a32c717b167f33a91d6f648bdf96596776afdb6377ac434c1c293ccb04")
422                .unwrap();
423
424        let output_prk = HASH256::hkdf_extract(&salt, &ikm).to_vec();
425        assert_eq!(expected_prk, output_prk);
426
427        let info = vec![];
428        let l = 42;
429        let expected_okm = hex::decode(
430            "8da4e775a563c18f715f802a063c5a31b8a11f5c5ee1879ec3454e5f3c738d2d9d201395faa4b61a96c8",
431        )
432        .unwrap();
433
434        let output_okm = HASH256::hkdf_extend(&expected_prk, &info, l);
435        assert_eq!(expected_okm, output_okm);
436    }
437}