ripemd/lib.rs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186
//! An implementation of the [RIPEMD] cryptographic hash.
//!
//! This crate implements only the modified 1996 versions, not the original
//! one from 1992.
//!
//! Note that RIPEMD-256 provides only the same security as RIPEMD-128,
//! and RIPEMD-320 provides only the same security as RIPEMD-160.
//!
//! # Usage
//!
//! ```rust
//! use hex_literal::hex;
//! use ripemd::{Ripemd160, Ripemd320, Digest};
//!
//! // create a RIPEMD-160 hasher instance
//! let mut hasher = Ripemd160::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!("7f772647d88750add82d8e1a7a3e5c0902a346a3"));
//!
//! // same for RIPEMD-320
//! let mut hasher = Ripemd320::new();
//! hasher.update(b"Hello world!");
//! let result = hasher.finalize();
//! assert_eq!(&result[..], &hex!("
//! f1c1c231d301abcf2d7daae0269ff3e7bc68e623
//! ad723aa068d316b056d26b7d1bb6f0cc0f28336d
//! ")[..]);
//! ```
//!
//! Also see [RustCrypto/hashes] readme.
//!
//! [RIPEMD]: https://en.wikipedia.org/wiki/RIPEMD
//! [RustCrypto/hashes]: https://github.com/RustCrypto/hashes
#![no_std]
#![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"
)]
#![forbid(unsafe_code)]
#![warn(missing_docs, rust_2018_idioms)]
pub use digest::{self, Digest};
use core::fmt;
#[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, U16, U20, U32, U40, U64},
HashMarker, Output,
};
mod c128;
mod c160;
mod c256;
mod c320;
macro_rules! impl_ripemd {
(
$name:ident, $wrapped_name:ident, $mod:ident,
$alg_width:expr, $doc_name:expr, $output_size:ty $(,)?
) => {
#[doc = "Core block-level"]
#[doc = $doc_name]
#[doc = " hasher state."]
#[derive(Clone)]
pub struct $name {
h: [u32; $mod::DIGEST_BUF_LEN],
block_len: u64,
}
impl HashMarker for $name {}
impl BlockSizeUser for $name {
type BlockSize = U64;
}
impl BufferKindUser for $name {
type BufferKind = Eager;
}
impl OutputSizeUser for $name {
type OutputSize = $output_size;
}
impl UpdateCore for $name {
#[inline]
fn update_blocks(&mut self, blocks: &[Block<Self>]) {
// Assumes that `block_len` does not overflow
self.block_len += blocks.len() as u64;
for block in blocks {
$mod::compress(&mut self.h, block.as_ref());
}
}
}
impl FixedOutputCore for $name {
#[inline]
fn finalize_fixed_core(&mut self, buffer: &mut Buffer<Self>, out: &mut Output<Self>) {
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_le(bit_len, |block| $mod::compress(&mut h, block.as_ref()));
for (chunk, v) in out.chunks_exact_mut(4).zip(h.iter()) {
chunk.copy_from_slice(&v.to_le_bytes());
}
}
}
impl Default for $name {
#[inline]
fn default() -> Self {
Self {
h: $mod::H0,
block_len: 0,
}
}
}
impl Reset for $name {
#[inline]
fn reset(&mut self) {
*self = Default::default();
}
}
impl AlgorithmName for $name {
#[inline]
fn write_alg_name(f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str(concat!("Ripemd", $alg_width))
}
}
impl fmt::Debug for $name {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str(concat!("Ripemd", $alg_width, "Core { ... }"))
}
}
#[doc = $doc_name]
#[doc = " hasher."]
pub type $wrapped_name = CoreWrapper<$name>;
};
}
impl_ripemd!(Ripemd128Core, Ripemd128, c128, "128", "RIPEMD-128", U16);
impl_ripemd!(Ripemd160Core, Ripemd160, c160, "160", "RIPEMD-160", U20);
impl_ripemd!(Ripemd256Core, Ripemd256, c256, "256", "RIPEMD-256", U32);
impl_ripemd!(Ripemd320Core, Ripemd320, c320, "320", "RIPEMD-320", U40);
#[cfg(feature = "oid")]
#[cfg_attr(docsrs, doc(cfg(feature = "oid")))]
impl AssociatedOid for Ripemd128Core {
/// The OID used for the RIPEMD-160. There are two OIDs defined. The Teletrust one (which is
/// used by almost anybody, including BouncyCastle, OpenSSL, GnuTLS, etc. and the ISO one
/// (1.0.10118.3.0.50), which seems to be used by nobody.
const OID: ObjectIdentifier = ObjectIdentifier::new_unwrap("1.3.36.3.2.2");
}
#[cfg(feature = "oid")]
#[cfg_attr(docsrs, doc(cfg(feature = "oid")))]
impl AssociatedOid for Ripemd160Core {
/// The OID used for the RIPEMD-160. There are two OIDs defined. The Teletrust one (which is
/// used by almost anybody, including BouncyCastle, OpenSSL, GnuTLS, etc. and the ISO one
/// (1.0.10118.3.0.49), which seems to be used by Go and nobody else.
const OID: ObjectIdentifier = ObjectIdentifier::new_unwrap("1.3.36.3.2.1");
}
#[cfg(feature = "oid")]
#[cfg_attr(docsrs, doc(cfg(feature = "oid")))]
impl AssociatedOid for Ripemd256Core {
const OID: ObjectIdentifier = ObjectIdentifier::new_unwrap("1.3.36.3.2.3");
}