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.
11//!
12//! # Usage
13//!
14//! ```rust
15//! use hex_literal::hex;
16//! use sha1::{Sha1, Digest};
17//!
18//! // create a Sha1 object
19//! let mut hasher = Sha1::new();
20//!
21//! // process input message
22//! hasher.update(b"hello world");
23//!
24//! // acquire hash digest in the form of GenericArray,
25//! // which in this case is equivalent to [u8; 20]
26//! let result = hasher.finalize();
27//! assert_eq!(result[..], hex!("2aae6c35c94fcfb415dbe95f408b9ce91ee846ed"));
28//! ```
29//!
30//! Also see [RustCrypto/hashes][3] readme.
31//!
32//! # Note for users of `sha1 v0.6`
33//!
34//! This crate has been transferred to the RustCrypto organization and uses
35//! implementation previously published as the `sha-1` crate. The previous
36//! zero dependencies version is now published as the [`sha1_smoll`] crate.
37//!
38//! [1]: https://en.wikipedia.org/wiki/SHA-1
39//! [2]: https://sha-mbles.github.io/
40//! [3]: https://github.com/RustCrypto/hashes
41//! [`sha1_smoll`]: https://github.com/mitsuhiko/sha1-smol/
42
43#![no_std]
44#![cfg_attr(docsrs, feature(doc_cfg))]
45#![doc(
46 html_logo_url = "https://raw.githubusercontent.com/RustCrypto/media/6ee8e381/logo.svg",
47 html_favicon_url = "https://raw.githubusercontent.com/RustCrypto/media/6ee8e381/logo.svg"
48)]
49#![warn(missing_docs, rust_2018_idioms)]
50
51pub use digest::{self, Digest};
52
53use core::{fmt, slice::from_ref};
54#[cfg(feature = "oid")]
55use digest::const_oid::{AssociatedOid, ObjectIdentifier};
56use digest::{
57 block_buffer::Eager,
58 core_api::{
59 AlgorithmName, Block, BlockSizeUser, Buffer, BufferKindUser, CoreWrapper, FixedOutputCore,
60 OutputSizeUser, Reset, UpdateCore,
61 },
62 typenum::{Unsigned, U20, U64},
63 HashMarker, Output,
64};
65
66mod compress;
67
68#[cfg(feature = "compress")]
69pub use compress::compress;
70#[cfg(not(feature = "compress"))]
71use compress::compress;
72
73const STATE_LEN: usize = 5;
74
75/// Core SHA-1 hasher state.
76#[derive(Clone)]
77pub struct Sha1Core {
78 h: [u32; STATE_LEN],
79 block_len: u64,
80}
81
82impl HashMarker for Sha1Core {}
83
84impl BlockSizeUser for Sha1Core {
85 type BlockSize = U64;
86}
87
88impl BufferKindUser for Sha1Core {
89 type BufferKind = Eager;
90}
91
92impl OutputSizeUser for Sha1Core {
93 type OutputSize = U20;
94}
95
96impl UpdateCore for Sha1Core {
97 #[inline]
98 fn update_blocks(&mut self, blocks: &[Block<Self>]) {
99 self.block_len += blocks.len() as u64;
100 compress(&mut self.h, blocks);
101 }
102}
103
104impl FixedOutputCore for Sha1Core {
105 #[inline]
106 fn finalize_fixed_core(&mut self, buffer: &mut Buffer<Self>, out: &mut Output<Self>) {
107 let bs: u64 = Self::BlockSize::U64;
108 let bit_len: u64 = 8 * (buffer.get_pos() as u64 + bs * self.block_len);
109
110 let mut h: [u32; 5] = self.h;
111 buffer.len64_padding_be(data_len:bit_len, |b: &GenericArray, …>>| compress(&mut h, blocks:from_ref(b)));
112 for (chunk: &mut [u8], v: &u32) in out.chunks_exact_mut(chunk_size:4).zip(h.iter()) {
113 chunk.copy_from_slice(&v.to_be_bytes());
114 }
115 }
116}
117
118impl Default for Sha1Core {
119 #[inline]
120 fn default() -> Self {
121 Self {
122 h: [0x67452301, 0xEFCDAB89, 0x98BADCFE, 0x10325476, 0xC3D2E1F0],
123 block_len: 0,
124 }
125 }
126}
127
128impl Reset for Sha1Core {
129 #[inline]
130 fn reset(&mut self) {
131 *self = Default::default();
132 }
133}
134
135impl AlgorithmName for Sha1Core {
136 fn write_alg_name(f: &mut fmt::Formatter<'_>) -> fmt::Result {
137 f.write_str(data:"Sha1")
138 }
139}
140
141impl fmt::Debug for Sha1Core {
142 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
143 f.write_str(data:"Sha1Core { ... }")
144 }
145}
146
147#[cfg(feature = "oid")]
148#[cfg_attr(docsrs, doc(cfg(feature = "oid")))]
149impl AssociatedOid for Sha1Core {
150 const OID: ObjectIdentifier = ObjectIdentifier::new_unwrap("1.3.14.3.2.26");
151}
152
153/// SHA-1 hasher state.
154pub type Sha1 = CoreWrapper<Sha1Core>;
155