//! Pure Rust implementation of the [SHA-1][1] cryptographic hash algorithm //! with optional hardware-specific optimizations. //! //! # 🚨 Warning: Cryptographically Broken! 🚨 //! //! The SHA-1 hash function should be considered cryptographically broken and //! unsuitable for further use in any security critical capacity, as it is //! [practically vulnerable to chosen-prefix collisions][2]. //! //! We provide this crate for legacy interoperability purposes only. //! //! # Usage //! //! ```rust //! use hex_literal::hex; //! use sha1::{Sha1, Digest}; //! //! // create a Sha1 object //! let mut hasher = Sha1::new(); //! //! // process input message //! hasher.update(b"hello world"); //! //! // acquire hash digest in the form of GenericArray, //! // which in this case is equivalent to [u8; 20] //! let result = hasher.finalize(); //! assert_eq!(result[..], hex!("2aae6c35c94fcfb415dbe95f408b9ce91ee846ed")); //! ``` //! //! Also see [RustCrypto/hashes][3] readme. //! //! # Note for users of `sha1 v0.6` //! //! This crate has been transferred to the RustCrypto organization and uses //! implementation previously published as the `sha-1` crate. The previous //! zero dependencies version is now published as the [`sha1_smoll`] crate. //! //! [1]: https://en.wikipedia.org/wiki/SHA-1 //! [2]: https://sha-mbles.github.io/ //! [3]: https://github.com/RustCrypto/hashes //! [`sha1_smoll`]: https://github.com/mitsuhiko/sha1-smol/ #![no_std] #![cfg_attr(docsrs, feature(doc_cfg))] #![doc( html_logo_url = "https://raw.githubusercontent.com/RustCrypto/media/6ee8e381/logo.svg", html_favicon_url = "https://raw.githubusercontent.com/RustCrypto/media/6ee8e381/logo.svg" )] #![warn(missing_docs, rust_2018_idioms)] pub use digest::{self, Digest}; use core::{fmt, slice::from_ref}; #[cfg(feature = "oid")] use digest::const_oid::{AssociatedOid, ObjectIdentifier}; use digest::{ block_buffer::Eager, core_api::{ AlgorithmName, Block, BlockSizeUser, Buffer, BufferKindUser, CoreWrapper, FixedOutputCore, OutputSizeUser, Reset, UpdateCore, }, typenum::{Unsigned, U20, U64}, HashMarker, Output, }; mod compress; #[cfg(feature = "compress")] pub use compress::compress; #[cfg(not(feature = "compress"))] use compress::compress; const STATE_LEN: usize = 5; /// Core SHA-1 hasher state. #[derive(Clone)] pub struct Sha1Core { h: [u32; STATE_LEN], block_len: u64, } impl HashMarker for Sha1Core {} impl BlockSizeUser for Sha1Core { type BlockSize = U64; } impl BufferKindUser for Sha1Core { type BufferKind = Eager; } impl OutputSizeUser for Sha1Core { type OutputSize = U20; } impl UpdateCore for Sha1Core { #[inline] fn update_blocks(&mut self, blocks: &[Block]) { self.block_len += blocks.len() as u64; compress(&mut self.h, blocks); } } impl FixedOutputCore for Sha1Core { #[inline] fn finalize_fixed_core(&mut self, buffer: &mut Buffer, out: &mut Output) { let bs = Self::BlockSize::U64; let bit_len = 8 * (buffer.get_pos() as u64 + bs * self.block_len); let mut h = self.h; buffer.len64_padding_be(bit_len, |b| compress(&mut h, from_ref(b))); for (chunk, v) in out.chunks_exact_mut(4).zip(h.iter()) { chunk.copy_from_slice(&v.to_be_bytes()); } } } impl Default for Sha1Core { #[inline] fn default() -> Self { Self { h: [0x67452301, 0xEFCDAB89, 0x98BADCFE, 0x10325476, 0xC3D2E1F0], block_len: 0, } } } impl Reset for Sha1Core { #[inline] fn reset(&mut self) { *self = Default::default(); } } impl AlgorithmName for Sha1Core { fn write_alg_name(f: &mut fmt::Formatter<'_>) -> fmt::Result { f.write_str("Sha1") } } impl fmt::Debug for Sha1Core { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.write_str("Sha1Core { ... }") } } #[cfg(feature = "oid")] #[cfg_attr(docsrs, doc(cfg(feature = "oid")))] impl AssociatedOid for Sha1Core { const OID: ObjectIdentifier = ObjectIdentifier::new_unwrap("1.3.14.3.2.26"); } /// SHA-1 hasher state. pub type Sha1 = CoreWrapper;