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