sha256/
lib.rs

1//! sha256 crypto digest util
2//!
3//! ```rust
4//!
5//! use sha256::{digest, try_digest};
6//!
7//! //sha256 digest String
8//! let input = String::from("hello");
9//! let val = digest(input);
10//! assert_eq!(val,"2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824");
11//!
12//! //sha256 digest &str
13//! let input = "hello";
14//! let val = digest(input);
15//! assert_eq!(val,"2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824");
16//!
17//! //sha256 digest &mut &str
18//! let mut input = "hello";
19//! let val = digest(&mut input);
20//! assert_eq!(val,"2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824");
21//!
22//! //sha256 digest char
23//! let mut input = 'π';
24//! let val = digest(input);
25//! assert_eq!(val,"2617fcb92baa83a96341de050f07a3186657090881eae6b833f66a035600f35a");
26//!
27//! //sha256 digest bytes
28//! let input = b"hello";
29//! let val = digest(input);
30//! assert_eq!(val,"2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824");
31//!
32//! //sha256 digest file
33//! use std::path::Path;
34//! let input = Path::new("./foo.file");
35//! let val = try_digest(input).unwrap();
36//! assert_eq!(val,"433855b7d2b96c23a6f60e70c655eb4305e8806b682a9596a200642f947259b1");
37//!
38//! ```
39
40#[cfg(feature = "async")]
41pub mod async_digest;
42#[cfg(feature = "native_openssl")]
43mod openssl_sha256;
44
45#[cfg(feature = "native_openssl")]
46use crate::openssl_sha256::OpenSslSha256;
47
48#[cfg(feature = "async")]
49pub use async_digest::*;
50
51use sha2::digest::Output;
52use sha2::{Digest, Sha256};
53use std::fmt::Debug;
54use std::fs;
55use std::io;
56use std::io::{BufReader, Read};
57use std::path::Path;
58
59#[cfg(test)]
60mod tests;
61
62/// sha256 digest string
63///
64/// # Examples
65///
66/// ```rust
67/// use sha256::digest;
68/// let input = "hello";
69/// let val = digest(input);
70/// assert_eq!(val,"2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824")
71/// ```
72///
73pub fn digest<D: Sha256Digest>(input: D) -> String {
74    input.digest()
75}
76
77/// sha256 digest file
78///
79/// # Examples
80///
81/// ```rust
82/// use sha256::try_digest;
83/// use std::path::Path;
84/// let input = Path::new("./foo.file");
85/// let val = try_digest(input).unwrap();
86/// assert_eq!(val,"433855b7d2b96c23a6f60e70c655eb4305e8806b682a9596a200642f947259b1")
87/// ```
88pub fn try_digest<D: TrySha256Digest>(input: D) -> Result<String, D::Error> {
89    input.digest()
90}
91
92/// sha256 digest bytes
93///
94/// # Examples
95///
96/// ```rust
97/// use sha256::digest_bytes;
98/// let input = b"hello";
99/// let val = digest_bytes(input);
100/// assert_eq!(val,"2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824")
101/// ```
102///
103#[deprecated(since = "1.1.0", note = "Use new function `digest()` instead")]
104pub fn digest_bytes(input: &[u8]) -> String {
105    __digest__(input)
106}
107
108/// sha256 digest file
109///
110/// # Examples
111///
112/// ```rust
113/// use sha256::digest_file;
114/// use std::path::Path;
115/// let input = Path::new("./foo.file");
116/// let val = digest_file(input).unwrap();
117/// assert_eq!(val,"433855b7d2b96c23a6f60e70c655eb4305e8806b682a9596a200642f947259b1")
118/// ```
119#[deprecated(since = "1.1.0", note = "Use new function `try_digest()` instead")]
120pub fn digest_file<P: AsRef<Path>>(path: P) -> Result<String, io::Error> {
121    let bytes = fs::read(path)?;
122    Ok(__digest__(&bytes))
123}
124
125pub trait Sha256Digest {
126    fn digest(self) -> String;
127}
128
129#[async_trait::async_trait]
130pub trait TrySha256Digest {
131    type Error: Debug;
132
133    fn digest(self) -> Result<String, Self::Error>;
134
135    #[cfg(feature = "async")]
136    async fn async_digest(self) -> Result<String, Self::Error>;
137
138    #[cfg(feature = "native_openssl")]
139    async fn async_openssl_digest(self) -> Result<String, Self::Error>;
140}
141
142impl<const N: usize> Sha256Digest for &[u8; N] {
143    fn digest(self) -> String {
144        __digest__(self)
145    }
146}
147
148impl Sha256Digest for &[u8] {
149    fn digest(self) -> String {
150        __digest__(self)
151    }
152}
153
154impl Sha256Digest for &Vec<u8> {
155    fn digest(self) -> String {
156        __digest__(self)
157    }
158}
159
160impl Sha256Digest for Vec<u8> {
161    fn digest(self) -> String {
162        __digest__(&self)
163    }
164}
165
166impl Sha256Digest for String {
167    fn digest(self) -> String {
168        __digest__(self.as_bytes())
169    }
170}
171
172impl Sha256Digest for &str {
173    fn digest(self) -> String {
174        __digest__(self.as_bytes())
175    }
176}
177
178impl Sha256Digest for char {
179    fn digest(self) -> String {
180        __digest__(self.encode_utf8(&mut [0; 4]).as_bytes())
181    }
182}
183
184impl Sha256Digest for &mut &str {
185    fn digest(self) -> String {
186        __digest__(self.as_bytes())
187    }
188}
189
190impl Sha256Digest for &String {
191    fn digest(self) -> String {
192        __digest__(self.as_bytes())
193    }
194}
195
196#[async_trait::async_trait]
197impl<P> TrySha256Digest for P
198where
199    P: AsRef<Path> + Send,
200{
201    type Error = io::Error;
202
203    fn digest(self) -> Result<String, Self::Error> {
204        let f = fs::File::open(self)?;
205        let reader = BufReader::new(f);
206        let sha = Sha256::new();
207        calc(reader, sha)
208    }
209
210    #[cfg(feature = "async")]
211    async fn async_digest(self) -> Result<String, Self::Error> {
212        let f = tokio::fs::File::open(self).await?;
213        let reader = tokio::io::BufReader::new(f);
214        let sha = Sha256::new();
215        async_calc(reader, sha).await
216    }
217
218    #[cfg(all(feature = "async", feature = "native_openssl"))]
219    async fn async_openssl_digest(self) -> Result<String, Self::Error> {
220        let f = tokio::fs::File::open(self).await?;
221        let reader = tokio::io::BufReader::new(f);
222        let sha = OpenSslSha256::new();
223        async_calc(reader, sha).await
224    }
225}
226
227fn __digest__(data: &[u8]) -> String {
228    hex::encode(Sha256::digest(data))
229}
230
231trait CalculatorInput {
232    fn read_inner(&mut self, buf: &mut [u8]) -> std::io::Result<usize>;
233}
234
235impl<T> CalculatorInput for T
236where
237    T: Read,
238{
239    fn read_inner(&mut self, buf: &mut [u8]) -> io::Result<usize> {
240        self.read(buf)
241    }
242}
243
244pub trait CalculatorSelector {
245    type FinishType: AsRef<[u8]>;
246    fn update_inner(&mut self, data: &[u8]);
247    fn finish_inner(self) -> Self::FinishType;
248}
249
250impl CalculatorSelector for Sha256 {
251    type FinishType = Output<Sha256>;
252
253    fn update_inner(&mut self, data: &[u8]) {
254        self.update(data)
255    }
256
257    fn finish_inner(self) -> Self::FinishType {
258        self.finalize()
259    }
260}
261
262fn calc<I, S>(mut input: I, mut selector: S) -> io::Result<String>
263where
264    I: CalculatorInput,
265    S: CalculatorSelector,
266{
267    let mut buf = [0u8; 1024];
268    loop {
269        let len = input.read_inner(&mut buf)?;
270        if len == 0 {
271            break;
272        }
273        selector.update_inner(&buf[0..len]);
274    }
275    let hash = selector.finish_inner();
276    Ok(hex::encode(hash))
277}