• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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]
sha1(data: &[u8]) -> [u8; 20]51 pub fn sha1(data: &[u8]) -> [u8; 20] {
52     unsafe {
53         let mut hash = MaybeUninit::<[u8; 20]>::uninit();
54         ffi::SHA1(data.as_ptr(), data.len(), 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]
sha224(data: &[u8]) -> [u8; 28]62 pub fn sha224(data: &[u8]) -> [u8; 28] {
63     unsafe {
64         let mut hash = MaybeUninit::<[u8; 28]>::uninit();
65         ffi::SHA224(data.as_ptr(), data.len(), 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]
sha256(data: &[u8]) -> [u8; 32]73 pub fn sha256(data: &[u8]) -> [u8; 32] {
74     unsafe {
75         let mut hash = MaybeUninit::<[u8; 32]>::uninit();
76         ffi::SHA256(data.as_ptr(), data.len(), 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]
sha384(data: &[u8]) -> [u8; 48]84 pub fn sha384(data: &[u8]) -> [u8; 48] {
85     unsafe {
86         let mut hash = MaybeUninit::<[u8; 48]>::uninit();
87         ffi::SHA384(data.as_ptr(), data.len(), 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]
sha512(data: &[u8]) -> [u8; 64]95 pub fn sha512(data: &[u8]) -> [u8; 64] {
96     unsafe {
97         let mut hash = MaybeUninit::<[u8; 64]>::uninit();
98         ffi::SHA512(data.as_ptr(), data.len(), 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]
standalone_1()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"))]
struct_1()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"))]
cloning_allows_incremental_hashing()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]
standalone_224()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"))]
struct_224()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]
standalone_256()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"))]
struct_256()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]
standalone_384()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"))]
struct_384()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]
standalone_512()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"))]
struct_512()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