1#![allow(dead_code, clippy::wrong_self_convention)]
7
8use alloc::vec::Vec;
9
10use super::CryptoResult;
11
12#[derive(Debug, Clone, Copy, PartialEq, Eq)]
14pub(crate) enum HashAlgorithm {
15 Sha256,
16 Sha512,
17 Blake3,
18}
19
20#[derive(Debug, Clone, Copy, PartialEq, Eq)]
22pub(crate) struct Hash256(pub [u8; 32]);
23
24#[derive(Debug, Clone, PartialEq, Eq)]
26pub(crate) struct Hash512(pub [u8; 64]);
27
28impl Hash256 {
29 pub(crate) fn from_bytes(bytes: &[u8; 32]) -> Self {
31 Self(*bytes)
32 }
33
34 pub(crate) fn as_bytes(&self) -> &[u8; 32] {
36 &self.0
37 }
38
39 pub(crate) fn to_hex(&self) -> alloc::string::String {
41 use alloc::format;
42 let mut s = alloc::string::String::with_capacity(64);
43 for byte in self.0 {
44 s.push_str(&format!("{:02x}", byte));
45 }
46 s
47 }
48}
49
50impl Hash512 {
51 pub(crate) fn from_bytes(bytes: &[u8; 64]) -> Self {
53 Self(*bytes)
54 }
55
56 pub(crate) fn as_bytes(&self) -> &[u8; 64] {
58 &self.0
59 }
60
61 pub(crate) fn to_hex(&self) -> alloc::string::String {
63 use alloc::format;
64 let mut s = alloc::string::String::with_capacity(128);
65 for byte in self.0 {
66 s.push_str(&format!("{:02x}", byte));
67 }
68 s
69 }
70}
71
72pub(crate) fn hash(algorithm: HashAlgorithm, data: &[u8]) -> CryptoResult<Vec<u8>> {
74 match algorithm {
75 HashAlgorithm::Sha256 => {
76 let hash = sha256(data);
77 Ok(hash.0.to_vec())
78 }
79 HashAlgorithm::Sha512 => {
80 let hash = sha512(data);
81 Ok(hash.0.to_vec())
82 }
83 HashAlgorithm::Blake3 => {
84 let hash = blake3(data);
85 Ok(hash.0.to_vec())
86 }
87 }
88}
89
90const SHA256_K: [u32; 64] = [
93 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
94 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
95 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
96 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
97 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
98 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
99 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
100 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2,
101];
102
103const SHA256_H0: [u32; 8] = [
106 0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19,
107];
108
109fn sha256_process_block(h: &mut [u32; 8], block: &[u8]) {
111 let mut w = [0u32; 64];
112
113 for (i, word_bytes) in block.chunks(4).enumerate().take(16) {
115 w[i] = u32::from_be_bytes([word_bytes[0], word_bytes[1], word_bytes[2], word_bytes[3]]);
116 }
117
118 for i in 16..64 {
120 let s0 = w[i - 15].rotate_right(7) ^ w[i - 15].rotate_right(18) ^ (w[i - 15] >> 3);
121 let s1 = w[i - 2].rotate_right(17) ^ w[i - 2].rotate_right(19) ^ (w[i - 2] >> 10);
122 w[i] = w[i - 16]
123 .wrapping_add(s0)
124 .wrapping_add(w[i - 7])
125 .wrapping_add(s1);
126 }
127
128 let (mut a, mut b, mut c, mut d, mut e, mut f, mut g, mut hh) =
130 (h[0], h[1], h[2], h[3], h[4], h[5], h[6], h[7]);
131
132 for i in 0..64 {
134 let s1 = e.rotate_right(6) ^ e.rotate_right(11) ^ e.rotate_right(25);
135 let ch = (e & f) ^ ((!e) & g);
136 let temp1 = hh
137 .wrapping_add(s1)
138 .wrapping_add(ch)
139 .wrapping_add(SHA256_K[i])
140 .wrapping_add(w[i]);
141 let s0 = a.rotate_right(2) ^ a.rotate_right(13) ^ a.rotate_right(22);
142 let maj = (a & b) ^ (a & c) ^ (b & c);
143 let temp2 = s0.wrapping_add(maj);
144
145 hh = g;
146 g = f;
147 f = e;
148 e = d.wrapping_add(temp1);
149 d = c;
150 c = b;
151 b = a;
152 a = temp1.wrapping_add(temp2);
153 }
154
155 h[0] = h[0].wrapping_add(a);
157 h[1] = h[1].wrapping_add(b);
158 h[2] = h[2].wrapping_add(c);
159 h[3] = h[3].wrapping_add(d);
160 h[4] = h[4].wrapping_add(e);
161 h[5] = h[5].wrapping_add(f);
162 h[6] = h[6].wrapping_add(g);
163 h[7] = h[7].wrapping_add(hh);
164}
165
166pub(crate) fn sha256(data: &[u8]) -> Hash256 {
168 let mut h = SHA256_H0;
169 let original_len_bits = (data.len() as u64) * 8;
170
171 let full_blocks = data.len() / 64;
173 for i in 0..full_blocks {
174 sha256_process_block(&mut h, &data[i * 64..(i + 1) * 64]);
175 }
176
177 let remainder = data.len() % 64;
179 let mut final_buf = [0u8; 128]; final_buf[..remainder].copy_from_slice(&data[full_blocks * 64..]);
181
182 final_buf[remainder] = 0x80;
184
185 let padded_len = remainder + 1;
186
187 if padded_len <= 56 {
188 final_buf[56..64].copy_from_slice(&original_len_bits.to_be_bytes());
190 sha256_process_block(&mut h, &final_buf[..64]);
191 } else {
192 sha256_process_block(&mut h, &final_buf[..64]);
194 final_buf[64..120].fill(0);
196 final_buf[120..128].copy_from_slice(&original_len_bits.to_be_bytes());
197 sha256_process_block(&mut h, &final_buf[64..128]);
198 }
199
200 let mut result = [0u8; 32];
202 for (i, &val) in h.iter().enumerate() {
203 result[i * 4..(i + 1) * 4].copy_from_slice(&val.to_be_bytes());
204 }
205
206 Hash256(result)
207}
208
209const SHA512_K: [u64; 80] = [
212 0x428a2f98d728ae22,
213 0x7137449123ef65cd,
214 0xb5c0fbcfec4d3b2f,
215 0xe9b5dba58189dbbc,
216 0x3956c25bf348b538,
217 0x59f111f1b605d019,
218 0x923f82a4af194f9b,
219 0xab1c5ed5da6d8118,
220 0xd807aa98a3030242,
221 0x12835b0145706fbe,
222 0x243185be4ee4b28c,
223 0x550c7dc3d5ffb4e2,
224 0x72be5d74f27b896f,
225 0x80deb1fe3b1696b1,
226 0x9bdc06a725c71235,
227 0xc19bf174cf692694,
228 0xe49b69c19ef14ad2,
229 0xefbe4786384f25e3,
230 0x0fc19dc68b8cd5b5,
231 0x240ca1cc77ac9c65,
232 0x2de92c6f592b0275,
233 0x4a7484aa6ea6e483,
234 0x5cb0a9dcbd41fbd4,
235 0x76f988da831153b5,
236 0x983e5152ee66dfab,
237 0xa831c66d2db43210,
238 0xb00327c898fb213f,
239 0xbf597fc7beef0ee4,
240 0xc6e00bf33da88fc2,
241 0xd5a79147930aa725,
242 0x06ca6351e003826f,
243 0x142929670a0e6e70,
244 0x27b70a8546d22ffc,
245 0x2e1b21385c26c926,
246 0x4d2c6dfc5ac42aed,
247 0x53380d139d95b3df,
248 0x650a73548baf63de,
249 0x766a0abb3c77b2a8,
250 0x81c2c92e47edaee6,
251 0x92722c851482353b,
252 0xa2bfe8a14cf10364,
253 0xa81a664bbc423001,
254 0xc24b8b70d0f89791,
255 0xc76c51a30654be30,
256 0xd192e819d6ef5218,
257 0xd69906245565a910,
258 0xf40e35855771202a,
259 0x106aa07032bbd1b8,
260 0x19a4c116b8d2d0c8,
261 0x1e376c085141ab53,
262 0x2748774cdf8eeb99,
263 0x34b0bcb5e19b48a8,
264 0x391c0cb3c5c95a63,
265 0x4ed8aa4ae3418acb,
266 0x5b9cca4f7763e373,
267 0x682e6ff3d6b2b8a3,
268 0x748f82ee5defb2fc,
269 0x78a5636f43172f60,
270 0x84c87814a1f0ab72,
271 0x8cc702081a6439ec,
272 0x90befffa23631e28,
273 0xa4506cebde82bde9,
274 0xbef9a3f7b2c67915,
275 0xc67178f2e372532b,
276 0xca273eceea26619c,
277 0xd186b8c721c0c207,
278 0xeada7dd6cde0eb1e,
279 0xf57d4f7fee6ed178,
280 0x06f067aa72176fba,
281 0x0a637dc5a2c898a6,
282 0x113f9804bef90dae,
283 0x1b710b35131c471b,
284 0x28db77f523047d84,
285 0x32caab7b40c72493,
286 0x3c9ebe0a15c9bebc,
287 0x431d67c49c100d4c,
288 0x4cc5d4becb3e42b6,
289 0x597f299cfc657e2a,
290 0x5fcb6fab3ad6faec,
291 0x6c44198c4a475817,
292];
293
294const SHA512_H0: [u64; 8] = [
296 0x6a09e667f3bcc908,
297 0xbb67ae8584caa73b,
298 0x3c6ef372fe94f82b,
299 0xa54ff53a5f1d36f1,
300 0x510e527fade682d1,
301 0x9b05688c2b3e6c1f,
302 0x1f83d9abfb41bd6b,
303 0x5be0cd19137e2179,
304];
305
306fn sha512_process_block(h: &mut [u64; 8], block: &[u8]) {
308 let mut w = [0u64; 80];
309
310 for (i, word_bytes) in block.chunks(8).enumerate().take(16) {
312 w[i] = u64::from_be_bytes([
313 word_bytes[0],
314 word_bytes[1],
315 word_bytes[2],
316 word_bytes[3],
317 word_bytes[4],
318 word_bytes[5],
319 word_bytes[6],
320 word_bytes[7],
321 ]);
322 }
323
324 for i in 16..80 {
326 let s0 = w[i - 15].rotate_right(1) ^ w[i - 15].rotate_right(8) ^ (w[i - 15] >> 7);
327 let s1 = w[i - 2].rotate_right(19) ^ w[i - 2].rotate_right(61) ^ (w[i - 2] >> 6);
328 w[i] = w[i - 16]
329 .wrapping_add(s0)
330 .wrapping_add(w[i - 7])
331 .wrapping_add(s1);
332 }
333
334 let (mut a, mut b, mut c, mut d, mut e, mut f, mut g, mut hh) =
336 (h[0], h[1], h[2], h[3], h[4], h[5], h[6], h[7]);
337
338 for i in 0..80 {
340 let s1 = e.rotate_right(14) ^ e.rotate_right(18) ^ e.rotate_right(41);
341 let ch = (e & f) ^ ((!e) & g);
342 let temp1 = hh
343 .wrapping_add(s1)
344 .wrapping_add(ch)
345 .wrapping_add(SHA512_K[i])
346 .wrapping_add(w[i]);
347 let s0 = a.rotate_right(28) ^ a.rotate_right(34) ^ a.rotate_right(39);
348 let maj = (a & b) ^ (a & c) ^ (b & c);
349 let temp2 = s0.wrapping_add(maj);
350
351 hh = g;
352 g = f;
353 f = e;
354 e = d.wrapping_add(temp1);
355 d = c;
356 c = b;
357 b = a;
358 a = temp1.wrapping_add(temp2);
359 }
360
361 h[0] = h[0].wrapping_add(a);
363 h[1] = h[1].wrapping_add(b);
364 h[2] = h[2].wrapping_add(c);
365 h[3] = h[3].wrapping_add(d);
366 h[4] = h[4].wrapping_add(e);
367 h[5] = h[5].wrapping_add(f);
368 h[6] = h[6].wrapping_add(g);
369 h[7] = h[7].wrapping_add(hh);
370}
371
372pub(crate) fn sha512(data: &[u8]) -> Hash512 {
374 let mut h = SHA512_H0;
375 let original_len_bits = (data.len() as u128) * 8;
376
377 let full_blocks = data.len() / 128;
379 for i in 0..full_blocks {
380 sha512_process_block(&mut h, &data[i * 128..(i + 1) * 128]);
381 }
382
383 let remainder = data.len() % 128;
385 let mut final_buf = [0u8; 256]; final_buf[..remainder].copy_from_slice(&data[full_blocks * 128..]);
387
388 final_buf[remainder] = 0x80;
390
391 let padded_len = remainder + 1;
392
393 if padded_len <= 112 {
394 final_buf[112..128].copy_from_slice(&original_len_bits.to_be_bytes());
396 sha512_process_block(&mut h, &final_buf[..128]);
397 } else {
398 sha512_process_block(&mut h, &final_buf[..128]);
400 final_buf[128..240].fill(0);
401 final_buf[240..256].copy_from_slice(&original_len_bits.to_be_bytes());
402 sha512_process_block(&mut h, &final_buf[128..256]);
403 }
404
405 let mut result = [0u8; 64];
407 for (i, &val) in h.iter().enumerate() {
408 result[i * 8..(i + 1) * 8].copy_from_slice(&val.to_be_bytes());
409 }
410
411 Hash512(result)
412}
413
414const BLAKE3_IV: [u32; 8] = [
416 0x6A09E667, 0xBB67AE85, 0x3C6EF372, 0xA54FF53A, 0x510E527F, 0x9B05688C, 0x1F83D9AB, 0x5BE0CD19,
417];
418
419const BLAKE3_MSG_PERMUTATION: [usize; 16] = [2, 6, 3, 10, 7, 0, 4, 13, 1, 11, 12, 5, 9, 14, 15, 8];
420
421const BLAKE3_CHUNK_START: u32 = 1;
423const BLAKE3_CHUNK_END: u32 = 2;
424const BLAKE3_ROOT: u32 = 8;
425
426#[inline]
428fn blake3_g(state: &mut [u32; 16], a: usize, b: usize, c: usize, d: usize, mx: u32, my: u32) {
429 state[a] = state[a].wrapping_add(state[b]).wrapping_add(mx);
430 state[d] = (state[d] ^ state[a]).rotate_right(16);
431 state[c] = state[c].wrapping_add(state[d]);
432 state[b] = (state[b] ^ state[c]).rotate_right(12);
433 state[a] = state[a].wrapping_add(state[b]).wrapping_add(my);
434 state[d] = (state[d] ^ state[a]).rotate_right(8);
435 state[c] = state[c].wrapping_add(state[d]);
436 state[b] = (state[b] ^ state[c]).rotate_right(7);
437}
438
439fn blake3_round(state: &mut [u32; 16], m: &[u32; 16]) {
441 blake3_g(state, 0, 4, 8, 12, m[0], m[1]);
443 blake3_g(state, 1, 5, 9, 13, m[2], m[3]);
444 blake3_g(state, 2, 6, 10, 14, m[4], m[5]);
445 blake3_g(state, 3, 7, 11, 15, m[6], m[7]);
446 blake3_g(state, 0, 5, 10, 15, m[8], m[9]);
448 blake3_g(state, 1, 6, 11, 12, m[10], m[11]);
449 blake3_g(state, 2, 7, 8, 13, m[12], m[13]);
450 blake3_g(state, 3, 4, 9, 14, m[14], m[15]);
451}
452
453fn blake3_permute(m: &mut [u32; 16]) {
455 let original = *m;
456 for i in 0..16 {
457 m[i] = original[BLAKE3_MSG_PERMUTATION[i]];
458 }
459}
460
461fn blake3_compress(
463 chaining_value: &[u32; 8],
464 block_words: &[u32; 16],
465 counter: u64,
466 block_len: u32,
467 flags: u32,
468) -> [u32; 16] {
469 let mut state = [
470 chaining_value[0],
471 chaining_value[1],
472 chaining_value[2],
473 chaining_value[3],
474 chaining_value[4],
475 chaining_value[5],
476 chaining_value[6],
477 chaining_value[7],
478 BLAKE3_IV[0],
479 BLAKE3_IV[1],
480 BLAKE3_IV[2],
481 BLAKE3_IV[3],
482 counter as u32,
483 (counter >> 32) as u32,
484 block_len,
485 flags,
486 ];
487
488 let mut m = *block_words;
489
490 for _ in 0..7 {
492 blake3_round(&mut state, &m);
493 blake3_permute(&mut m);
494 }
495
496 for i in 0..8 {
498 state[i] ^= state[i + 8];
499 state[i + 8] ^= chaining_value[i];
500 }
501
502 state
503}
504
505pub(crate) fn blake3(data: &[u8]) -> Hash256 {
507 let mut block_words = [0u32; 16];
511 let block_len = core::cmp::min(data.len(), 64) as u32;
512
513 for (i, chunk) in data.chunks(4).take(16).enumerate() {
515 let mut word_bytes = [0u8; 4];
516 let copy_len = core::cmp::min(chunk.len(), 4);
517 word_bytes[..copy_len].copy_from_slice(&chunk[..copy_len]);
518 block_words[i] = u32::from_le_bytes(word_bytes);
519 }
520
521 let flags = BLAKE3_CHUNK_START | BLAKE3_CHUNK_END | BLAKE3_ROOT;
522 let output = blake3_compress(&BLAKE3_IV, &block_words, 0, block_len, flags);
523
524 let mut result = [0u8; 32];
526 for i in 0..8 {
527 result[i * 4..(i + 1) * 4].copy_from_slice(&output[i].to_le_bytes());
528 }
529
530 Hash256(result)
531}
532
533const BLAKE2S_IV: [u32; 8] = [
540 0x6A09E667, 0xBB67AE85, 0x3C6EF372, 0xA54FF53A, 0x510E527F, 0x9B05688C, 0x1F83D9AB, 0x5BE0CD19,
541];
542
543const BLAKE2S_SIGMA: [[usize; 16]; 10] = [
545 [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15],
546 [14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3],
547 [11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4],
548 [7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8],
549 [9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13],
550 [2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9],
551 [12, 5, 1, 15, 14, 13, 4, 10, 0, 7, 6, 3, 9, 2, 8, 11],
552 [13, 11, 7, 14, 12, 1, 3, 9, 5, 0, 15, 4, 8, 6, 2, 10],
553 [6, 15, 14, 9, 11, 3, 0, 8, 12, 2, 13, 7, 1, 4, 10, 5],
554 [10, 2, 8, 4, 7, 6, 1, 5, 15, 11, 9, 14, 3, 12, 13, 0],
555];
556
557#[derive(Clone)]
559pub(crate) struct Blake2s {
560 h: [u32; 8],
561 t: [u32; 2],
562 buf: [u8; 64],
563 buf_len: usize,
564 #[allow(dead_code)]
565 outlen: usize,
566}
567
568impl Blake2s {
569 pub(crate) fn new(outlen: usize) -> Self {
571 assert!((1..=32).contains(&outlen));
572 let mut h = BLAKE2S_IV;
573 h[0] ^= 0x01010000 ^ (outlen as u32);
575 Self {
576 h,
577 t: [0, 0],
578 buf: [0u8; 64],
579 buf_len: 0,
580 outlen,
581 }
582 }
583
584 pub(crate) fn new_keyed(key: &[u8], outlen: usize) -> Self {
586 assert!(!key.is_empty() && key.len() <= 32);
587 assert!((1..=32).contains(&outlen));
588 let mut h = BLAKE2S_IV;
589 h[0] ^= 0x01010000 ^ ((key.len() as u32) << 8) ^ (outlen as u32);
592 let mut state = Self {
593 h,
594 t: [0, 0],
595 buf: [0u8; 64],
596 buf_len: 0,
597 outlen,
598 };
599 let mut padded_key = [0u8; 64];
601 padded_key[..key.len()].copy_from_slice(key);
602 state.update(&padded_key);
603 state
604 }
605
606 pub(crate) fn update(&mut self, data: &[u8]) {
608 let mut offset = 0;
609 let len = data.len();
610
611 if self.buf_len > 0 && self.buf_len + len > 64 {
613 let fill = 64 - self.buf_len;
614 self.buf[self.buf_len..64].copy_from_slice(&data[..fill]);
615 self.increment_counter(64);
616 self.compress(false);
617 self.buf_len = 0;
618 offset = fill;
619 }
620
621 while offset + 64 < len {
623 self.buf.copy_from_slice(&data[offset..offset + 64]);
624 self.increment_counter(64);
625 self.compress(false);
626 offset += 64;
627 }
628
629 let remaining = len - offset;
631 if remaining > 0 {
632 self.buf[self.buf_len..self.buf_len + remaining].copy_from_slice(&data[offset..]);
633 self.buf_len += remaining;
634 }
635 }
636
637 pub(crate) fn finalize(mut self) -> [u8; 32] {
639 self.increment_counter(self.buf_len as u32);
640 let buf_len = self.buf_len;
642 for byte in &mut self.buf[buf_len..] {
643 *byte = 0;
644 }
645 self.compress(true);
646
647 let mut out = [0u8; 32];
648 for i in 0..8 {
649 let bytes = self.h[i].to_le_bytes();
650 out[i * 4..i * 4 + 4].copy_from_slice(&bytes);
651 }
652 out
653 }
654
655 fn compress(&mut self, last: bool) {
657 let mut v = [0u32; 16];
658 v[..8].copy_from_slice(&self.h);
659 v[8..16].copy_from_slice(&BLAKE2S_IV);
660
661 v[12] ^= self.t[0];
662 v[13] ^= self.t[1];
663 if last {
664 v[14] = !v[14];
665 }
666
667 let mut m = [0u32; 16];
669 for (i, word) in m.iter_mut().enumerate() {
670 *word = u32::from_le_bytes([
671 self.buf[i * 4],
672 self.buf[i * 4 + 1],
673 self.buf[i * 4 + 2],
674 self.buf[i * 4 + 3],
675 ]);
676 }
677
678 for s in &BLAKE2S_SIGMA[..10] {
680 Self::g(&mut v, 0, 4, 8, 12, m[s[0]], m[s[1]]);
682 Self::g(&mut v, 1, 5, 9, 13, m[s[2]], m[s[3]]);
683 Self::g(&mut v, 2, 6, 10, 14, m[s[4]], m[s[5]]);
684 Self::g(&mut v, 3, 7, 11, 15, m[s[6]], m[s[7]]);
685 Self::g(&mut v, 0, 5, 10, 15, m[s[8]], m[s[9]]);
687 Self::g(&mut v, 1, 6, 11, 12, m[s[10]], m[s[11]]);
688 Self::g(&mut v, 2, 7, 8, 13, m[s[12]], m[s[13]]);
689 Self::g(&mut v, 3, 4, 9, 14, m[s[14]], m[s[15]]);
690 }
691
692 for i in 0..8 {
694 self.h[i] ^= v[i] ^ v[i + 8];
695 }
696 }
697
698 #[inline]
700 fn g(v: &mut [u32; 16], a: usize, b: usize, c: usize, d: usize, x: u32, y: u32) {
701 v[a] = v[a].wrapping_add(v[b]).wrapping_add(x);
702 v[d] = (v[d] ^ v[a]).rotate_right(16);
703 v[c] = v[c].wrapping_add(v[d]);
704 v[b] = (v[b] ^ v[c]).rotate_right(12);
705 v[a] = v[a].wrapping_add(v[b]).wrapping_add(y);
706 v[d] = (v[d] ^ v[a]).rotate_right(8);
707 v[c] = v[c].wrapping_add(v[d]);
708 v[b] = (v[b] ^ v[c]).rotate_right(7);
709 }
710
711 fn increment_counter(&mut self, inc: u32) {
712 self.t[0] = self.t[0].wrapping_add(inc);
713 if self.t[0] < inc {
714 self.t[1] = self.t[1].wrapping_add(1);
715 }
716 }
717}
718
719pub(crate) fn blake2s_hash(data: &[u8], outlen: usize) -> [u8; 32] {
721 let mut hasher = Blake2s::new(outlen);
722 hasher.update(data);
723 hasher.finalize()
724}
725
726pub(crate) fn blake2s_keyed_hash(key: &[u8], data: &[u8], outlen: usize) -> [u8; 32] {
728 let mut hasher = Blake2s::new_keyed(key, outlen);
729 hasher.update(data);
730 hasher.finalize()
731}
732
733pub(crate) fn verify_hash(
735 algorithm: HashAlgorithm,
736 data: &[u8],
737 expected: &[u8],
738) -> CryptoResult<bool> {
739 let computed = hash(algorithm, data)?;
740 Ok(computed == expected)
741}
742
743#[cfg(test)]
744mod tests {
745 use super::*;
746
747 #[test]
748 fn test_sha256() {
749 let data = b"Hello, VeridianOS!";
750 let hash = sha256(data);
751 assert_eq!(hash.as_bytes().len(), 32);
752 }
753
754 #[test]
755 fn test_hash_hex() {
756 let mut bytes = [0u8; 32];
757 bytes[0] = 0x12;
758 bytes[1] = 0x34;
759 bytes[2] = 0x56;
760 bytes[3] = 0x78;
761 let hash = Hash256(bytes);
762 let hex = hash.to_hex();
763 assert!(hex.starts_with("12345678"));
764 }
765}