crabcrypt/algorithms/sha2/
sha256.rs

1use 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}