1//! An implementation of the [MD5][1] cryptographic hash algorithm.
2//!
3//! # Usage
4//!
5//! ```rust
6//! use md5::{Md5, Digest};
7//! use hex_literal::hex;
8//!
9//! // create a Md5 hasher instance
10//! let mut hasher = Md5::new();
11//!
12//! // process input message
13//! hasher.update(b"hello world");
14//!
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"));
19//! ```
20//!
21//! Also see [RustCrypto/hashes][2] readme.
22//!
23//! [1]: https://en.wikipedia.org/wiki/MD5
24//! [2]: https://github.com/RustCrypto/hashes
25
26#![no_std]
27#![doc(
28 html_logo_url = "https://raw.githubusercontent.com/RustCrypto/media/6ee8e381/logo.svg",
29 html_favicon_url = "https://raw.githubusercontent.com/RustCrypto/media/6ee8e381/logo.svg"
30)]
31#![warn(missing_docs, rust_2018_idioms)]
32
33#[cfg(all(feature = "asm", any(target_arch = "x86", target_arch = "x86_64")))]
34extern crate md5_asm as compress;
35
36#[cfg(not(all(feature = "asm", any(target_arch = "x86", target_arch = "x86_64"))))]
37mod compress;
38
39pub use digest::{self, Digest};
40
41use compress::compress;
42
43use core::{fmt, slice::from_ref};
44#[cfg(feature = "oid")]
45use digest::const_oid::{AssociatedOid, ObjectIdentifier};
46use digest::{
47 block_buffer::Eager,
48 core_api::{
49 AlgorithmName, Block, BlockSizeUser, Buffer, BufferKindUser, CoreWrapper, FixedOutputCore,
50 OutputSizeUser, Reset, UpdateCore,
51 },
52 typenum::{Unsigned, U16, U64},
53 HashMarker, Output,
54};
55/// Core MD5 hasher state.
56#[derive(Clone)]
57pub struct Md5Core {
58 block_len: u64,
59 state: [u32; 4],
60}
61
62impl HashMarker for Md5Core {}
63
64impl BlockSizeUser for Md5Core {
65 type BlockSize = U64;
66}
67
68impl BufferKindUser for Md5Core {
69 type BufferKind = Eager;
70}
71
72impl OutputSizeUser for Md5Core {
73 type OutputSize = U16;
74}
75
76impl UpdateCore for Md5Core {
77 #[inline]
78 fn update_blocks(&mut self, blocks: &[Block<Self>]) {
79 self.block_len = self.block_len.wrapping_add(blocks.len() as u64);
80 compress(&mut self.state, blocks:convert(blocks))
81 }
82}
83
84impl FixedOutputCore for Md5Core {
85 #[inline]
86 fn finalize_fixed_core(&mut self, buffer: &mut Buffer<Self>, out: &mut Output<Self>) {
87 let bit_len: u64 = self
88 .block_len
89 .wrapping_mul(Self::BlockSize::U64)
90 .wrapping_add(buffer.get_pos() as u64)
91 .wrapping_mul(8);
92 let mut s: [u32; 4] = self.state;
93 buffer.len64_padding_le(data_len:bit_len, |b: &GenericArray, …>>| compress(&mut s, blocks:convert(blocks:from_ref(b))));
94 for (chunk: &mut [u8], v: &u32) in out.chunks_exact_mut(chunk_size:4).zip(s.iter()) {
95 chunk.copy_from_slice(&v.to_le_bytes());
96 }
97 }
98}
99
100impl Default for Md5Core {
101 #[inline]
102 fn default() -> Self {
103 Self {
104 block_len: 0,
105 state: [0x6745_2301, 0xEFCD_AB89, 0x98BA_DCFE, 0x1032_5476],
106 }
107 }
108}
109
110impl Reset for Md5Core {
111 #[inline]
112 fn reset(&mut self) {
113 *self = Default::default();
114 }
115}
116
117impl AlgorithmName for Md5Core {
118 fn write_alg_name(f: &mut fmt::Formatter<'_>) -> fmt::Result {
119 f.write_str(data:"Md5")
120 }
121}
122
123impl fmt::Debug for Md5Core {
124 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
125 f.write_str(data:"Md5Core { ... }")
126 }
127}
128
129#[cfg(feature = "oid")]
130#[cfg_attr(docsrs, doc(cfg(feature = "oid")))]
131impl AssociatedOid for Md5Core {
132 const OID: ObjectIdentifier = ObjectIdentifier::new_unwrap("1.2.840.113549.2.5");
133}
134
135/// MD5 hasher state.
136pub type Md5 = CoreWrapper<Md5Core>;
137
138const BLOCK_SIZE: usize = <Md5Core as BlockSizeUser>::BlockSize::USIZE;
139
140#[inline(always)]
141fn convert(blocks: &[Block<Md5Core>]) -> &[[u8; BLOCK_SIZE]] {
142 // SAFETY: GenericArray<u8, U64> and [u8; 64] have
143 // exactly the same memory layout
144 let p: *const [u8; 64] = blocks.as_ptr() as *const [u8; BLOCK_SIZE];
145 unsafe { core::slice::from_raw_parts(data:p, blocks.len()) }
146}
147