1 //! An implementation of the [MD5][1] cryptographic hash algorithm.
6 //! use md5::{Md5, Digest};
7 //! use hex_literal::hex;
9 //! // create a Md5 hasher instance
10 //! let mut hasher = Md5::new();
12 //! // process input message
13 //! hasher.update(b"hello world");
15 //! // acquire hash digest in the form of GenericArray,
16 //! // which in this case is equivalent to [u8; 16]
17 //! let result = hasher.finalize();
18 //! assert_eq!(result[..], hex!("5eb63bbbe01eeed093cb22bb8f5acdc3"));
21 //! Also see [RustCrypto/hashes][2] readme.
23 //! [1]: https://en.wikipedia.org/wiki/MD5
24 //! [2]: https://github.com/RustCrypto/hashes
27 #![doc(html_logo_url = "https://raw.githubusercontent.com/RustCrypto/meta/master/logo_small.png")]
29 #![warn(missing_docs, rust_2018_idioms)]
31 #[cfg(feature = "asm")]
32 extern crate md5_asm
as utils
;
34 #[cfg(feature = "std")]
37 #[cfg(not(feature = "asm"))]
40 pub use digest
::{self, Digest}
;
42 use crate::utils
::compress
;
44 use block_buffer
::BlockBuffer
;
45 use digest
::generic_array
::typenum
::{U16, U64}
;
46 use digest
::generic_array
::GenericArray
;
47 use digest
::{BlockInput, FixedOutputDirty, Reset, Update}
;
55 buffer
: BlockBuffer
<U64
>,
59 impl Default
for Md5
{
60 fn default() -> Self {
63 buffer
: Default
::default(),
70 fn convert(d
: &GenericArray
<u8, U64
>) -> &[u8; 64] {
73 &*(d
.as_ptr() as *const [u8; 64])
79 fn finalize_inner(&mut self) {
80 let s
= &mut self.state
;
81 let l
= (self.length_bytes
<< 3) as u64;
82 self.buffer
.len64_padding_le(l
, |d
| compress(s
, convert(d
)));
86 impl BlockInput
for Md5
{
92 fn update(&mut self, input
: impl AsRef
<[u8]>) {
93 let input
= input
.as_ref();
94 // Unlike Sha1 and Sha2, the length value in MD5 is defined as
95 // the length of the message mod 2^64 - ie: integer overflow is OK.
96 self.length_bytes
= self.length_bytes
.wrapping_add(input
.len() as u64);
97 let s
= &mut self.state
;
98 self.buffer
.input_block(input
, |d
| compress(s
, convert(d
)));
102 impl FixedOutputDirty
for Md5
{
103 type OutputSize
= U16
;
106 fn finalize_into_dirty(&mut self, out
: &mut GenericArray
<u8, U16
>) {
107 self.finalize_inner();
108 for (chunk
, v
) in out
.chunks_exact_mut(4).zip(self.state
.iter()) {
109 chunk
.copy_from_slice(&v
.to_le_bytes());
115 fn reset(&mut self) {
116 self.state
= consts
::S0
;
117 self.length_bytes
= 0;
122 opaque_debug
::implement
!(Md5
);
123 digest
::impl_write
!(Md5
);