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 irreversable.
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 //! extern crate openssl;
18 //! extern crate hex;
19 //!
20 //! use openssl::sha;
21 //!
22 //! fn main() {
23 //!     let mut hasher = sha::Sha256::new();
24 //!
25 //!     hasher.update(b"Hello, ");
26 //!     hasher.update(b"world");
27 //!
28 //!     let hash = hasher.finish();
29 //!     println!("Hashed \"Hello, world\" to {}", hex::encode(hash));
30 //! }
31 //! ```
32 //!
33 //! On the other hand, if you already have access to all of the data you woud like to hash, you
34 //! may prefer to use the slightly simpler method of simply calling the hash function corresponding
35 //! to the algorithm you want to use.
36 //!
37 //! ```rust
38 //! extern crate openssl;
39 //! extern crate hex;
40 //!
41 //! use openssl::sha::sha256;
42 //!
43 //! fn main() {
44 //!     let hash = sha256(b"your data or message");
45 //!     println!("Hash = {}", hex::encode(hash));
46 //! }
47 //! ```
48 use ffi;
49 use libc::c_void;
50 use std::mem;
51 
52 /// Computes the SHA1 hash of some data.
53 ///
54 /// # Warning
55 ///
56 /// SHA1 is known to be insecure - it should not be used unless required for
57 /// compatibility with existing systems.
58 #[inline]
59 #[allow(deprecated)] // https://github.com/rust-lang/rust/issues/63566
sha1(data: &[u8]) -> [u8; 20]60 pub fn sha1(data: &[u8]) -> [u8; 20] {
61     unsafe {
62         let mut hash: [u8; 20] = mem::uninitialized();
63         ffi::SHA1(data.as_ptr(), data.len(), hash.as_mut_ptr());
64         hash
65     }
66 }
67 
68 /// Computes the SHA224 hash of some data.
69 #[inline]
70 #[allow(deprecated)] // https://github.com/rust-lang/rust/issues/63566
sha224(data: &[u8]) -> [u8; 28]71 pub fn sha224(data: &[u8]) -> [u8; 28] {
72     unsafe {
73         let mut hash: [u8; 28] = mem::uninitialized();
74         ffi::SHA224(data.as_ptr(), data.len(), hash.as_mut_ptr());
75         hash
76     }
77 }
78 
79 /// Computes the SHA256 hash of some data.
80 #[inline]
81 #[allow(deprecated)] // https://github.com/rust-lang/rust/issues/63566
sha256(data: &[u8]) -> [u8; 32]82 pub fn sha256(data: &[u8]) -> [u8; 32] {
83     unsafe {
84         let mut hash: [u8; 32] = mem::uninitialized();
85         ffi::SHA256(data.as_ptr(), data.len(), hash.as_mut_ptr());
86         hash
87     }
88 }
89 
90 /// Computes the SHA384 hash of some data.
91 #[inline]
92 #[allow(deprecated)] // https://github.com/rust-lang/rust/issues/63566
sha384(data: &[u8]) -> [u8; 48]93 pub fn sha384(data: &[u8]) -> [u8; 48] {
94     unsafe {
95         let mut hash: [u8; 48] = mem::uninitialized();
96         ffi::SHA384(data.as_ptr(), data.len(), hash.as_mut_ptr());
97         hash
98     }
99 }
100 
101 /// Computes the SHA512 hash of some data.
102 #[inline]
103 #[allow(deprecated)] // https://github.com/rust-lang/rust/issues/63566
sha512(data: &[u8]) -> [u8; 64]104 pub fn sha512(data: &[u8]) -> [u8; 64] {
105     unsafe {
106         let mut hash: [u8; 64] = mem::uninitialized();
107         ffi::SHA512(data.as_ptr(), data.len(), hash.as_mut_ptr());
108         hash
109     }
110 }
111 
112 /// An object which calculates a SHA1 hash of some data.
113 ///
114 /// # Warning
115 ///
116 /// SHA1 is known to be insecure - it should not be used unless required for
117 /// compatibility with existing systems.
118 #[derive(Clone)]
119 pub struct Sha1(ffi::SHA_CTX);
120 
121 impl Default for Sha1 {
122     #[inline]
default() -> Sha1123     fn default() -> Sha1 {
124         Sha1::new()
125     }
126 }
127 
128 impl Sha1 {
129     /// Creates a new hasher.
130     #[inline]
131     #[allow(deprecated)] // https://github.com/rust-lang/rust/issues/63566
new() -> Sha1132     pub fn new() -> Sha1 {
133         unsafe {
134             let mut ctx = mem::uninitialized();
135             ffi::SHA1_Init(&mut ctx);
136             Sha1(ctx)
137         }
138     }
139 
140     /// Feeds some data into the hasher.
141     ///
142     /// This can be called multiple times.
143     #[inline]
update(&mut self, buf: &[u8])144     pub fn update(&mut self, buf: &[u8]) {
145         unsafe {
146             ffi::SHA1_Update(&mut self.0, buf.as_ptr() as *const c_void, buf.len());
147         }
148     }
149 
150     /// Returns the hash of the data.
151     #[inline]
152     #[allow(deprecated)] // https://github.com/rust-lang/rust/issues/63566
finish(mut self) -> [u8; 20]153     pub fn finish(mut self) -> [u8; 20] {
154         unsafe {
155             let mut hash: [u8; 20] = mem::uninitialized();
156             ffi::SHA1_Final(hash.as_mut_ptr(), &mut self.0);
157             hash
158         }
159     }
160 }
161 
162 /// An object which calculates a SHA224 hash of some data.
163 #[derive(Clone)]
164 pub struct Sha224(ffi::SHA256_CTX);
165 
166 impl Default for Sha224 {
167     #[inline]
default() -> Sha224168     fn default() -> Sha224 {
169         Sha224::new()
170     }
171 }
172 
173 impl Sha224 {
174     /// Creates a new hasher.
175     #[inline]
176     #[allow(deprecated)] // https://github.com/rust-lang/rust/issues/63566
new() -> Sha224177     pub fn new() -> Sha224 {
178         unsafe {
179             let mut ctx = mem::uninitialized();
180             ffi::SHA224_Init(&mut ctx);
181             Sha224(ctx)
182         }
183     }
184 
185     /// Feeds some data into the hasher.
186     ///
187     /// This can be called multiple times.
188     #[inline]
update(&mut self, buf: &[u8])189     pub fn update(&mut self, buf: &[u8]) {
190         unsafe {
191             ffi::SHA224_Update(&mut self.0, buf.as_ptr() as *const c_void, buf.len());
192         }
193     }
194 
195     /// Returns the hash of the data.
196     #[inline]
197     #[allow(deprecated)] // https://github.com/rust-lang/rust/issues/63566
finish(mut self) -> [u8; 28]198     pub fn finish(mut self) -> [u8; 28] {
199         unsafe {
200             let mut hash: [u8; 28] = mem::uninitialized();
201             ffi::SHA224_Final(hash.as_mut_ptr(), &mut self.0);
202             hash
203         }
204     }
205 }
206 
207 /// An object which calculates a SHA256 hash of some data.
208 #[derive(Clone)]
209 pub struct Sha256(ffi::SHA256_CTX);
210 
211 impl Default for Sha256 {
212     #[inline]
default() -> Sha256213     fn default() -> Sha256 {
214         Sha256::new()
215     }
216 }
217 
218 impl Sha256 {
219     /// Creates a new hasher.
220     #[inline]
221     #[allow(deprecated)] // https://github.com/rust-lang/rust/issues/63566
new() -> Sha256222     pub fn new() -> Sha256 {
223         unsafe {
224             let mut ctx = mem::uninitialized();
225             ffi::SHA256_Init(&mut ctx);
226             Sha256(ctx)
227         }
228     }
229 
230     /// Feeds some data into the hasher.
231     ///
232     /// This can be called multiple times.
233     #[inline]
update(&mut self, buf: &[u8])234     pub fn update(&mut self, buf: &[u8]) {
235         unsafe {
236             ffi::SHA256_Update(&mut self.0, buf.as_ptr() as *const c_void, buf.len());
237         }
238     }
239 
240     /// Returns the hash of the data.
241     #[inline]
242     #[allow(deprecated)] // https://github.com/rust-lang/rust/issues/63566
finish(mut self) -> [u8; 32]243     pub fn finish(mut self) -> [u8; 32] {
244         unsafe {
245             let mut hash: [u8; 32] = mem::uninitialized();
246             ffi::SHA256_Final(hash.as_mut_ptr(), &mut self.0);
247             hash
248         }
249     }
250 }
251 
252 /// An object which calculates a SHA384 hash of some data.
253 #[derive(Clone)]
254 pub struct Sha384(ffi::SHA512_CTX);
255 
256 impl Default for Sha384 {
257     #[inline]
default() -> Sha384258     fn default() -> Sha384 {
259         Sha384::new()
260     }
261 }
262 
263 impl Sha384 {
264     /// Creates a new hasher.
265     #[inline]
266     #[allow(deprecated)] // https://github.com/rust-lang/rust/issues/63566
new() -> Sha384267     pub fn new() -> Sha384 {
268         unsafe {
269             let mut ctx = mem::uninitialized();
270             ffi::SHA384_Init(&mut ctx);
271             Sha384(ctx)
272         }
273     }
274 
275     /// Feeds some data into the hasher.
276     ///
277     /// This can be called multiple times.
278     #[inline]
update(&mut self, buf: &[u8])279     pub fn update(&mut self, buf: &[u8]) {
280         unsafe {
281             ffi::SHA384_Update(&mut self.0, buf.as_ptr() as *const c_void, buf.len());
282         }
283     }
284 
285     /// Returns the hash of the data.
286     #[inline]
287     #[allow(deprecated)] // https://github.com/rust-lang/rust/issues/63566
finish(mut self) -> [u8; 48]288     pub fn finish(mut self) -> [u8; 48] {
289         unsafe {
290             let mut hash: [u8; 48] = mem::uninitialized();
291             ffi::SHA384_Final(hash.as_mut_ptr(), &mut self.0);
292             hash
293         }
294     }
295 }
296 
297 /// An object which calculates a SHA512 hash of some data.
298 #[derive(Clone)]
299 pub struct Sha512(ffi::SHA512_CTX);
300 
301 impl Default for Sha512 {
302     #[inline]
default() -> Sha512303     fn default() -> Sha512 {
304         Sha512::new()
305     }
306 }
307 
308 impl Sha512 {
309     /// Creates a new hasher.
310     #[inline]
311     #[allow(deprecated)] // https://github.com/rust-lang/rust/issues/63566
new() -> Sha512312     pub fn new() -> Sha512 {
313         unsafe {
314             let mut ctx = mem::uninitialized();
315             ffi::SHA512_Init(&mut ctx);
316             Sha512(ctx)
317         }
318     }
319 
320     /// Feeds some data into the hasher.
321     ///
322     /// This can be called multiple times.
323     #[inline]
update(&mut self, buf: &[u8])324     pub fn update(&mut self, buf: &[u8]) {
325         unsafe {
326             ffi::SHA512_Update(&mut self.0, buf.as_ptr() as *const c_void, buf.len());
327         }
328     }
329 
330     /// Returns the hash of the data.
331     #[inline]
332     #[allow(deprecated)] // https://github.com/rust-lang/rust/issues/63566
finish(mut self) -> [u8; 64]333     pub fn finish(mut self) -> [u8; 64] {
334         unsafe {
335             let mut hash: [u8; 64] = mem::uninitialized();
336             ffi::SHA512_Final(hash.as_mut_ptr(), &mut self.0);
337             hash
338         }
339     }
340 }
341 
342 #[cfg(test)]
343 mod test {
344     use hex;
345 
346     use super::*;
347 
348     #[test]
standalone_1()349     fn standalone_1() {
350         let data = b"abc";
351         let expected = "a9993e364706816aba3e25717850c26c9cd0d89d";
352 
353         assert_eq!(hex::encode(sha1(data)), expected);
354     }
355 
356     #[test]
struct_1()357     fn struct_1() {
358         let expected = "a9993e364706816aba3e25717850c26c9cd0d89d";
359 
360         let mut hasher = Sha1::new();
361         hasher.update(b"a");
362         hasher.update(b"bc");
363         assert_eq!(hex::encode(hasher.finish()), expected);
364     }
365 
366     #[test]
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]
struct_224()389     fn struct_224() {
390         let expected = "23097d223405d8228642a477bda255b32aadbce4bda0b3f7e36c9da7";
391 
392         let mut hasher = Sha224::new();
393         hasher.update(b"a");
394         hasher.update(b"bc");
395         assert_eq!(hex::encode(hasher.finish()), expected);
396     }
397 
398     #[test]
standalone_256()399     fn standalone_256() {
400         let data = b"abc";
401         let expected = "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad";
402 
403         assert_eq!(hex::encode(sha256(data)), expected);
404     }
405 
406     #[test]
struct_256()407     fn struct_256() {
408         let expected = "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad";
409 
410         let mut hasher = Sha256::new();
411         hasher.update(b"a");
412         hasher.update(b"bc");
413         assert_eq!(hex::encode(hasher.finish()), expected);
414     }
415 
416     #[test]
standalone_384()417     fn standalone_384() {
418         let data = b"abc";
419         let expected =
420             "cb00753f45a35e8bb5a03d699ac65007272c32ab0eded1631a8b605a43ff5bed8086072ba1e\
421              7cc2358baeca134c825a7";
422 
423         assert_eq!(hex::encode(&sha384(data)[..]), expected);
424     }
425 
426     #[test]
struct_384()427     fn struct_384() {
428         let expected =
429             "cb00753f45a35e8bb5a03d699ac65007272c32ab0eded1631a8b605a43ff5bed8086072ba1e\
430              7cc2358baeca134c825a7";
431 
432         let mut hasher = Sha384::new();
433         hasher.update(b"a");
434         hasher.update(b"bc");
435         assert_eq!(hex::encode(&hasher.finish()[..]), expected);
436     }
437 
438     #[test]
standalone_512()439     fn standalone_512() {
440         let data = b"abc";
441         let expected =
442             "ddaf35a193617abacc417349ae20413112e6fa4e89a97ea20a9eeee64b55d39a2192992a274\
443              fc1a836ba3c23a3feebbd454d4423643ce80e2a9ac94fa54ca49f";
444 
445         assert_eq!(hex::encode(&sha512(data)[..]), expected);
446     }
447 
448     #[test]
struct_512()449     fn struct_512() {
450         let expected =
451             "ddaf35a193617abacc417349ae20413112e6fa4e89a97ea20a9eeee64b55d39a2192992a274\
452              fc1a836ba3c23a3feebbd454d4423643ce80e2a9ac94fa54ca49f";
453 
454         let mut hasher = Sha512::new();
455         hasher.update(b"a");
456         hasher.update(b"bc");
457         assert_eq!(hex::encode(&hasher.finish()[..]), expected);
458     }
459 }
460