apple_cryptokit/hashing/
sha256.rs

1// SHA-256 hash algorithm implementation
2
3use super::HashFunction;
4use std::ffi::c_void;
5
6/// SHA-256 output size
7pub const SHA256_OUTPUT_SIZE: usize = 32;
8
9// SHA256 Swift FFI declarations
10extern "C" {
11    #[link_name = "sha256_hash"]
12    fn swift_sha256_hash(data: *const u8, length: i32, out_hash: *mut u8);
13
14    #[link_name = "sha256_init"]
15    fn swift_sha256_init() -> *mut c_void;
16
17    #[link_name = "sha256_update"]
18    fn swift_sha256_update(ptr: *mut c_void, data: *const u8, len: i32);
19
20    #[link_name = "sha256_finalize"]
21    fn swift_sha256_finalize(ptr: *mut c_void, out: *mut u8);
22
23    #[link_name = "sha256_free"]
24    fn swift_sha256_free(ptr: *mut c_void);
25}
26
27/// SHA256 one-shot hash computation
28pub fn sha256_hash(data: &[u8]) -> [u8; 32] {
29    let mut output = [0u8; 32];
30    sha256_hash_to(data, &mut output);
31    output
32}
33
34/// SHA256 hash computation to provided buffer (zero allocation)
35///
36/// # Arguments
37/// - `output`: must be at least 32 bytes
38///
39/// # Panics
40/// Panics if output buffer is too small
41pub fn sha256_hash_to(data: &[u8], output: &mut [u8]) {
42    assert!(
43        output.len() >= SHA256_OUTPUT_SIZE,
44        "Output buffer too small: {} < {}",
45        output.len(),
46        SHA256_OUTPUT_SIZE
47    );
48    unsafe {
49        swift_sha256_hash(data.as_ptr(), data.len() as i32, output.as_mut_ptr());
50    }
51}
52
53/// SHA256 streaming hash state
54pub struct Sha256 {
55    ptr: *mut c_void,
56}
57
58impl Sha256 {
59    /// Create a new SHA256 hash state
60    pub fn new() -> Self {
61        let ptr = unsafe { swift_sha256_init() };
62        Self { ptr }
63    }
64
65    /// Update hash state
66    pub fn update(&mut self, data: &[u8]) {
67        unsafe {
68            swift_sha256_update(self.ptr, data.as_ptr(), data.len() as i32);
69        }
70    }
71
72    /// Finalize hash computation and return result
73    pub fn finalize(self) -> [u8; 32] {
74        self.snapshot()
75    }
76
77    pub fn snapshot(&self) -> [u8; 32] {
78        let mut hash = [0u8; 32];
79        unsafe {
80            swift_sha256_finalize(self.ptr, hash.as_mut_ptr());
81        }
82        hash
83    }
84}
85
86impl Default for Sha256 {
87    fn default() -> Self {
88        Self::new()
89    }
90}
91
92impl Drop for Sha256 {
93    fn drop(&mut self) {
94        unsafe {
95            swift_sha256_free(self.ptr);
96        }
97    }
98}
99
100/// SHA256 hash algorithm implementation
101pub struct SHA256;
102
103impl HashFunction for SHA256 {
104    const OUTPUT_SIZE: usize = SHA256_OUTPUT_SIZE;
105
106    fn hash_to(data: &[u8], output: &mut [u8]) {
107        sha256_hash_to(data, output)
108    }
109}
110
111// Re-export
112pub use SHA256 as Sha256Algorithm;