1mod sha_cfg;
2
3use crate::sha::sha_cfg::{
4 HASH224_INIT_VALUES, HASH256_INIT_VALUES, HASH384_INIT_VALUES, HASH512_INIT_VALUES, K_224_256,
5 K_384_512,
6};
7use std::{u128, usize};
8
9#[cfg(test)]
10mod sha_tests {
11 use super::{sha, ShaType};
12 #[test]
13 fn sha224() {
14 let message: String = String::from("SUNYSUNYSUNYSUNY");
15 let hash_bytes: Vec<u8> = sha(&message, ShaType::SHA224);
16 let mut hash_hex_str: String = String::new();
17
18 for byte in hash_bytes {
19 hash_hex_str.push_str(&format!("{:02x}", byte))
20 }
21
22 assert_eq!(
23 hash_hex_str,
24 String::from("678669c52c658fba0da32398376f700f367d2adf82291a269308f168")
25 );
26 }
27
28 #[test]
29 fn sha256() {
30 let message: String = String::from("SUNYSUNYSUNYSUNY");
31 let hash_bytes: Vec<u8> = sha(&message, ShaType::SHA256);
32 let mut hash_hex_str: String = String::new();
33
34 for byte in hash_bytes {
35 hash_hex_str.push_str(&format!("{:02x}", byte))
36 }
37
38 assert_eq!(
39 hash_hex_str,
40 String::from("142ea313267fe7670d878726214c30b6850a1e189edeff9cd4f769ba02371180")
41 );
42 }
43
44 #[test]
45 fn sha384() {
46 let message: String = String::from("SUNYSUNYSUNYSUNYSUNYSUNYSUNYSUNY");
47
48 let hash_bytes: Vec<u8> = sha(&message, ShaType::SHA384);
49 let mut hash_hex_str: String = String::new();
50
51 for byte in hash_bytes {
52 hash_hex_str.push_str(&format!("{:02x}", byte))
53 }
54
55 assert_eq!(
56 hash_hex_str,
57 String::from("b206401fad03e08d606bce8eab03f5116e01963dc5af6c8162b4020bc2a98c1ed7417399a0d611d259c04a6e6868f0e4")
58 );
59 }
60 #[test]
61 fn sha512() {
62 let message: String = String::from("SUNYSUNYSUNYSUNYSUNYSUNYSUNYSUNY");
63 let hash_bytes: Vec<u8> = sha(&message, ShaType::SHA512);
64 let mut hash_hex_str: String = String::new();
65
66 for byte in hash_bytes {
67 hash_hex_str.push_str(&format!("{:02x}", byte))
68 }
69
70 assert_eq!(
71 hash_hex_str,
72 String::from("e8d877cad3ada1877203bec43cad9fe6fba800b91afcf874069d0c5559ac4efd3645009564fe7490c0f13c6aa4c069e0d3aed4ea2dc36af77696008602ff459e")
73 );
74 }
75}
76pub enum ShaType {
77 SHA224,
78 SHA256,
79 SHA384,
80 SHA512,
81}
82
83pub fn sha(message: &str, sha_type: ShaType) -> Vec<u8> {
84 let mut message_padding: Vec<u8> = Vec::from(message);
85
86 padding(&mut message_padding, &sha_type);
88
89 let mut res: Vec<u8> = Vec::new();
90
91 match sha_type {
92 ShaType::SHA224 => {
93 let hash: [u32; 8] = iteration_64(&message_padding, &HASH224_INIT_VALUES, &K_224_256);
94 for word in hash.into_iter().take(7) {
95 res.append(&mut word.to_be_bytes().to_vec());
96 }
97 }
98 ShaType::SHA256 => {
99 let hash: [u32; 8] = iteration_64(&message_padding, &HASH256_INIT_VALUES, &K_224_256);
100 for word in hash {
101 res.append(&mut word.to_be_bytes().to_vec());
102 }
103 }
104 ShaType::SHA384 => {
105 let hash: [u64; 8] = iteration_80(&message_padding, &HASH384_INIT_VALUES, &K_384_512);
106 for word in hash.into_iter().take(6) {
107 res.append(&mut word.to_be_bytes().to_vec());
108 }
109 }
110 ShaType::SHA512 => {
111 let hash: [u64; 8] = iteration_80(&message_padding, &HASH512_INIT_VALUES, &K_384_512);
112 for word in hash {
113 res.append(&mut word.to_be_bytes().to_vec());
114 }
115 }
116 };
117
118 res
119}
120
121fn padding(message: &mut Vec<u8>, sha_type: &ShaType) {
122 let alignment: u32;
123 let remainer_expect: u32;
124 let message_bits = (message.len() as u32) * u8::BITS;
125 let mut message_length: Vec<u8>;
126
127 match sha_type {
128 ShaType::SHA224 | ShaType::SHA256 => {
129 alignment = 512;
130 remainer_expect = alignment - u64::BITS;
131 message_length = Vec::from((message_bits as u64).to_be_bytes());
132 }
133 ShaType::SHA384 | ShaType::SHA512 => {
134 alignment = 1024;
135 remainer_expect = alignment - u128::BITS;
136 message_length = Vec::from((message_bits as u128).to_be_bytes());
137 }
138 };
139
140 let remainer = message_bits % alignment;
141
142 let bits_padding = if remainer == remainer_expect {
143 alignment
144 } else {
145 if remainer > remainer_expect {
146 alignment + remainer_expect - remainer
147 } else {
148 remainer_expect - remainer
149 }
150 };
151
152 message.push(0x80);
154
155 for _ in 1..(bits_padding as u32) / u8::BITS {
157 message.push(0x00);
158 }
159
160 message.append(&mut message_length);
162}
163
164fn iteration_64(message_padding: &[u8], hash_init_values: &[u32; 8], k: &[u32; 64]) -> [u32; 8] {
165 let mut w: [u32; 64] = [0; 64];
166 let mut m: Vec<u32> = Vec::new();
167 let mut hash: [u32; 8] = hash_init_values.clone();
168
169 for chunk in message_padding.chunks((u32::BITS / u8::BITS) as usize) {
171 m.push(u32::from_be_bytes(
172 chunk.try_into().expect("Convert bytes to u32 failed!"),
173 ));
174 }
175
176 let msg_total_bits: usize = m.len() * u32::BITS as usize;
177 let msg_blocks_num: usize = msg_total_bits / 512;
178
179 for mi in 0..msg_blocks_num {
181 for i in 0..16 {
182 w[i] = m[(mi * 16)..(mi * 16 + 16)][i];
183 }
184
185 for i in 16..64 {
186 let s0: u32 = w[i - 15].rotate_right(7) ^ w[i - 15].rotate_right(18) ^ (w[i - 15] >> 3);
187 let s1: u32 = w[i - 2].rotate_right(17) ^ w[i - 2].rotate_right(19) ^ (w[i - 2] >> 10);
188 w[i] = s1 + w[i - 7] + s0 + w[i - 16];
189 }
190
191 let mut a: u32 = hash[0];
192 let mut b: u32 = hash[1];
193 let mut c: u32 = hash[2];
194 let mut d: u32 = hash[3];
195 let mut e: u32 = hash[4];
196 let mut f: u32 = hash[5];
197 let mut g: u32 = hash[6];
198 let mut h: u32 = hash[7];
199
200 for i in 0..64 {
201 let s0: u32 = a.rotate_right(2) ^ a.rotate_right(13) ^ a.rotate_right(22);
202 let s1: u32 = e.rotate_right(6) ^ e.rotate_right(11) ^ e.rotate_right(25);
203 let maj: u32 = (a & b) ^ (a & c) ^ (b & c);
204 let ch: u32 = (e & f) ^ ((!e) & g);
205 let t1: u32 = h + s1 + ch + k[i] + w[i];
206 let t2: u32 = s0 + maj;
207
208 h = g;
209 g = f;
210 f = e;
211 e = d + t1;
212 d = c;
213 c = b;
214 b = a;
215 a = t1 + t2;
216 }
217
218 hash[0] += a;
219 hash[1] += b;
220 hash[2] += c;
221 hash[3] += d;
222 hash[4] += e;
223 hash[5] += f;
224 hash[6] += g;
225 hash[7] += h;
226 }
227 hash
228}
229
230fn iteration_80(message_padding: &[u8], hash_init_values: &[u64; 8], k: &[u64; 80]) -> [u64; 8] {
231 let mut w: [u64; 80] = [0; 80];
232 let mut m: Vec<u64> = Vec::new();
233 let mut hash = hash_init_values.clone();
234
235 for chunk in message_padding.chunks((u64::BITS / u8::BITS) as usize) {
237 m.push(u64::from_be_bytes(
238 chunk.try_into().expect("Convert bytes to u64 failed!"),
239 ));
240 }
241
242 let msg_total_bits: usize = m.len() * u64::BITS as usize;
243 let msg_blocks_num: usize = msg_total_bits / 1024;
244
245 for mi in 0..msg_blocks_num {
247 for i in 0..16 {
248 w[i] = m[(mi * 16)..(mi * 16 + 16)][i];
249 }
250
251 for i in 16..80 {
252 let s0: u64 = w[i - 15].rotate_right(1) ^ w[i - 15].rotate_right(8) ^ (w[i - 15] >> 7);
253 let s1: u64 = w[i - 2].rotate_right(19) ^ w[i - 2].rotate_right(61) ^ (w[i - 2] >> 6);
254 w[i] = s1 + w[i - 16] + s0 + w[i - 7];
255 }
256
257 let mut a: u64 = hash[0];
258 let mut b: u64 = hash[1];
259 let mut c: u64 = hash[2];
260 let mut d: u64 = hash[3];
261 let mut e: u64 = hash[4];
262 let mut f: u64 = hash[5];
263 let mut g: u64 = hash[6];
264 let mut h: u64 = hash[7];
265
266 for i in 0..80 {
267 let s0: u64 = a.rotate_right(28) ^ a.rotate_right(34) ^ a.rotate_right(39);
268 let s1: u64 = e.rotate_right(14) ^ e.rotate_right(18) ^ e.rotate_right(41);
269 let maj: u64 = (a & b) ^ (a & c) ^ (b & c);
270 let ch: u64 = (e & f) ^ ((!e) & g);
271 let t1: u64 = h + s1 + ch + k[i] + w[i];
272 let t2: u64 = s0 + maj;
273
274 h = g;
275 g = f;
276 f = e;
277 e = d + t1;
278 d = c;
279 c = b;
280 b = a;
281 a = t1 + t2;
282 }
283
284 hash[0] += a;
285 hash[1] += b;
286 hash[2] += c;
287 hash[3] += d;
288 hash[4] += e;
289 hash[5] += f;
290 hash[6] += g;
291 hash[7] += h;
292 }
293
294 hash
295}