crabcrypt/algorithms/sha2/
sha256.rs1use crate::BinaryToTextEncoding;
2use crate::utils::encoders::{to_base32, to_base64, to_base64url, to_binary_string, to_hex_string};
3
4#[derive(Copy, Clone)]
5pub struct Sha256 {
6 data: [u8; 64],
7 datalen: usize,
8 bitlen: u64,
9 state: [u32; 8],
10}
11
12impl Sha256 {
13 pub fn new() -> Self {
14 Self {
15 data: [0; 64],
16 datalen: 0,
17 bitlen: 0,
18 state: [
19 0x6a09e667,
20 0xbb67ae85,
21 0x3c6ef372,
22 0xa54ff53a,
23 0x510e527f,
24 0x9b05688c,
25 0x1f83d9ab,
26 0x5be0cd19,
27 ],
28 }
29 }
30
31 pub fn update(&mut self, data: &[u8]) -> Self {
32 let mut i = 0usize;
33 while i < data.len() {
34 self.data[self.datalen] = data[i];
35 self.datalen += 1;
36 if self.datalen == 64 {
37 self.transform();
38 self.bitlen += 512;
39 self.datalen = 0;
40 }
41 i += 1;
42 }
43 *self
44 }
45
46 pub fn digest(&mut self, encoding: BinaryToTextEncoding) -> String {
47 let i = self.datalen;
48 if self.datalen < 56 {
49 self.data[i] = 0x80;
50 for j in i+1..56 {
51 self.data[j] = 0x00;
52 }
53 } else {
54 self.data[i] = 0x80;
55 for j in i+1..64 {
56 self.data[j] = 0x00;
57 }
58 self.transform();
59 for j in 0..56 {
60 self.data[j] = 0x00;
61 }
62 }
63
64 self.bitlen += self.datalen as u64 * 8;
65 self.data[63] = self.bitlen as u8;
66 self.data[62] = (self.bitlen >> 8) as u8;
67 self.data[61] = (self.bitlen >> 16) as u8;
68 self.data[60] = (self.bitlen >> 24) as u8;
69 self.data[59] = (self.bitlen >> 32) as u8;
70 self.data[58] = (self.bitlen >> 40) as u8;
71 self.data[57] = (self.bitlen >> 48) as u8;
72 self.data[56] = (self.bitlen >> 56) as u8;
73 self.transform();
74
75 let mut hash: [u8; 32] = [0; 32];
76 for i in 0..4 {
77 hash[i] = (self.state[0] >> (24 - i * 8)) as u8;
78 hash[i + 4] = (self.state[1] >> (24 - i * 8)) as u8;
79 hash[i + 8] = (self.state[2] >> (24 - i * 8)) as u8;
80 hash[i + 12] = (self.state[3] >> (24 - i * 8)) as u8;
81 hash[i + 16] = (self.state[4] >> (24 - i * 8)) as u8;
82 hash[i + 20] = (self.state[5] >> (24 - i * 8)) as u8;
83 hash[i + 24] = (self.state[6] >> (24 - i * 8)) as u8;
84 hash[i + 28] = (self.state[7] >> (24 - i * 8)) as u8;
85 }
86
87 match encoding {
88 BinaryToTextEncoding::Base32 => to_base32(&hash),
89 BinaryToTextEncoding::Base64 => to_base64(&hash),
90 BinaryToTextEncoding::Base64Url => to_base64url(to_base64(&hash)),
91 BinaryToTextEncoding::Hex => to_hex_string(&hash),
92 BinaryToTextEncoding::Binary => to_binary_string(&hash),
93 }
94 }
95
96 fn transform(&mut self) {
97 let k: [u32; 64] = [
98 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
99 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
100 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
101 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
102 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
103 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
104 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
105 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
106 ];
107 let mut m: [u32; 64] = [0; 64];
108 let mut a: u32;
109 let mut b: u32;
110 let mut c: u32;
111 let mut d: u32;
112 let mut e: u32;
113 let mut f: u32;
114 let mut g: u32;
115 let mut h: u32;
116 let mut t1: u32;
117 let mut t2: u32;
118
119 for i in 0..16 {
120 let j = i * 4;
121 m[i] = ((self.data[j] as u32) << 24) | ((self.data[j + 1] as u32) << 16)
122 | ((self.data[j + 2] as u32) << 8) | (self.data[j + 3] as u32);
123 }
124
125 for i in 16..64 {
126 let s0 = self.rotate_right(m[i - 15], 7) ^ self.rotate_right(m[i - 15], 18) ^ (m[i - 15] >> 3);
127 let s1 = self.rotate_right(m[i - 2], 17) ^ self.rotate_right(m[i - 2], 19) ^ (m[i - 2] >> 10);
128 m[i] = m[i - 16].wrapping_add(s0).wrapping_add(m[i - 7]).wrapping_add(s1);
129 }
130
131 a = self.state[0];
132 b = self.state[1];
133 c = self.state[2];
134 d = self.state[3];
135 e = self.state[4];
136 f = self.state[5];
137 g = self.state[6];
138 h = self.state[7];
139
140 for i in 0..64 {
141 let s1 = self.rotate_right(e, 6) ^ self.rotate_right(e, 11) ^ self.rotate_right(e, 25);
142 let ch = (e & f) ^ (!e & g);
143 t1 = h.wrapping_add(s1).wrapping_add(ch).wrapping_add(k[i]).wrapping_add(m[i]);
144 let s0 = self.rotate_right(a, 2) ^ self.rotate_right(a, 13) ^ self.rotate_right(a, 22);
145 let maj = (a & b) ^ (a & c) ^ (b & c);
146 t2 = s0.wrapping_add(maj);
147
148 h = g;
149 g = f;
150 f = e;
151 e = d.wrapping_add(t1);
152 d = c;
153 c = b;
154 b = a;
155 a = t1.wrapping_add(t2);
156 }
157
158 self.state[0] = self.state[0].wrapping_add(a);
159 self.state[1] = self.state[1].wrapping_add(b);
160 self.state[2] = self.state[2].wrapping_add(c);
161 self.state[3] = self.state[3].wrapping_add(d);
162 self.state[4] = self.state[4].wrapping_add(e);
163 self.state[5] = self.state[5].wrapping_add(f);
164 self.state[6] = self.state[6].wrapping_add(g);
165 self.state[7] = self.state[7].wrapping_add(h);
166 }
167
168 fn rotate_right(&mut self, x: u32, n: u32) -> u32 {
169 (x >> n) | (x << (32 - n))
170 }
171}
172
173#[cfg(test)]
174mod tests {
175 use super::*;
176
177 #[test]
178 fn test_sha256() {
179 let sut = Sha256::new()
180 .update(b"hello world")
181 .digest(BinaryToTextEncoding::Hex);
182 assert_eq!(sut, "b94d27b9934d3e08a52e52d7da7dabfac484efe37a5380ee9088f7ace2efcde9");
183 }
184}