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