]>
Commit | Line | Data |
---|---|---|
5099ac24 FG |
1 | //! Pure Rust implementation of the [SHA-1][1] cryptographic hash algorithm |
2 | //! with optional hardware-specific optimizations. | |
3 | //! | |
4 | //! # 🚨 Warning: Cryptographically Broken! 🚨 | |
5 | //! | |
6 | //! The SHA-1 hash function should be considered cryptographically broken and | |
7 | //! unsuitable for further use in any security critical capacity, as it is | |
8 | //! [practically vulnerable to chosen-prefix collisions][2]. | |
9 | //! | |
10 | //! We provide this crate for legacy interoperability purposes only. | |
9fa01778 | 11 | //! |
ba9703b0 | 12 | //! # Usage |
9fa01778 XL |
13 | //! |
14 | //! ```rust | |
29967ef6 | 15 | //! use hex_literal::hex; |
9fa01778 XL |
16 | //! use sha1::{Sha1, Digest}; |
17 | //! | |
18 | //! // create a Sha1 object | |
ba9703b0 | 19 | //! let mut hasher = Sha1::new(); |
9fa01778 | 20 | //! |
ba9703b0 | 21 | //! // process input message |
29967ef6 | 22 | //! hasher.update(b"hello world"); |
9fa01778 | 23 | //! |
ba9703b0 XL |
24 | //! // acquire hash digest in the form of GenericArray, |
25 | //! // which in this case is equivalent to [u8; 20] | |
29967ef6 | 26 | //! let result = hasher.finalize(); |
ba9703b0 | 27 | //! assert_eq!(result[..], hex!("2aae6c35c94fcfb415dbe95f408b9ce91ee846ed")); |
9fa01778 XL |
28 | //! ``` |
29 | //! | |
5099ac24 | 30 | //! Also see [RustCrypto/hashes][3] readme. |
9fa01778 | 31 | //! |
ba9703b0 | 32 | //! [1]: https://en.wikipedia.org/wiki/SHA-1 |
5099ac24 FG |
33 | //! [2]: https://sha-mbles.github.io/ |
34 | //! [3]: https://github.com/RustCrypto/hashes | |
9fa01778 | 35 | |
29967ef6 | 36 | #![no_std] |
5099ac24 FG |
37 | #![cfg_attr(docsrs, feature(doc_cfg))] |
38 | #![doc( | |
39 | html_logo_url = "https://raw.githubusercontent.com/RustCrypto/media/6ee8e381/logo.svg", | |
40 | html_favicon_url = "https://raw.githubusercontent.com/RustCrypto/media/6ee8e381/logo.svg", | |
41 | html_root_url = "https://docs.rs/sha-1/0.10.0" | |
42 | )] | |
29967ef6 | 43 | #![warn(missing_docs, rust_2018_idioms)] |
ba9703b0 | 44 | |
5099ac24 FG |
45 | pub use digest::{self, Digest}; |
46 | ||
47 | use core::{fmt, slice::from_ref}; | |
48 | use digest::{ | |
49 | block_buffer::Eager, | |
50 | core_api::{ | |
51 | AlgorithmName, Block, BlockSizeUser, Buffer, BufferKindUser, CoreWrapper, FixedOutputCore, | |
52 | OutputSizeUser, Reset, UpdateCore, | |
53 | }, | |
54 | generic_array::typenum::{Unsigned, U20, U64}, | |
55 | HashMarker, Output, | |
56 | }; | |
9fa01778 | 57 | |
29967ef6 | 58 | mod compress; |
9fa01778 | 59 | |
5099ac24 FG |
60 | #[cfg(feature = "compress")] |
61 | pub use compress::compress; | |
62 | #[cfg(not(feature = "compress"))] | |
63 | use compress::compress; | |
64 | ||
65 | const STATE_LEN: usize = 5; | |
9fa01778 | 66 | |
5099ac24 | 67 | /// Core SHA-1 hasher state. |
9fa01778 | 68 | #[derive(Clone)] |
5099ac24 | 69 | pub struct Sha1Core { |
9fa01778 | 70 | h: [u32; STATE_LEN], |
5099ac24 | 71 | block_len: u64, |
9fa01778 XL |
72 | } |
73 | ||
5099ac24 | 74 | impl HashMarker for Sha1Core {} |
9fa01778 | 75 | |
5099ac24 | 76 | impl BlockSizeUser for Sha1Core { |
9fa01778 XL |
77 | type BlockSize = U64; |
78 | } | |
79 | ||
5099ac24 FG |
80 | impl BufferKindUser for Sha1Core { |
81 | type BufferKind = Eager; | |
9fa01778 XL |
82 | } |
83 | ||
5099ac24 | 84 | impl OutputSizeUser for Sha1Core { |
9fa01778 | 85 | type OutputSize = U20; |
5099ac24 FG |
86 | } |
87 | ||
88 | impl UpdateCore for Sha1Core { | |
89 | #[inline] | |
90 | fn update_blocks(&mut self, blocks: &[Block<Self>]) { | |
91 | self.block_len += blocks.len() as u64; | |
92 | compress(&mut self.h, blocks); | |
93 | } | |
94 | } | |
9fa01778 | 95 | |
5099ac24 FG |
96 | impl FixedOutputCore for Sha1Core { |
97 | #[inline] | |
98 | fn finalize_fixed_core(&mut self, buffer: &mut Buffer<Self>, out: &mut Output<Self>) { | |
99 | let bs = Self::BlockSize::U64; | |
100 | let bit_len = 8 * (buffer.get_pos() as u64 + bs * self.block_len); | |
101 | ||
102 | let mut h = self.h; | |
103 | buffer.len64_padding_be(bit_len, |b| compress(&mut h, from_ref(b))); | |
104 | for (chunk, v) in out.chunks_exact_mut(4).zip(h.iter()) { | |
29967ef6 | 105 | chunk.copy_from_slice(&v.to_be_bytes()); |
9fa01778 | 106 | } |
9fa01778 XL |
107 | } |
108 | } | |
109 | ||
5099ac24 FG |
110 | impl Default for Sha1Core { |
111 | #[inline] | |
112 | fn default() -> Self { | |
113 | Self { | |
114 | h: [0x67452301, 0xEFCDAB89, 0x98BADCFE, 0x10325476, 0xC3D2E1F0], | |
115 | block_len: 0, | |
116 | } | |
117 | } | |
118 | } | |
119 | ||
120 | impl Reset for Sha1Core { | |
121 | #[inline] | |
ba9703b0 | 122 | fn reset(&mut self) { |
5099ac24 FG |
123 | *self = Default::default(); |
124 | } | |
125 | } | |
126 | ||
127 | impl AlgorithmName for Sha1Core { | |
128 | fn write_alg_name(f: &mut fmt::Formatter<'_>) -> fmt::Result { | |
129 | f.write_str("Sha1") | |
130 | } | |
131 | } | |
132 | ||
133 | impl fmt::Debug for Sha1Core { | |
134 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | |
135 | f.write_str("Sha1Core { ... }") | |
ba9703b0 XL |
136 | } |
137 | } | |
138 | ||
5099ac24 FG |
139 | /// SHA-1 hasher state. |
140 | pub type Sha1 = CoreWrapper<Sha1Core>; |