Skip to main content

rns_crypto/
sha256.rs

1use alloc::vec::Vec;
2
3const K: [u32; 64] = [
4    0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5,
5    0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
6    0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
7    0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
8    0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc,
9    0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
10    0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7,
11    0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
12    0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,
13    0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
14    0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3,
15    0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
16    0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5,
17    0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
18    0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
19    0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2,
20];
21
22const H_INIT: [u32; 8] = [
23    0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a,
24    0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19,
25];
26
27#[derive(Clone)]
28pub struct Sha256 {
29    h: [u32; 8],
30    buffer: Vec<u8>,
31    counter: u64,
32}
33
34fn rotr(x: u32, y: u32) -> u32 {
35    (x >> y) | (x << (32 - y))
36}
37
38impl Sha256 {
39    pub fn new() -> Self {
40        Sha256 {
41            h: H_INIT,
42            buffer: Vec::new(),
43            counter: 0,
44        }
45    }
46
47    fn process_block(&mut self, block: &[u8]) {
48        let mut w = [0u32; 64];
49        for i in 0..16 {
50            w[i] = u32::from_be_bytes([
51                block[i * 4],
52                block[i * 4 + 1],
53                block[i * 4 + 2],
54                block[i * 4 + 3],
55            ]);
56        }
57
58        for i in 16..64 {
59            let s0 = rotr(w[i - 15], 7) ^ rotr(w[i - 15], 18) ^ (w[i - 15] >> 3);
60            let s1 = rotr(w[i - 2], 17) ^ rotr(w[i - 2], 19) ^ (w[i - 2] >> 10);
61            w[i] = w[i - 16]
62                .wrapping_add(s0)
63                .wrapping_add(w[i - 7])
64                .wrapping_add(s1);
65        }
66
67        let [mut a, mut b, mut c, mut d, mut e, mut f, mut g, mut h] = self.h;
68
69        for i in 0..64 {
70            let s0 = rotr(a, 2) ^ rotr(a, 13) ^ rotr(a, 22);
71            let maj = (a & b) ^ (a & c) ^ (b & c);
72            let t2 = s0.wrapping_add(maj);
73            let s1 = rotr(e, 6) ^ rotr(e, 11) ^ rotr(e, 25);
74            let ch = (e & f) ^ ((!e) & g);
75            let t1 = h
76                .wrapping_add(s1)
77                .wrapping_add(ch)
78                .wrapping_add(K[i])
79                .wrapping_add(w[i]);
80
81            h = g;
82            g = f;
83            f = e;
84            e = d.wrapping_add(t1);
85            d = c;
86            c = b;
87            b = a;
88            a = t1.wrapping_add(t2);
89        }
90
91        self.h[0] = self.h[0].wrapping_add(a);
92        self.h[1] = self.h[1].wrapping_add(b);
93        self.h[2] = self.h[2].wrapping_add(c);
94        self.h[3] = self.h[3].wrapping_add(d);
95        self.h[4] = self.h[4].wrapping_add(e);
96        self.h[5] = self.h[5].wrapping_add(f);
97        self.h[6] = self.h[6].wrapping_add(g);
98        self.h[7] = self.h[7].wrapping_add(h);
99    }
100
101    pub fn update(&mut self, data: &[u8]) {
102        if data.is_empty() {
103            return;
104        }
105        self.buffer.extend_from_slice(data);
106        self.counter += data.len() as u64;
107
108        while self.buffer.len() >= 64 {
109            let block: Vec<u8> = self.buffer.drain(..64).collect();
110            self.process_block(&block);
111        }
112    }
113
114    pub fn digest(&self) -> [u8; 32] {
115        let mut clone = self.clone();
116        let mdi = clone.counter & 0x3F;
117        let length = (clone.counter << 3).to_be_bytes();
118
119        let padlen = if mdi < 56 { 55 - mdi } else { 119 - mdi };
120
121        let mut padding = Vec::with_capacity(padlen as usize + 9);
122        padding.push(0x80);
123        for _ in 0..padlen {
124            padding.push(0x00);
125        }
126        padding.extend_from_slice(&length);
127        clone.update(&padding);
128
129        let mut result = [0u8; 32];
130        for (i, &val) in clone.h.iter().enumerate() {
131            result[i * 4..i * 4 + 4].copy_from_slice(&val.to_be_bytes());
132        }
133        result
134    }
135}
136
137pub fn sha256(data: &[u8]) -> [u8; 32] {
138    let mut hasher = Sha256::new();
139    hasher.update(data);
140    hasher.digest()
141}
142
143#[cfg(test)]
144mod tests {
145    use super::*;
146
147    #[test]
148    fn test_sha256_empty() {
149        let expected = [
150            0xe3, 0xb0, 0xc4, 0x42, 0x98, 0xfc, 0x1c, 0x14,
151            0x9a, 0xfb, 0xf4, 0xc8, 0x99, 0x6f, 0xb9, 0x24,
152            0x27, 0xae, 0x41, 0xe4, 0x64, 0x9b, 0x93, 0x4c,
153            0xa4, 0x95, 0x99, 0x1b, 0x78, 0x52, 0xb8, 0x55,
154        ];
155        assert_eq!(sha256(b""), expected);
156    }
157
158    #[test]
159    fn test_sha256_abc() {
160        let expected = [
161            0xba, 0x78, 0x16, 0xbf, 0x8f, 0x01, 0xcf, 0xea,
162            0x41, 0x41, 0x40, 0xde, 0x5d, 0xae, 0x22, 0x23,
163            0xb0, 0x03, 0x61, 0xa3, 0x96, 0x17, 0x7a, 0x9c,
164            0xb4, 0x10, 0xff, 0x61, 0xf2, 0x00, 0x15, 0xad,
165        ];
166        assert_eq!(sha256(b"abc"), expected);
167    }
168
169    #[test]
170    fn test_sha256_long() {
171        // SHA-256 of 1000 'a' bytes
172        let data = [b'a'; 1000];
173        let result = sha256(&data);
174        // Known value: sha256("a" * 1000)
175        let expected = [
176            0x41, 0xed, 0xec, 0xe4, 0x2d, 0x63, 0xe8, 0xd9,
177            0xbf, 0x51, 0x5a, 0x9b, 0xa6, 0x93, 0x2e, 0x1c,
178            0x20, 0xcb, 0xc9, 0xf5, 0xa5, 0xd1, 0x34, 0x64,
179            0x5a, 0xdb, 0x5d, 0xb1, 0xb9, 0x73, 0x7e, 0xa3,
180        ];
181        assert_eq!(result, expected);
182    }
183
184    #[test]
185    fn test_sha256_incremental() {
186        let mut hasher = Sha256::new();
187        hasher.update(b"ab");
188        hasher.update(b"c");
189        assert_eq!(hasher.digest(), sha256(b"abc"));
190    }
191}