| /* |
| Licensed to the Apache Software Foundation (ASF) under one |
| or more contributor license agreements. See the NOTICE file |
| distributed with this work for additional information |
| regarding copyright ownership. The ASF licenses this file |
| to you under the Apache License, Version 2.0 (the |
| "License"); you may not use this file except in compliance |
| with the License. You may obtain a copy of the License at |
| |
| http://www.apache.org/licenses/LICENSE-2.0 |
| |
| Unless required by applicable law or agreed to in writing, |
| software distributed under the License is distributed on an |
| "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| KIND, either express or implied. See the License for the |
| specific language governing permissions and limitations |
| under the License. |
| */ |
| |
| pub const HASH224: usize = 28; |
| pub const HASH256: usize = 32; |
| pub const HASH384: usize = 48; |
| pub const HASH512: usize = 64; |
| pub const SHAKE128: usize = 16; |
| pub const SHAKE256: usize = 32; |
| |
| const ROUNDS: usize = 24; |
| |
| const RC: [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, |
| ]; |
| |
| pub struct SHA3 { |
| length: u64, |
| rate: usize, |
| len: usize, |
| s: [[u64; 5]; 5], |
| } |
| |
| impl SHA3 { |
| fn rotl(x: u64, n: u64) -> u64 { |
| return ((x) << n) | ((x) >> (64 - n)); |
| } |
| |
| fn transform(&mut self) { |
| /* basic transformation step */ |
| let mut c: [u64; 5] = [0; 5]; |
| let mut d: [u64; 5] = [0; 5]; |
| let mut b: [[u64; 5]; 5] = [[0; 5]; 5]; |
| |
| for k in 0..ROUNDS { |
| c[0] = self.s[0][0] ^ self.s[0][1] ^ self.s[0][2] ^ self.s[0][3] ^ self.s[0][4]; |
| c[1] = self.s[1][0] ^ self.s[1][1] ^ self.s[1][2] ^ self.s[1][3] ^ self.s[1][4]; |
| c[2] = self.s[2][0] ^ self.s[2][1] ^ self.s[2][2] ^ self.s[2][3] ^ self.s[2][4]; |
| c[3] = self.s[3][0] ^ self.s[3][1] ^ self.s[3][2] ^ self.s[3][3] ^ self.s[3][4]; |
| c[4] = self.s[4][0] ^ self.s[4][1] ^ self.s[4][2] ^ self.s[4][3] ^ self.s[4][4]; |
| |
| d[0] = c[4] ^ SHA3::rotl(c[1], 1); |
| d[1] = c[0] ^ SHA3::rotl(c[2], 1); |
| d[2] = c[1] ^ SHA3::rotl(c[3], 1); |
| d[3] = c[2] ^ SHA3::rotl(c[4], 1); |
| d[4] = c[3] ^ SHA3::rotl(c[0], 1); |
| |
| for i in 0..5 { |
| for j in 0..5 { |
| self.s[i][j] ^= d[i]; |
| } |
| } |
| |
| b[0][0] = self.s[0][0]; |
| b[1][3] = SHA3::rotl(self.s[0][1], 36); |
| b[2][1] = SHA3::rotl(self.s[0][2], 3); |
| b[3][4] = SHA3::rotl(self.s[0][3], 41); |
| b[4][2] = SHA3::rotl(self.s[0][4], 18); |
| |
| b[0][2] = SHA3::rotl(self.s[1][0], 1); |
| b[1][0] = SHA3::rotl(self.s[1][1], 44); |
| b[2][3] = SHA3::rotl(self.s[1][2], 10); |
| b[3][1] = SHA3::rotl(self.s[1][3], 45); |
| b[4][4] = SHA3::rotl(self.s[1][4], 2); |
| |
| b[0][4] = SHA3::rotl(self.s[2][0], 62); |
| b[1][2] = SHA3::rotl(self.s[2][1], 6); |
| b[2][0] = SHA3::rotl(self.s[2][2], 43); |
| b[3][3] = SHA3::rotl(self.s[2][3], 15); |
| b[4][1] = SHA3::rotl(self.s[2][4], 61); |
| |
| b[0][1] = SHA3::rotl(self.s[3][0], 28); |
| b[1][4] = SHA3::rotl(self.s[3][1], 55); |
| b[2][2] = SHA3::rotl(self.s[3][2], 25); |
| b[3][0] = SHA3::rotl(self.s[3][3], 21); |
| b[4][3] = SHA3::rotl(self.s[3][4], 56); |
| |
| b[0][3] = SHA3::rotl(self.s[4][0], 27); |
| b[1][1] = SHA3::rotl(self.s[4][1], 20); |
| b[2][4] = SHA3::rotl(self.s[4][2], 39); |
| b[3][2] = SHA3::rotl(self.s[4][3], 8); |
| b[4][0] = SHA3::rotl(self.s[4][4], 14); |
| |
| for i in 0..5 { |
| for j in 0..5 { |
| self.s[i][j] = b[i][j] ^ (!b[(i + 1) % 5][j] & b[(i + 2) % 5][j]); |
| } |
| } |
| |
| self.s[0][0] ^= RC[k]; |
| } |
| } |
| |
| /* Initialise Hash function */ |
| pub fn init(&mut self, olen: usize) { |
| /* initialise */ |
| for i in 0..5 { |
| for j in 0..5 { |
| self.s[i][j] = 0; |
| } |
| } |
| self.length = 0; |
| self.len = olen; |
| self.rate = 200 - 2 * olen; |
| } |
| |
| pub fn new(olen: usize) -> SHA3 { |
| let mut nh = SHA3 { |
| length: 0, |
| rate: 0, |
| len: 0, |
| s: [[0; 5]; 5], |
| }; |
| nh.init(olen); |
| return nh; |
| } |
| |
| /* process a single byte */ |
| pub fn process(&mut self, byt: u8) { |
| /* process the next message byte */ |
| let cnt = (self.length % (self.rate as u64)) as usize; |
| let b = cnt % 8; |
| let ind = cnt / 8; |
| let i = ind % 5; |
| let j = ind / 5; |
| self.s[i][j] ^= ((byt & 0xff) as u64) << (8 * b); |
| self.length += 1; |
| if cnt + 1 == self.rate { |
| self.transform(); |
| } |
| } |
| |
| pub fn squeeze(&mut self, buff: &mut [u8], olen: usize) { |
| //let olen=buff.len(); |
| let mut done = false; |
| let mut m = 0; |
| loop { |
| for j in 0..5 { |
| for i in 0..5 { |
| let mut el = self.s[i][j]; |
| for _ in 0..8 { |
| buff[m] = (el & 0xff) as u8; |
| m += 1; |
| if m >= olen || (m % self.rate) == 0 { |
| done = true; |
| break; |
| } |
| el >>= 8; |
| } |
| if done { |
| break; |
| } |
| } |
| if done { |
| break; |
| } |
| } |
| if m >= olen { |
| break; |
| } |
| done = false; |
| self.transform(); |
| } |
| } |
| |
| /* Generate 32-byte Hash */ |
| pub fn hash(&mut self, digest: &mut [u8]) { |
| /* pad message and finish - supply digest */ |
| let q = self.rate - (self.length % (self.rate as u64)) as usize; |
| if q == 1 { |
| self.process(0x86); |
| } else { |
| self.process(0x06); |
| while (self.length % (self.rate as u64)) as usize != self.rate - 1 { |
| self.process(0x00) |
| } |
| self.process(0x80); |
| } |
| let hlen = self.len as usize; |
| self.squeeze(digest, hlen); |
| } |
| |
| pub fn shake(&mut self, digest: &mut [u8], olen: usize) { |
| let q = self.rate - (self.length % (self.rate as u64)) as usize; |
| if q == 1 { |
| self.process(0x9f); |
| } else { |
| self.process(0x1f); |
| while (self.length % (self.rate as u64)) as usize != self.rate - 1 { |
| self.process(0x00) |
| } |
| self.process(0x80); |
| } |
| self.squeeze(digest, olen); |
| } |
| } |
| |
| //916f6061fe879741ca6469b43971dfdb28b1a32dc36cb3254e812be27aad1d18 |
| //afebb2ef542e6579c50cad06d2e578f9f8dd6881d7dc824d26360feebf18a4fa73e3261122948efcfd492e74e82e2189ed0fb440d187f382270cb455f21dd185 |
| //98be04516c04cc73593fef3ed0352ea9f6443942d6950e29a372a681c3deaf4535423709b02843948684e029010badcc0acd8303fc85fdad3eabf4f78cae165635f57afd28810fc2 |
| /* |
| fn main() { |
| let s = String::from("abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu"); |
| let mut digest: [u8;100]=[0;100]; |
| let test = s.into_bytes(); |
| |
| let mut sh=SHA3::new(HASH256); |
| for i in 0..test.len(){ |
| sh.process(test[i]); |
| } |
| sh.hash(&mut digest); |
| for i in 0..32 {print!("{:02x}",digest[i])} |
| println!(""); |
| |
| sh=SHA3::new(HASH512); |
| for i in 0..test.len(){ |
| sh.process(test[i]); |
| } |
| sh.hash(&mut digest); |
| for i in 0..64 {print!("{:02x}",digest[i])} |
| println!(""); |
| |
| sh=SHA3::new(SHAKE256); |
| for i in 0..test.len(){ |
| sh.process(test[i]); |
| } |
| sh.shake(&mut digest,72); |
| for i in 0..72 {print!("{:02x}",digest[i])} |
| println!(""); |
| |
| } */ |