vector_core/crypto/
sha256.rs1#[cfg(target_arch = "aarch64")]
9use bitcoin_hashes::HashEngine as _;
10#[cfg(not(target_arch = "aarch64"))]
11use sha2::Digest as _;
12
13#[derive(Clone, Default)]
15pub struct Sha256 {
16 #[cfg(target_arch = "aarch64")]
17 engine: bitcoin_hashes::sha256::HashEngine,
18 #[cfg(not(target_arch = "aarch64"))]
19 engine: sha2::Sha256,
20}
21
22impl Sha256 {
23 pub fn new() -> Self {
24 Self::default()
25 }
26
27 pub fn update(&mut self, data: impl AsRef<[u8]>) {
28 #[cfg(target_arch = "aarch64")]
29 self.engine.input(data.as_ref());
30 #[cfg(not(target_arch = "aarch64"))]
31 self.engine.update(data.as_ref());
32 }
33
34 pub fn finalize(self) -> [u8; 32] {
35 #[cfg(target_arch = "aarch64")]
36 {
37 self.engine.finalize().to_byte_array()
38 }
39 #[cfg(not(target_arch = "aarch64"))]
40 {
41 self.engine.finalize().into()
42 }
43 }
44}
45
46pub fn digest(data: &[u8]) -> [u8; 32] {
48 let mut h = Sha256::new();
49 h.update(data);
50 h.finalize()
51}
52
53#[cfg(test)]
54mod tests {
55 use super::*;
56 use sha2::Digest;
57
58 #[test]
59 fn matches_sha2_across_block_and_update_boundaries() {
60 assert_eq!(
61 super::super::hex::encode(&digest(b"abc")),
62 "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad"
63 );
64 let data: Vec<u8> = (0..5000u32).map(|i| (i * 31 + 7) as u8).collect();
65 for len in [0usize, 1, 55, 56, 63, 64, 65, 127, 128, 1000, 5000] {
66 let want: [u8; 32] = sha2::Sha256::digest(&data[..len]).into();
67 assert_eq!(digest(&data[..len]), want, "len {len}");
68 for split in [0, 1, 63, 64, len / 2, len] {
69 let split = split.min(len);
70 let mut h = Sha256::new();
71 h.update(&data[..split]);
72 h.update(&data[split..len]);
73 assert_eq!(h.finalize(), want, "len {len} split {split}");
74 }
75 }
76 }
77}