1 //! Message digest (hash) computation support.
2 //!
3 //! # Examples
4 //!
5 //! Calculate a hash in one go:
6 //!
7 //! ```
8 //! # fn main() -> Result<(), Box<dyn std::error::Error>> {
9 //! use openssl::hash::{hash, MessageDigest};
10 //!
11 //! let data = b"\x42\xF4\x97\xE0";
12 //! let spec = b"\x7c\x43\x0f\x17\x8a\xef\xdf\x14\x87\xfe\xe7\x14\x4e\x96\x41\xe2";
13 //! let res = hash(MessageDigest::md5(), data)?;
14 //! assert_eq!(&*res, spec);
15 //! # Ok(()) }
16 //! ```
17 //!
18 //! Supply the input in chunks:
19 //!
20 //! ```
21 //! use openssl::hash::{Hasher, MessageDigest};
22 //!
23 //! # fn main() -> Result<(), Box<dyn std::error::Error>> {
24 //! let mut hasher = Hasher::new(MessageDigest::sha256())?;
25 //! hasher.update(b"test")?;
26 //! hasher.update(b"this")?;
27 //! let digest: &[u8] = &hasher.finish()?;
28 //!
29 //! let expected = hex::decode("9740e652ab5b4acd997a7cca13d6696702ccb2d441cca59fc6e285127f28cfe6")?;
30 //! assert_eq!(digest, expected);
31 //! # Ok(()) }
32 //! ```
33 use cfg_if::cfg_if;
34 use std::ffi::CString;
35 use std::fmt;
36 use std::io;
37 use std::io::prelude::*;
38 use std::ops::{Deref, DerefMut};
39 use std::ptr;
40
41 use crate::error::ErrorStack;
42 use crate::nid::Nid;
43 use crate::{cvt, cvt_p};
44
45 cfg_if! {
46 if #[cfg(any(ossl110, boringssl, libressl382))] {
47 use ffi::{EVP_MD_CTX_free, EVP_MD_CTX_new};
48 } else {
49 use ffi::{EVP_MD_CTX_create as EVP_MD_CTX_new, EVP_MD_CTX_destroy as EVP_MD_CTX_free};
50 }
51 }
52
53 /// A message digest algorithm.
54 #[derive(Copy, Clone, PartialEq, Eq)]
55 pub struct MessageDigest(*const ffi::EVP_MD);
56
57 impl MessageDigest {
58 /// Creates a `MessageDigest` from a raw OpenSSL pointer.
59 ///
60 /// # Safety
61 ///
62 /// The caller must ensure the pointer is valid.
from_ptr(x: *const ffi::EVP_MD) -> Self63 pub unsafe fn from_ptr(x: *const ffi::EVP_MD) -> Self {
64 MessageDigest(x)
65 }
66
67 /// Returns the `MessageDigest` corresponding to an `Nid`.
68 ///
69 /// This corresponds to [`EVP_get_digestbynid`].
70 ///
71 /// [`EVP_get_digestbynid`]: https://www.openssl.org/docs/manmaster/crypto/EVP_DigestInit.html
from_nid(type_: Nid) -> Option<MessageDigest>72 pub fn from_nid(type_: Nid) -> Option<MessageDigest> {
73 unsafe {
74 let ptr = ffi::EVP_get_digestbynid(type_.as_raw());
75 if ptr.is_null() {
76 None
77 } else {
78 Some(MessageDigest(ptr))
79 }
80 }
81 }
82
83 /// Returns the `MessageDigest` corresponding to an algorithm name.
84 ///
85 /// This corresponds to [`EVP_get_digestbyname`].
86 ///
87 /// [`EVP_get_digestbyname`]: https://www.openssl.org/docs/manmaster/crypto/EVP_DigestInit.html
from_name(name: &str) -> Option<MessageDigest>88 pub fn from_name(name: &str) -> Option<MessageDigest> {
89 ffi::init();
90 let name = CString::new(name).ok()?;
91 unsafe {
92 let ptr = ffi::EVP_get_digestbyname(name.as_ptr());
93 if ptr.is_null() {
94 None
95 } else {
96 Some(MessageDigest(ptr))
97 }
98 }
99 }
100
101 #[cfg(not(boringssl))]
null() -> MessageDigest102 pub fn null() -> MessageDigest {
103 unsafe { MessageDigest(ffi::EVP_md_null()) }
104 }
105
md5() -> MessageDigest106 pub fn md5() -> MessageDigest {
107 unsafe { MessageDigest(ffi::EVP_md5()) }
108 }
109
sha1() -> MessageDigest110 pub fn sha1() -> MessageDigest {
111 unsafe { MessageDigest(ffi::EVP_sha1()) }
112 }
113
sha224() -> MessageDigest114 pub fn sha224() -> MessageDigest {
115 unsafe { MessageDigest(ffi::EVP_sha224()) }
116 }
117
sha256() -> MessageDigest118 pub fn sha256() -> MessageDigest {
119 unsafe { MessageDigest(ffi::EVP_sha256()) }
120 }
121
sha384() -> MessageDigest122 pub fn sha384() -> MessageDigest {
123 unsafe { MessageDigest(ffi::EVP_sha384()) }
124 }
125
sha512() -> MessageDigest126 pub fn sha512() -> MessageDigest {
127 unsafe { MessageDigest(ffi::EVP_sha512()) }
128 }
129
130 #[cfg(any(ossl111, libressl380))]
sha3_224() -> MessageDigest131 pub fn sha3_224() -> MessageDigest {
132 unsafe { MessageDigest(ffi::EVP_sha3_224()) }
133 }
134
135 #[cfg(any(ossl111, libressl380))]
sha3_256() -> MessageDigest136 pub fn sha3_256() -> MessageDigest {
137 unsafe { MessageDigest(ffi::EVP_sha3_256()) }
138 }
139
140 #[cfg(any(ossl111, libressl380))]
sha3_384() -> MessageDigest141 pub fn sha3_384() -> MessageDigest {
142 unsafe { MessageDigest(ffi::EVP_sha3_384()) }
143 }
144
145 #[cfg(any(ossl111, libressl380))]
sha3_512() -> MessageDigest146 pub fn sha3_512() -> MessageDigest {
147 unsafe { MessageDigest(ffi::EVP_sha3_512()) }
148 }
149
150 #[cfg(ossl111)]
shake_128() -> MessageDigest151 pub fn shake_128() -> MessageDigest {
152 unsafe { MessageDigest(ffi::EVP_shake128()) }
153 }
154
155 #[cfg(ossl111)]
shake_256() -> MessageDigest156 pub fn shake_256() -> MessageDigest {
157 unsafe { MessageDigest(ffi::EVP_shake256()) }
158 }
159
160 #[cfg(not(osslconf = "OPENSSL_NO_RMD160"))]
161 #[cfg(not(boringssl))]
ripemd160() -> MessageDigest162 pub fn ripemd160() -> MessageDigest {
163 unsafe { MessageDigest(ffi::EVP_ripemd160()) }
164 }
165
166 #[cfg(all(any(ossl111, libressl291), not(osslconf = "OPENSSL_NO_SM3")))]
sm3() -> MessageDigest167 pub fn sm3() -> MessageDigest {
168 unsafe { MessageDigest(ffi::EVP_sm3()) }
169 }
170
171 #[allow(clippy::trivially_copy_pass_by_ref)]
as_ptr(&self) -> *const ffi::EVP_MD172 pub fn as_ptr(&self) -> *const ffi::EVP_MD {
173 self.0
174 }
175
176 /// The block size of the digest in bytes.
177 #[allow(clippy::trivially_copy_pass_by_ref)]
block_size(&self) -> usize178 pub fn block_size(&self) -> usize {
179 unsafe { ffi::EVP_MD_block_size(self.0) as usize }
180 }
181
182 /// The size of the digest in bytes.
183 #[allow(clippy::trivially_copy_pass_by_ref)]
size(&self) -> usize184 pub fn size(&self) -> usize {
185 unsafe { ffi::EVP_MD_size(self.0) as usize }
186 }
187
188 /// The name of the digest.
189 #[allow(clippy::trivially_copy_pass_by_ref)]
type_(&self) -> Nid190 pub fn type_(&self) -> Nid {
191 Nid::from_raw(unsafe { ffi::EVP_MD_type(self.0) })
192 }
193 }
194
195 unsafe impl Sync for MessageDigest {}
196 unsafe impl Send for MessageDigest {}
197
198 #[derive(PartialEq, Copy, Clone)]
199 enum State {
200 Reset,
201 Updated,
202 Finalized,
203 }
204
205 use self::State::*;
206
207 /// Provides message digest (hash) computation.
208 ///
209 /// # Examples
210 ///
211 /// ```
212 /// use openssl::hash::{Hasher, MessageDigest};
213 ///
214 /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
215 /// let data = [b"\x42\xF4", b"\x97\xE0"];
216 /// let spec = b"\x7c\x43\x0f\x17\x8a\xef\xdf\x14\x87\xfe\xe7\x14\x4e\x96\x41\xe2";
217 /// let mut h = Hasher::new(MessageDigest::md5())?;
218 /// h.update(data[0])?;
219 /// h.update(data[1])?;
220 /// let res = h.finish()?;
221 /// assert_eq!(&*res, spec);
222 /// # Ok(()) }
223 /// ```
224 ///
225 /// # Warning
226 ///
227 /// Don't actually use MD5 and SHA-1 hashes, they're not secure anymore.
228 ///
229 /// Don't ever hash passwords, use the functions in the `pkcs5` module or bcrypt/scrypt instead.
230 ///
231 /// For extendable output functions (XOFs, i.e. SHAKE128/SHAKE256),
232 /// you must use [`Hasher::finish_xof`] instead of [`Hasher::finish`]
233 /// and provide a `buf` to store the hash. The hash will be as long as
234 /// the `buf`.
235 pub struct Hasher {
236 ctx: *mut ffi::EVP_MD_CTX,
237 md: *const ffi::EVP_MD,
238 type_: MessageDigest,
239 state: State,
240 }
241
242 unsafe impl Sync for Hasher {}
243 unsafe impl Send for Hasher {}
244
245 impl Hasher {
246 /// Creates a new `Hasher` with the specified hash type.
new(ty: MessageDigest) -> Result<Hasher, ErrorStack>247 pub fn new(ty: MessageDigest) -> Result<Hasher, ErrorStack> {
248 ffi::init();
249
250 let ctx = unsafe { cvt_p(EVP_MD_CTX_new())? };
251
252 let mut h = Hasher {
253 ctx,
254 md: ty.as_ptr(),
255 type_: ty,
256 state: Finalized,
257 };
258 h.init()?;
259 Ok(h)
260 }
261
init(&mut self) -> Result<(), ErrorStack>262 fn init(&mut self) -> Result<(), ErrorStack> {
263 match self.state {
264 Reset => return Ok(()),
265 Updated => {
266 self.finish()?;
267 }
268 Finalized => (),
269 }
270 unsafe {
271 cvt(ffi::EVP_DigestInit_ex(self.ctx, self.md, ptr::null_mut()))?;
272 }
273 self.state = Reset;
274 Ok(())
275 }
276
277 /// Feeds data into the hasher.
update(&mut self, data: &[u8]) -> Result<(), ErrorStack>278 pub fn update(&mut self, data: &[u8]) -> Result<(), ErrorStack> {
279 if self.state == Finalized {
280 self.init()?;
281 }
282 unsafe {
283 cvt(ffi::EVP_DigestUpdate(
284 self.ctx,
285 data.as_ptr() as *mut _,
286 data.len(),
287 ))?;
288 }
289 self.state = Updated;
290 Ok(())
291 }
292
293 /// Returns the hash of the data written and resets the non-XOF hasher.
finish(&mut self) -> Result<DigestBytes, ErrorStack>294 pub fn finish(&mut self) -> Result<DigestBytes, ErrorStack> {
295 if self.state == Finalized {
296 self.init()?;
297 }
298 unsafe {
299 #[cfg(not(boringssl))]
300 let mut len = ffi::EVP_MAX_MD_SIZE;
301 #[cfg(boringssl)]
302 let mut len = ffi::EVP_MAX_MD_SIZE as u32;
303 let mut buf = [0; ffi::EVP_MAX_MD_SIZE as usize];
304 cvt(ffi::EVP_DigestFinal_ex(
305 self.ctx,
306 buf.as_mut_ptr(),
307 &mut len,
308 ))?;
309 self.state = Finalized;
310 Ok(DigestBytes {
311 buf,
312 len: len as usize,
313 })
314 }
315 }
316
317 /// Writes the hash of the data into the supplied buf and resets the XOF hasher.
318 /// The hash will be as long as the buf.
319 #[cfg(ossl111)]
finish_xof(&mut self, buf: &mut [u8]) -> Result<(), ErrorStack>320 pub fn finish_xof(&mut self, buf: &mut [u8]) -> Result<(), ErrorStack> {
321 if self.state == Finalized {
322 self.init()?;
323 }
324 unsafe {
325 cvt(ffi::EVP_DigestFinalXOF(
326 self.ctx,
327 buf.as_mut_ptr(),
328 buf.len(),
329 ))?;
330 self.state = Finalized;
331 Ok(())
332 }
333 }
334 }
335
336 impl Write for Hasher {
337 #[inline]
write(&mut self, buf: &[u8]) -> io::Result<usize>338 fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
339 self.update(buf)?;
340 Ok(buf.len())
341 }
342
flush(&mut self) -> io::Result<()>343 fn flush(&mut self) -> io::Result<()> {
344 Ok(())
345 }
346 }
347
348 impl Clone for Hasher {
clone(&self) -> Hasher349 fn clone(&self) -> Hasher {
350 let ctx = unsafe {
351 let ctx = EVP_MD_CTX_new();
352 assert!(!ctx.is_null());
353 let r = ffi::EVP_MD_CTX_copy_ex(ctx, self.ctx);
354 assert_eq!(r, 1);
355 ctx
356 };
357 Hasher {
358 ctx,
359 md: self.md,
360 type_: self.type_,
361 state: self.state,
362 }
363 }
364 }
365
366 impl Drop for Hasher {
drop(&mut self)367 fn drop(&mut self) {
368 unsafe {
369 if self.state != Finalized {
370 drop(self.finish());
371 }
372 EVP_MD_CTX_free(self.ctx);
373 }
374 }
375 }
376
377 /// The resulting bytes of a digest.
378 ///
379 /// This type derefs to a byte slice - it exists to avoid allocating memory to
380 /// store the digest data.
381 #[derive(Copy)]
382 pub struct DigestBytes {
383 pub(crate) buf: [u8; ffi::EVP_MAX_MD_SIZE as usize],
384 pub(crate) len: usize,
385 }
386
387 impl Clone for DigestBytes {
388 #[inline]
clone(&self) -> DigestBytes389 fn clone(&self) -> DigestBytes {
390 *self
391 }
392 }
393
394 impl Deref for DigestBytes {
395 type Target = [u8];
396
397 #[inline]
deref(&self) -> &[u8]398 fn deref(&self) -> &[u8] {
399 &self.buf[..self.len]
400 }
401 }
402
403 impl DerefMut for DigestBytes {
404 #[inline]
deref_mut(&mut self) -> &mut [u8]405 fn deref_mut(&mut self) -> &mut [u8] {
406 &mut self.buf[..self.len]
407 }
408 }
409
410 impl AsRef<[u8]> for DigestBytes {
411 #[inline]
as_ref(&self) -> &[u8]412 fn as_ref(&self) -> &[u8] {
413 self.deref()
414 }
415 }
416
417 impl fmt::Debug for DigestBytes {
fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result418 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
419 fmt::Debug::fmt(&**self, fmt)
420 }
421 }
422
423 /// Computes the hash of the `data` with the non-XOF hasher `t`.
424 ///
425 /// # Examples
426 ///
427 /// ```
428 /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
429 /// use openssl::hash::{hash, MessageDigest};
430 ///
431 /// let data = b"\x42\xF4\x97\xE0";
432 /// let spec = b"\x7c\x43\x0f\x17\x8a\xef\xdf\x14\x87\xfe\xe7\x14\x4e\x96\x41\xe2";
433 /// let res = hash(MessageDigest::md5(), data)?;
434 /// assert_eq!(&*res, spec);
435 /// # Ok(()) }
436 /// ```
hash(t: MessageDigest, data: &[u8]) -> Result<DigestBytes, ErrorStack>437 pub fn hash(t: MessageDigest, data: &[u8]) -> Result<DigestBytes, ErrorStack> {
438 let mut h = Hasher::new(t)?;
439 h.update(data)?;
440 h.finish()
441 }
442
443 /// Computes the hash of the `data` with the XOF hasher `t` and stores it in `buf`.
444 ///
445 /// # Examples
446 ///
447 /// ```
448 /// use openssl::hash::{hash_xof, MessageDigest};
449 ///
450 /// let data = b"\x41\x6c\x6c\x20\x79\x6f\x75\x72\x20\x62\x61\x73\x65\x20\x61\x72\x65\x20\x62\x65\x6c\x6f\x6e\x67\x20\x74\x6f\x20\x75\x73";
451 /// let spec = b"\x49\xd0\x69\x7f\xf5\x08\x11\x1d\x8b\x84\xf1\x5e\x46\xda\xf1\x35";
452 /// let mut buf = vec![0; 16];
453 /// hash_xof(MessageDigest::shake_128(), data, buf.as_mut_slice()).unwrap();
454 /// assert_eq!(buf, spec);
455 /// ```
456 ///
457 #[cfg(ossl111)]
hash_xof(t: MessageDigest, data: &[u8], buf: &mut [u8]) -> Result<(), ErrorStack>458 pub fn hash_xof(t: MessageDigest, data: &[u8], buf: &mut [u8]) -> Result<(), ErrorStack> {
459 let mut h = Hasher::new(t)?;
460 h.update(data)?;
461 h.finish_xof(buf)
462 }
463
464 #[cfg(test)]
465 mod tests {
466 use hex::{self, FromHex};
467 use std::io::prelude::*;
468
469 use super::*;
470
hash_test(hashtype: MessageDigest, hashtest: &(&str, &str))471 fn hash_test(hashtype: MessageDigest, hashtest: &(&str, &str)) {
472 let res = hash(hashtype, &Vec::from_hex(hashtest.0).unwrap()).unwrap();
473 assert_eq!(hex::encode(res), hashtest.1);
474 }
475
476 #[cfg(ossl111)]
hash_xof_test(hashtype: MessageDigest, hashtest: &(&str, &str))477 fn hash_xof_test(hashtype: MessageDigest, hashtest: &(&str, &str)) {
478 let expected = Vec::from_hex(hashtest.1).unwrap();
479 let mut buf = vec![0; expected.len()];
480 hash_xof(
481 hashtype,
482 &Vec::from_hex(hashtest.0).unwrap(),
483 buf.as_mut_slice(),
484 )
485 .unwrap();
486 assert_eq!(buf, expected);
487 }
488
hash_recycle_test(h: &mut Hasher, hashtest: &(&str, &str))489 fn hash_recycle_test(h: &mut Hasher, hashtest: &(&str, &str)) {
490 h.write_all(&Vec::from_hex(hashtest.0).unwrap()).unwrap();
491 let res = h.finish().unwrap();
492 assert_eq!(hex::encode(res), hashtest.1);
493 }
494
495 // Test vectors from http://www.nsrl.nist.gov/testdata/
496 const MD5_TESTS: [(&str, &str); 13] = [
497 ("", "d41d8cd98f00b204e9800998ecf8427e"),
498 ("7F", "83acb6e67e50e31db6ed341dd2de1595"),
499 ("EC9C", "0b07f0d4ca797d8ac58874f887cb0b68"),
500 ("FEE57A", "e0d583171eb06d56198fc0ef22173907"),
501 ("42F497E0", "7c430f178aefdf1487fee7144e9641e2"),
502 ("C53B777F1C", "75ef141d64cb37ec423da2d9d440c925"),
503 ("89D5B576327B", "ebbaf15eb0ed784c6faa9dc32831bf33"),
504 ("5D4CCE781EB190", "ce175c4b08172019f05e6b5279889f2c"),
505 ("81901FE94932D7B9", "cd4d2f62b8cdb3a0cf968a735a239281"),
506 ("C9FFDEE7788EFB4EC9", "e0841a231ab698db30c6c0f3f246c014"),
507 ("66AC4B7EBA95E53DC10B", "a3b3cea71910d9af56742aa0bb2fe329"),
508 ("A510CD18F7A56852EB0319", "577e216843dd11573574d3fb209b97d8"),
509 (
510 "AAED18DBE8938C19ED734A8D",
511 "6f80fb775f27e0a4ce5c2f42fc72c5f1",
512 ),
513 ];
514
515 #[test]
test_md5()516 fn test_md5() {
517 for test in MD5_TESTS.iter() {
518 hash_test(MessageDigest::md5(), test);
519 }
520
521 assert_eq!(MessageDigest::md5().block_size(), 64);
522 assert_eq!(MessageDigest::md5().size(), 16);
523 assert_eq!(MessageDigest::md5().type_().as_raw(), Nid::MD5.as_raw());
524 }
525
526 #[test]
test_md5_recycle()527 fn test_md5_recycle() {
528 let mut h = Hasher::new(MessageDigest::md5()).unwrap();
529 for test in MD5_TESTS.iter() {
530 hash_recycle_test(&mut h, test);
531 }
532 }
533
534 #[test]
test_finish_twice()535 fn test_finish_twice() {
536 let mut h = Hasher::new(MessageDigest::md5()).unwrap();
537 h.write_all(&Vec::from_hex(MD5_TESTS[6].0).unwrap())
538 .unwrap();
539 h.finish().unwrap();
540 let res = h.finish().unwrap();
541 let null = hash(MessageDigest::md5(), &[]).unwrap();
542 assert_eq!(&*res, &*null);
543 }
544
545 #[test]
546 #[allow(clippy::redundant_clone)]
test_clone()547 fn test_clone() {
548 let i = 7;
549 let inp = Vec::from_hex(MD5_TESTS[i].0).unwrap();
550 assert!(inp.len() > 2);
551 let p = inp.len() / 2;
552 let h0 = Hasher::new(MessageDigest::md5()).unwrap();
553
554 println!("Clone a new hasher");
555 let mut h1 = h0.clone();
556 h1.write_all(&inp[..p]).unwrap();
557 {
558 println!("Clone an updated hasher");
559 let mut h2 = h1.clone();
560 h2.write_all(&inp[p..]).unwrap();
561 let res = h2.finish().unwrap();
562 assert_eq!(hex::encode(res), MD5_TESTS[i].1);
563 }
564 h1.write_all(&inp[p..]).unwrap();
565 let res = h1.finish().unwrap();
566 assert_eq!(hex::encode(res), MD5_TESTS[i].1);
567
568 println!("Clone a finished hasher");
569 let mut h3 = h1.clone();
570 h3.write_all(&Vec::from_hex(MD5_TESTS[i + 1].0).unwrap())
571 .unwrap();
572 let res = h3.finish().unwrap();
573 assert_eq!(hex::encode(res), MD5_TESTS[i + 1].1);
574 }
575
576 #[test]
test_sha1()577 fn test_sha1() {
578 let tests = [("616263", "a9993e364706816aba3e25717850c26c9cd0d89d")];
579
580 for test in tests.iter() {
581 hash_test(MessageDigest::sha1(), test);
582 }
583
584 assert_eq!(MessageDigest::sha1().block_size(), 64);
585 assert_eq!(MessageDigest::sha1().size(), 20);
586 assert_eq!(MessageDigest::sha1().type_().as_raw(), Nid::SHA1.as_raw());
587 }
588
589 #[test]
test_sha256()590 fn test_sha256() {
591 let tests = [(
592 "616263",
593 "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad",
594 )];
595
596 for test in tests.iter() {
597 hash_test(MessageDigest::sha256(), test);
598 }
599
600 assert_eq!(MessageDigest::sha256().block_size(), 64);
601 assert_eq!(MessageDigest::sha256().size(), 32);
602 assert_eq!(
603 MessageDigest::sha256().type_().as_raw(),
604 Nid::SHA256.as_raw()
605 );
606 }
607
608 #[test]
test_sha512()609 fn test_sha512() {
610 let tests = [(
611 "737465766566696e647365766572797468696e67",
612 "ba61d1f1af0f2dd80729f6cc900f19c0966bd38ba5c75e4471ef11b771dfe7551afab7fcbd300fdc4418f2\
613 b07a028fcd99e7b6446a566f2d9bcd7c604a1ea801",
614 )];
615
616 for test in tests.iter() {
617 hash_test(MessageDigest::sha512(), test);
618 }
619
620 assert_eq!(MessageDigest::sha512().block_size(), 128);
621 assert_eq!(MessageDigest::sha512().size(), 64);
622 assert_eq!(
623 MessageDigest::sha512().type_().as_raw(),
624 Nid::SHA512.as_raw()
625 );
626 }
627
628 #[cfg(any(ossl111, libressl380))]
629 #[test]
test_sha3_224()630 fn test_sha3_224() {
631 let tests = [(
632 "416c6c20796f75722062617365206172652062656c6f6e6720746f207573",
633 "1de092dd9fbcbbf450f26264f4778abd48af851f2832924554c56913",
634 )];
635
636 for test in tests.iter() {
637 hash_test(MessageDigest::sha3_224(), test);
638 }
639
640 assert_eq!(MessageDigest::sha3_224().block_size(), 144);
641 assert_eq!(MessageDigest::sha3_224().size(), 28);
642 assert_eq!(
643 MessageDigest::sha3_224().type_().as_raw(),
644 Nid::SHA3_224.as_raw()
645 );
646 }
647
648 #[cfg(any(ossl111, libressl380))]
649 #[test]
test_sha3_256()650 fn test_sha3_256() {
651 let tests = [(
652 "416c6c20796f75722062617365206172652062656c6f6e6720746f207573",
653 "b38e38f08bc1c0091ed4b5f060fe13e86aa4179578513ad11a6e3abba0062f61",
654 )];
655
656 for test in tests.iter() {
657 hash_test(MessageDigest::sha3_256(), test);
658 }
659
660 assert_eq!(MessageDigest::sha3_256().block_size(), 136);
661 assert_eq!(MessageDigest::sha3_256().size(), 32);
662 assert_eq!(
663 MessageDigest::sha3_256().type_().as_raw(),
664 Nid::SHA3_256.as_raw()
665 );
666 }
667
668 #[cfg(any(ossl111, libressl380))]
669 #[test]
test_sha3_384()670 fn test_sha3_384() {
671 let tests = [("416c6c20796f75722062617365206172652062656c6f6e6720746f207573",
672 "966ee786ab3482dd811bf7c8fa8db79aa1f52f6c3c369942ef14240ebd857c6ff626ec35d9e131ff64d328\
673 ef2008ff16"
674 )];
675
676 for test in tests.iter() {
677 hash_test(MessageDigest::sha3_384(), test);
678 }
679
680 assert_eq!(MessageDigest::sha3_384().block_size(), 104);
681 assert_eq!(MessageDigest::sha3_384().size(), 48);
682 assert_eq!(
683 MessageDigest::sha3_384().type_().as_raw(),
684 Nid::SHA3_384.as_raw()
685 );
686 }
687
688 #[cfg(any(ossl111, libressl380))]
689 #[test]
test_sha3_512()690 fn test_sha3_512() {
691 let tests = [("416c6c20796f75722062617365206172652062656c6f6e6720746f207573",
692 "c072288ef728cd53a029c47687960b9225893532f42b923156e37020bdc1eda753aafbf30af859d4f4c3a1\
693 807caee3a79f8eb02dcd61589fbbdf5f40c8787a72"
694 )];
695
696 for test in tests.iter() {
697 hash_test(MessageDigest::sha3_512(), test);
698 }
699
700 assert_eq!(MessageDigest::sha3_512().block_size(), 72);
701 assert_eq!(MessageDigest::sha3_512().size(), 64);
702 assert_eq!(
703 MessageDigest::sha3_512().type_().as_raw(),
704 Nid::SHA3_512.as_raw()
705 );
706 }
707
708 #[cfg(ossl111)]
709 #[test]
test_shake_128()710 fn test_shake_128() {
711 let tests = [(
712 "416c6c20796f75722062617365206172652062656c6f6e6720746f207573",
713 "49d0697ff508111d8b84f15e46daf135",
714 )];
715
716 for test in tests.iter() {
717 hash_xof_test(MessageDigest::shake_128(), test);
718 }
719
720 assert_eq!(MessageDigest::shake_128().block_size(), 168);
721 assert_eq!(MessageDigest::shake_128().size(), 16);
722 assert_eq!(
723 MessageDigest::shake_128().type_().as_raw(),
724 Nid::SHAKE128.as_raw()
725 );
726 }
727
728 #[cfg(ossl111)]
729 #[test]
test_shake_256()730 fn test_shake_256() {
731 let tests = [(
732 "416c6c20796f75722062617365206172652062656c6f6e6720746f207573",
733 "4e2dfdaa75d1e049d0eaeffe28e76b17cea47b650fb8826fe48b94664326a697",
734 )];
735
736 for test in tests.iter() {
737 hash_xof_test(MessageDigest::shake_256(), test);
738 }
739
740 assert_eq!(MessageDigest::shake_256().block_size(), 136);
741 assert_eq!(MessageDigest::shake_256().size(), 32);
742 assert_eq!(
743 MessageDigest::shake_256().type_().as_raw(),
744 Nid::SHAKE256.as_raw()
745 );
746 }
747
748 #[test]
749 #[cfg(not(osslconf = "OPENSSL_NO_RMD160"))]
750 #[cfg_attr(ossl300, ignore)]
test_ripemd160()751 fn test_ripemd160() {
752 #[cfg(ossl300)]
753 let _provider = crate::provider::Provider::try_load(None, "legacy", true).unwrap();
754
755 let tests = [("616263", "8eb208f7e05d987a9b044a8e98c6b087f15a0bfc")];
756
757 for test in tests.iter() {
758 hash_test(MessageDigest::ripemd160(), test);
759 }
760
761 assert_eq!(MessageDigest::ripemd160().block_size(), 64);
762 assert_eq!(MessageDigest::ripemd160().size(), 20);
763 assert_eq!(
764 MessageDigest::ripemd160().type_().as_raw(),
765 Nid::RIPEMD160.as_raw()
766 );
767 }
768
769 #[cfg(all(any(ossl111, libressl291), not(osslconf = "OPENSSL_NO_SM3")))]
770 #[test]
test_sm3()771 fn test_sm3() {
772 let tests = [(
773 "616263",
774 "66c7f0f462eeedd9d1f2d46bdc10e4e24167c4875cf2f7a2297da02b8f4ba8e0",
775 )];
776
777 for test in tests.iter() {
778 hash_test(MessageDigest::sm3(), test);
779 }
780
781 assert_eq!(MessageDigest::sm3().block_size(), 64);
782 assert_eq!(MessageDigest::sm3().size(), 32);
783 assert_eq!(MessageDigest::sm3().type_().as_raw(), Nid::SM3.as_raw());
784 }
785
786 #[test]
from_nid()787 fn from_nid() {
788 assert_eq!(
789 MessageDigest::from_nid(Nid::SHA256).unwrap().as_ptr(),
790 MessageDigest::sha256().as_ptr()
791 );
792 }
793
794 #[test]
from_name()795 fn from_name() {
796 assert_eq!(
797 MessageDigest::from_name("SHA256").unwrap().as_ptr(),
798 MessageDigest::sha256().as_ptr()
799 )
800 }
801 }
802