Skip to main content

sha1/
lib.rs

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