]> git.proxmox.com Git - rustc.git/blob - vendor/md-5/src/lib.rs
New upstream version 1.49.0+dfsg1
[rustc.git] / vendor / md-5 / src / lib.rs
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(html_logo_url = "https://raw.githubusercontent.com/RustCrypto/meta/master/logo_small.png")]
28 #![deny(unsafe_code)]
29 #![warn(missing_docs, rust_2018_idioms)]
30
31 #[cfg(feature = "asm")]
32 extern crate md5_asm as utils;
33
34 #[cfg(feature = "std")]
35 extern crate std;
36
37 #[cfg(not(feature = "asm"))]
38 mod utils;
39
40 pub use digest::{self, Digest};
41
42 use crate::utils::compress;
43
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};
48
49 mod consts;
50
51 /// The MD5 hasher
52 #[derive(Clone)]
53 pub struct Md5 {
54 length_bytes: u64,
55 buffer: BlockBuffer<U64>,
56 state: [u32; 4],
57 }
58
59 impl Default for Md5 {
60 fn default() -> Self {
61 Md5 {
62 length_bytes: 0,
63 buffer: Default::default(),
64 state: consts::S0,
65 }
66 }
67 }
68
69 #[inline(always)]
70 fn convert(d: &GenericArray<u8, U64>) -> &[u8; 64] {
71 #[allow(unsafe_code)]
72 unsafe {
73 &*(d.as_ptr() as *const [u8; 64])
74 }
75 }
76
77 impl Md5 {
78 #[inline]
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)));
83 }
84 }
85
86 impl BlockInput for Md5 {
87 type BlockSize = U64;
88 }
89
90 impl Update for Md5 {
91 #[inline]
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)));
99 }
100 }
101
102 impl FixedOutputDirty for Md5 {
103 type OutputSize = U16;
104
105 #[inline]
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());
110 }
111 }
112 }
113
114 impl Reset for Md5 {
115 fn reset(&mut self) {
116 self.state = consts::S0;
117 self.length_bytes = 0;
118 self.buffer.reset();
119 }
120 }
121
122 opaque_debug::implement!(Md5);
123 digest::impl_write!(Md5);