Coverage Report

Created: 2026-03-11 07:34

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/rust/registry/src/index.crates.io-1949cf8c6b5b557f/md-5-0.10.6/src/lib.rs
Line
Count
Source
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
pub use digest::{self, Digest};
34
35
mod compress;
36
pub(crate) mod consts;
37
38
use core::{fmt, slice::from_ref};
39
#[cfg(feature = "oid")]
40
use digest::const_oid::{AssociatedOid, ObjectIdentifier};
41
use digest::{
42
    block_buffer::Eager,
43
    core_api::{
44
        AlgorithmName, Block, BlockSizeUser, Buffer, BufferKindUser, CoreWrapper, FixedOutputCore,
45
        OutputSizeUser, Reset, UpdateCore,
46
    },
47
    typenum::{Unsigned, U16, U64},
48
    HashMarker, Output,
49
};
50
51
/// Core MD5 hasher state.
52
#[derive(Clone)]
53
pub struct Md5Core {
54
    block_len: u64,
55
    state: [u32; 4],
56
}
57
58
impl HashMarker for Md5Core {}
59
60
impl BlockSizeUser for Md5Core {
61
    type BlockSize = U64;
62
}
63
64
impl BufferKindUser for Md5Core {
65
    type BufferKind = Eager;
66
}
67
68
impl OutputSizeUser for Md5Core {
69
    type OutputSize = U16;
70
}
71
72
impl UpdateCore for Md5Core {
73
    #[inline]
74
0
    fn update_blocks(&mut self, blocks: &[Block<Self>]) {
75
0
        self.block_len = self.block_len.wrapping_add(blocks.len() as u64);
76
0
        compress::compress(&mut self.state, convert(blocks))
77
0
    }
Unexecuted instantiation: <md5::Md5Core as digest::core_api::UpdateCore>::update_blocks
Unexecuted instantiation: <md5::Md5Core as digest::core_api::UpdateCore>::update_blocks
78
}
79
80
impl FixedOutputCore for Md5Core {
81
    #[inline]
82
0
    fn finalize_fixed_core(&mut self, buffer: &mut Buffer<Self>, out: &mut Output<Self>) {
83
0
        let bit_len = self
84
0
            .block_len
85
0
            .wrapping_mul(Self::BlockSize::U64)
86
0
            .wrapping_add(buffer.get_pos() as u64)
87
0
            .wrapping_mul(8);
88
0
        let mut s = self.state;
89
0
        buffer.len64_padding_le(bit_len, |b| {
90
0
            compress::compress(&mut s, convert(from_ref(b)))
91
0
        });
Unexecuted instantiation: <md5::Md5Core as digest::core_api::FixedOutputCore>::finalize_fixed_core::{closure#0}
Unexecuted instantiation: <md5::Md5Core as digest::core_api::FixedOutputCore>::finalize_fixed_core::{closure#0}
92
0
        for (chunk, v) in out.chunks_exact_mut(4).zip(s.iter()) {
93
0
            chunk.copy_from_slice(&v.to_le_bytes());
94
0
        }
95
0
    }
Unexecuted instantiation: <md5::Md5Core as digest::core_api::FixedOutputCore>::finalize_fixed_core
Unexecuted instantiation: <md5::Md5Core as digest::core_api::FixedOutputCore>::finalize_fixed_core
96
}
97
98
impl Default for Md5Core {
99
    #[inline]
100
0
    fn default() -> Self {
101
0
        Self {
102
0
            block_len: 0,
103
0
            state: consts::STATE_INIT,
104
0
        }
105
0
    }
Unexecuted instantiation: <md5::Md5Core as core::default::Default>::default
Unexecuted instantiation: <md5::Md5Core as core::default::Default>::default
106
}
107
108
impl Reset for Md5Core {
109
    #[inline]
110
0
    fn reset(&mut self) {
111
0
        *self = Default::default();
112
0
    }
113
}
114
115
impl AlgorithmName for Md5Core {
116
0
    fn write_alg_name(f: &mut fmt::Formatter<'_>) -> fmt::Result {
117
0
        f.write_str("Md5")
118
0
    }
119
}
120
121
impl fmt::Debug for Md5Core {
122
0
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
123
0
        f.write_str("Md5Core { ... }")
124
0
    }
125
}
126
127
#[cfg(feature = "oid")]
128
#[cfg_attr(docsrs, doc(cfg(feature = "oid")))]
129
impl AssociatedOid for Md5Core {
130
    const OID: ObjectIdentifier = ObjectIdentifier::new_unwrap("1.2.840.113549.2.5");
131
}
132
133
/// MD5 hasher state.
134
pub type Md5 = CoreWrapper<Md5Core>;
135
136
const BLOCK_SIZE: usize = <Md5Core as BlockSizeUser>::BlockSize::USIZE;
137
138
#[inline(always)]
139
0
fn convert(blocks: &[Block<Md5Core>]) -> &[[u8; BLOCK_SIZE]] {
140
    // SAFETY: GenericArray<u8, U64> and [u8; 64] have
141
    // exactly the same memory layout
142
0
    let p = blocks.as_ptr() as *const [u8; BLOCK_SIZE];
143
0
    unsafe { core::slice::from_raw_parts(p, blocks.len()) }
144
0
}