1 | //! The SHA family of hashes. |
2 | //! |
3 | //! SHA, or Secure Hash Algorithms, are a family of cryptographic hashing algorithms published by |
4 | //! the National Institute of Standards and Technology (NIST). Hash algorithms such as those in |
5 | //! the SHA family are used to map data of an arbitrary size to a fixed-size string of bytes. |
6 | //! As cryptographic hashing algorithms, these mappings have the property of being irreversible. |
7 | //! This property makes hash algorithms like these excellent for uses such as verifying the |
8 | //! contents of a file- if you know the hash you expect beforehand, then you can verify that the |
9 | //! data you have is correct if it hashes to the same value. |
10 | //! |
11 | //! # Examples |
12 | //! |
13 | //! When dealing with data that becomes available in chunks, such as while buffering data from IO, |
14 | //! you can create a hasher that you can repeatedly update to add bytes to. |
15 | //! |
16 | //! ```rust |
17 | //! use openssl::sha; |
18 | //! |
19 | //! let mut hasher = sha::Sha256::new(); |
20 | //! |
21 | //! hasher.update(b"Hello, " ); |
22 | //! hasher.update(b"world" ); |
23 | //! |
24 | //! let hash = hasher.finish(); |
25 | //! println!("Hashed \"Hello, world \" to {}" , hex::encode(hash)); |
26 | //! ``` |
27 | //! |
28 | //! On the other hand, if you already have access to all of the data you would like to hash, you |
29 | //! may prefer to use the slightly simpler method of simply calling the hash function corresponding |
30 | //! to the algorithm you want to use. |
31 | //! |
32 | //! ```rust |
33 | //! use openssl::sha::sha256; |
34 | //! |
35 | //! let hash = sha256(b"your data or message" ); |
36 | //! println!("Hash = {}" , hex::encode(hash)); |
37 | //! ``` |
38 | use cfg_if::cfg_if; |
39 | use libc::c_void; |
40 | use openssl_macros::corresponds; |
41 | use std::mem::MaybeUninit; |
42 | |
43 | /// Computes the SHA1 hash of some data. |
44 | /// |
45 | /// # Warning |
46 | /// |
47 | /// SHA1 is known to be insecure - it should not be used unless required for |
48 | /// compatibility with existing systems. |
49 | #[corresponds (SHA1)] |
50 | #[inline ] |
51 | pub fn sha1(data: &[u8]) -> [u8; 20] { |
52 | unsafe { |
53 | let mut hash: MaybeUninit<[u8; 20]> = MaybeUninit::<[u8; 20]>::uninit(); |
54 | ffi::SHA1(d:data.as_ptr(), n:data.len(), md:hash.as_mut_ptr() as *mut _); |
55 | hash.assume_init() |
56 | } |
57 | } |
58 | |
59 | /// Computes the SHA224 hash of some data. |
60 | #[corresponds (SHA224)] |
61 | #[inline ] |
62 | pub fn sha224(data: &[u8]) -> [u8; 28] { |
63 | unsafe { |
64 | let mut hash: MaybeUninit<[u8; 28]> = MaybeUninit::<[u8; 28]>::uninit(); |
65 | ffi::SHA224(d:data.as_ptr(), n:data.len(), md:hash.as_mut_ptr() as *mut _); |
66 | hash.assume_init() |
67 | } |
68 | } |
69 | |
70 | /// Computes the SHA256 hash of some data. |
71 | #[corresponds (SHA256)] |
72 | #[inline ] |
73 | pub fn sha256(data: &[u8]) -> [u8; 32] { |
74 | unsafe { |
75 | let mut hash: MaybeUninit<[u8; 32]> = MaybeUninit::<[u8; 32]>::uninit(); |
76 | ffi::SHA256(d:data.as_ptr(), n:data.len(), md:hash.as_mut_ptr() as *mut _); |
77 | hash.assume_init() |
78 | } |
79 | } |
80 | |
81 | /// Computes the SHA384 hash of some data. |
82 | #[corresponds (SHA384)] |
83 | #[inline ] |
84 | pub fn sha384(data: &[u8]) -> [u8; 48] { |
85 | unsafe { |
86 | let mut hash: MaybeUninit<[u8; 48]> = MaybeUninit::<[u8; 48]>::uninit(); |
87 | ffi::SHA384(d:data.as_ptr(), n:data.len(), md:hash.as_mut_ptr() as *mut _); |
88 | hash.assume_init() |
89 | } |
90 | } |
91 | |
92 | /// Computes the SHA512 hash of some data. |
93 | #[corresponds (SHA512)] |
94 | #[inline ] |
95 | pub fn sha512(data: &[u8]) -> [u8; 64] { |
96 | unsafe { |
97 | let mut hash: MaybeUninit<[u8; 64]> = MaybeUninit::<[u8; 64]>::uninit(); |
98 | ffi::SHA512(d:data.as_ptr(), n:data.len(), md:hash.as_mut_ptr() as *mut _); |
99 | hash.assume_init() |
100 | } |
101 | } |
102 | |
103 | cfg_if! { |
104 | if #[cfg(not(osslconf = "OPENSSL_NO_DEPRECATED_3_0" ))] { |
105 | /// An object which calculates a SHA1 hash of some data. |
106 | /// |
107 | /// # Warning |
108 | /// |
109 | /// SHA1 is known to be insecure - it should not be used unless required for |
110 | /// compatibility with existing systems. |
111 | #[derive (Clone)] |
112 | pub struct Sha1(ffi::SHA_CTX); |
113 | |
114 | impl Default for Sha1 { |
115 | #[inline ] |
116 | fn default() -> Sha1 { |
117 | Sha1::new() |
118 | } |
119 | } |
120 | |
121 | impl Sha1 { |
122 | /// Creates a new hasher. |
123 | #[corresponds (SHA1_Init)] |
124 | #[inline ] |
125 | pub fn new() -> Sha1 { |
126 | unsafe { |
127 | let mut ctx = MaybeUninit::uninit(); |
128 | ffi::SHA1_Init( ctx.as_mut_ptr()); |
129 | Sha1(ctx.assume_init()) |
130 | } |
131 | } |
132 | |
133 | /// Feeds some data into the hasher. |
134 | /// |
135 | /// This can be called multiple times. |
136 | #[corresponds (SHA1_Update)] |
137 | #[inline ] |
138 | pub fn update(&mut self, buf: &[u8]) { |
139 | unsafe { |
140 | ffi::SHA1_Update(&mut self.0, buf.as_ptr() as *const c_void, buf.len()); |
141 | } |
142 | } |
143 | |
144 | /// Returns the hash of the data. |
145 | #[corresponds (SHA1_Final)] |
146 | #[inline ] |
147 | pub fn finish(mut self) -> [u8; 20] { |
148 | unsafe { |
149 | let mut hash = MaybeUninit::<[u8; 20]>::uninit(); |
150 | ffi::SHA1_Final(hash.as_mut_ptr() as *mut _, &mut self.0); |
151 | hash.assume_init() |
152 | } |
153 | } |
154 | } |
155 | |
156 | /// An object which calculates a SHA224 hash of some data. |
157 | #[derive (Clone)] |
158 | pub struct Sha224(ffi::SHA256_CTX); |
159 | |
160 | impl Default for Sha224 { |
161 | #[inline ] |
162 | fn default() -> Sha224 { |
163 | Sha224::new() |
164 | } |
165 | } |
166 | |
167 | impl Sha224 { |
168 | /// Creates a new hasher. |
169 | #[corresponds (SHA224_Init)] |
170 | #[inline ] |
171 | pub fn new() -> Sha224 { |
172 | unsafe { |
173 | let mut ctx = MaybeUninit::uninit(); |
174 | ffi::SHA224_Init(ctx.as_mut_ptr()); |
175 | Sha224(ctx.assume_init()) |
176 | } |
177 | } |
178 | |
179 | /// Feeds some data into the hasher. |
180 | /// |
181 | /// This can be called multiple times. |
182 | #[corresponds (SHA224_Update)] |
183 | #[inline ] |
184 | pub fn update(&mut self, buf: &[u8]) { |
185 | unsafe { |
186 | ffi::SHA224_Update(&mut self.0, buf.as_ptr() as *const c_void, buf.len()); |
187 | } |
188 | } |
189 | |
190 | /// Returns the hash of the data. |
191 | #[corresponds (SHA224_Final)] |
192 | #[inline ] |
193 | pub fn finish(mut self) -> [u8; 28] { |
194 | unsafe { |
195 | let mut hash = MaybeUninit::<[u8; 28]>::uninit(); |
196 | ffi::SHA224_Final(hash.as_mut_ptr() as *mut _, &mut self.0); |
197 | hash.assume_init() |
198 | } |
199 | } |
200 | } |
201 | |
202 | /// An object which calculates a SHA256 hash of some data. |
203 | #[derive (Clone)] |
204 | pub struct Sha256(ffi::SHA256_CTX); |
205 | |
206 | impl Default for Sha256 { |
207 | #[inline ] |
208 | fn default() -> Sha256 { |
209 | Sha256::new() |
210 | } |
211 | } |
212 | |
213 | impl Sha256 { |
214 | /// Creates a new hasher. |
215 | #[corresponds (SHA256_Init)] |
216 | #[inline ] |
217 | pub fn new() -> Sha256 { |
218 | unsafe { |
219 | let mut ctx = MaybeUninit::uninit(); |
220 | ffi::SHA256_Init(ctx.as_mut_ptr()); |
221 | Sha256(ctx.assume_init()) |
222 | } |
223 | } |
224 | |
225 | /// Feeds some data into the hasher. |
226 | /// |
227 | /// This can be called multiple times. |
228 | #[corresponds (SHA256_Update)] |
229 | #[inline ] |
230 | pub fn update(&mut self, buf: &[u8]) { |
231 | unsafe { |
232 | ffi::SHA256_Update(&mut self.0, buf.as_ptr() as *const c_void, buf.len()); |
233 | } |
234 | } |
235 | |
236 | /// Returns the hash of the data. |
237 | #[corresponds (SHA256_Final)] |
238 | #[inline ] |
239 | pub fn finish(mut self) -> [u8; 32] { |
240 | unsafe { |
241 | let mut hash = MaybeUninit::<[u8; 32]>::uninit(); |
242 | ffi::SHA256_Final(hash.as_mut_ptr() as *mut _, &mut self.0); |
243 | hash.assume_init() |
244 | } |
245 | } |
246 | } |
247 | |
248 | /// An object which calculates a SHA384 hash of some data. |
249 | #[derive (Clone)] |
250 | pub struct Sha384(ffi::SHA512_CTX); |
251 | |
252 | impl Default for Sha384 { |
253 | #[inline ] |
254 | fn default() -> Sha384 { |
255 | Sha384::new() |
256 | } |
257 | } |
258 | |
259 | impl Sha384 { |
260 | /// Creates a new hasher. |
261 | #[corresponds (SHA384_Init)] |
262 | #[inline ] |
263 | pub fn new() -> Sha384 { |
264 | unsafe { |
265 | let mut ctx = MaybeUninit::uninit(); |
266 | ffi::SHA384_Init(ctx.as_mut_ptr()); |
267 | Sha384(ctx.assume_init()) |
268 | } |
269 | } |
270 | |
271 | /// Feeds some data into the hasher. |
272 | /// |
273 | /// This can be called multiple times. |
274 | #[corresponds (SHA384_Update)] |
275 | #[inline ] |
276 | pub fn update(&mut self, buf: &[u8]) { |
277 | unsafe { |
278 | ffi::SHA384_Update(&mut self.0, buf.as_ptr() as *const c_void, buf.len()); |
279 | } |
280 | } |
281 | |
282 | /// Returns the hash of the data. |
283 | #[corresponds (SHA384_Final)] |
284 | #[inline ] |
285 | pub fn finish(mut self) -> [u8; 48] { |
286 | unsafe { |
287 | let mut hash = MaybeUninit::<[u8; 48]>::uninit(); |
288 | ffi::SHA384_Final(hash.as_mut_ptr() as *mut _, &mut self.0); |
289 | hash.assume_init() |
290 | } |
291 | } |
292 | } |
293 | |
294 | /// An object which calculates a SHA512 hash of some data. |
295 | #[derive (Clone)] |
296 | pub struct Sha512(ffi::SHA512_CTX); |
297 | |
298 | impl Default for Sha512 { |
299 | #[inline ] |
300 | fn default() -> Sha512 { |
301 | Sha512::new() |
302 | } |
303 | } |
304 | |
305 | impl Sha512 { |
306 | /// Creates a new hasher. |
307 | #[corresponds (SHA512_Init)] |
308 | #[inline ] |
309 | pub fn new() -> Sha512 { |
310 | unsafe { |
311 | let mut ctx = MaybeUninit::uninit(); |
312 | ffi::SHA512_Init(ctx.as_mut_ptr()); |
313 | Sha512(ctx.assume_init()) |
314 | } |
315 | } |
316 | |
317 | /// Feeds some data into the hasher. |
318 | /// |
319 | /// This can be called multiple times. |
320 | #[corresponds (SHA512_Update)] |
321 | #[inline ] |
322 | pub fn update(&mut self, buf: &[u8]) { |
323 | unsafe { |
324 | ffi::SHA512_Update(&mut self.0, buf.as_ptr() as *const c_void, buf.len()); |
325 | } |
326 | } |
327 | |
328 | /// Returns the hash of the data. |
329 | #[corresponds (SHA512_Final)] |
330 | #[inline ] |
331 | pub fn finish(mut self) -> [u8; 64] { |
332 | unsafe { |
333 | let mut hash= MaybeUninit::<[u8; 64]>::uninit(); |
334 | ffi::SHA512_Final(hash.as_mut_ptr() as *mut _, &mut self.0); |
335 | hash.assume_init() |
336 | } |
337 | } |
338 | } |
339 | } |
340 | } |
341 | |
342 | #[cfg (test)] |
343 | mod test { |
344 | use super::*; |
345 | |
346 | #[test ] |
347 | fn standalone_1() { |
348 | let data = b"abc" ; |
349 | let expected = "a9993e364706816aba3e25717850c26c9cd0d89d" ; |
350 | |
351 | assert_eq!(hex::encode(sha1(data)), expected); |
352 | } |
353 | |
354 | #[test ] |
355 | #[cfg (not(osslconf = "OPENSSL_NO_DEPRECATED_3_0" ))] |
356 | fn struct_1() { |
357 | let expected = "a9993e364706816aba3e25717850c26c9cd0d89d" ; |
358 | |
359 | let mut hasher = Sha1::new(); |
360 | hasher.update(b"a" ); |
361 | hasher.update(b"bc" ); |
362 | assert_eq!(hex::encode(hasher.finish()), expected); |
363 | } |
364 | |
365 | #[test ] |
366 | #[cfg (not(osslconf = "OPENSSL_NO_DEPRECATED_3_0" ))] |
367 | fn cloning_allows_incremental_hashing() { |
368 | let expected = "a9993e364706816aba3e25717850c26c9cd0d89d" ; |
369 | |
370 | let mut hasher = Sha1::new(); |
371 | hasher.update(b"a" ); |
372 | |
373 | let mut incr_hasher = hasher.clone(); |
374 | incr_hasher.update(b"bc" ); |
375 | |
376 | assert_eq!(hex::encode(incr_hasher.finish()), expected); |
377 | assert_ne!(hex::encode(hasher.finish()), expected); |
378 | } |
379 | |
380 | #[test ] |
381 | fn standalone_224() { |
382 | let data = b"abc" ; |
383 | let expected = "23097d223405d8228642a477bda255b32aadbce4bda0b3f7e36c9da7" ; |
384 | |
385 | assert_eq!(hex::encode(sha224(data)), expected); |
386 | } |
387 | |
388 | #[test ] |
389 | #[cfg (not(osslconf = "OPENSSL_NO_DEPRECATED_3_0" ))] |
390 | fn struct_224() { |
391 | let expected = "23097d223405d8228642a477bda255b32aadbce4bda0b3f7e36c9da7" ; |
392 | |
393 | let mut hasher = Sha224::new(); |
394 | hasher.update(b"a" ); |
395 | hasher.update(b"bc" ); |
396 | assert_eq!(hex::encode(hasher.finish()), expected); |
397 | } |
398 | |
399 | #[test ] |
400 | fn standalone_256() { |
401 | let data = b"abc" ; |
402 | let expected = "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad" ; |
403 | |
404 | assert_eq!(hex::encode(sha256(data)), expected); |
405 | } |
406 | |
407 | #[test ] |
408 | #[cfg (not(osslconf = "OPENSSL_NO_DEPRECATED_3_0" ))] |
409 | fn struct_256() { |
410 | let expected = "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad" ; |
411 | |
412 | let mut hasher = Sha256::new(); |
413 | hasher.update(b"a" ); |
414 | hasher.update(b"bc" ); |
415 | assert_eq!(hex::encode(hasher.finish()), expected); |
416 | } |
417 | |
418 | #[test ] |
419 | fn standalone_384() { |
420 | let data = b"abc" ; |
421 | let expected = |
422 | "cb00753f45a35e8bb5a03d699ac65007272c32ab0eded1631a8b605a43ff5bed8086072ba1e\ |
423 | 7cc2358baeca134c825a7" ; |
424 | |
425 | assert_eq!(hex::encode(&sha384(data)[..]), expected); |
426 | } |
427 | |
428 | #[test ] |
429 | #[cfg (not(osslconf = "OPENSSL_NO_DEPRECATED_3_0" ))] |
430 | fn struct_384() { |
431 | let expected = |
432 | "cb00753f45a35e8bb5a03d699ac65007272c32ab0eded1631a8b605a43ff5bed8086072ba1e\ |
433 | 7cc2358baeca134c825a7" ; |
434 | |
435 | let mut hasher = Sha384::new(); |
436 | hasher.update(b"a" ); |
437 | hasher.update(b"bc" ); |
438 | assert_eq!(hex::encode(&hasher.finish()[..]), expected); |
439 | } |
440 | |
441 | #[test ] |
442 | fn standalone_512() { |
443 | let data = b"abc" ; |
444 | let expected = |
445 | "ddaf35a193617abacc417349ae20413112e6fa4e89a97ea20a9eeee64b55d39a2192992a274\ |
446 | fc1a836ba3c23a3feebbd454d4423643ce80e2a9ac94fa54ca49f" ; |
447 | |
448 | assert_eq!(hex::encode(&sha512(data)[..]), expected); |
449 | } |
450 | |
451 | #[test ] |
452 | #[cfg (not(osslconf = "OPENSSL_NO_DEPRECATED_3_0" ))] |
453 | fn struct_512() { |
454 | let expected = |
455 | "ddaf35a193617abacc417349ae20413112e6fa4e89a97ea20a9eeee64b55d39a2192992a274\ |
456 | fc1a836ba3c23a3feebbd454d4423643ce80e2a9ac94fa54ca49f" ; |
457 | |
458 | let mut hasher = Sha512::new(); |
459 | hasher.update(b"a" ); |
460 | hasher.update(b"bc" ); |
461 | assert_eq!(hex::encode(&hasher.finish()[..]), expected); |
462 | } |
463 | } |
464 | |