#![no_std]
#![warn(missing_docs)]
#![warn(deprecated_in_future)]
#![doc(test(attr(warn(unused))))]
#![warn(clippy::return_self_not_must_use)]
#![cfg_attr(hashes_fuzz, allow(dead_code, unused_imports))]
#![allow(clippy::needless_question_mark)] #![allow(clippy::manual_range_contains)] #![allow(clippy::uninlined_format_args)]
#[cfg(feature = "alloc")]
extern crate alloc;
extern crate core;
#[cfg(feature = "std")]
extern crate std;
#[cfg(feature = "serde")]
pub extern crate serde;
#[cfg(all(test, feature = "serde"))]
extern crate serde_test;
#[cfg(feature = "hex")]
pub extern crate hex;
#[doc(hidden)]
pub mod _export {
pub mod _core {
pub use core::*;
}
}
mod internal_macros;
pub mod cmp;
pub mod hash160;
pub mod hkdf;
pub mod hmac;
#[macro_use]
pub mod macros;
pub mod muhash;
pub mod ripemd160;
pub mod sha1;
pub mod sha256;
pub mod sha256d;
pub mod sha256t;
pub mod sha384;
pub mod sha3_256;
pub mod sha512;
pub mod sha512_256;
pub mod siphash24;
use core::fmt::{self, Write as _};
use core::{convert, hash};
use encoding::Encoder;
#[rustfmt::skip] #[doc(inline)]
pub use self::{
hkdf::Hkdf,
hmac::{Hmac, HmacEngine},
};
#[doc(inline)]
pub use hash160::Hash as Hash160;
#[doc(inline)]
pub use muhash::Hash as MuHash;
#[doc(inline)]
pub use ripemd160::Hash as Ripemd160;
#[doc(inline)]
pub use sha1::Hash as Sha1;
#[doc(inline)]
pub use sha256::Hash as Sha256;
#[doc(inline)]
pub use sha256d::Hash as Sha256d;
#[doc(inline)]
pub use sha384::Hash as Sha384;
pub use sha3_256::Hash as Sha3_256;
#[doc(inline)]
pub use sha512::Hash as Sha512;
#[doc(inline)]
pub use sha512_256::Hash as Sha512_256;
#[doc(inline)]
pub use siphash24::Hash as Siphash24;
pub type Sha256t<T> = sha256t::Hash<T>;
pub type HmacSha256 = Hmac<sha256::Hash>;
pub type HmacSha512 = Hmac<sha512::Hash>;
pub type HkdfSha256 = Hkdf<sha256::Hash>;
pub type HkdfSha512 = Hkdf<sha512::Hash>;
pub trait HashEngine: Clone {
type Hash: Hash;
type Bytes: Copy + IsByteArray;
const LEN: usize = Self::Bytes::LEN;
const BLOCK_SIZE: usize;
fn input(&mut self, data: &[u8]);
fn n_bytes_hashed(&self) -> u64;
fn finalize(self) -> Self::Hash;
}
pub fn encode_to_engine<T, H>(object: &T, mut engine: H) -> H
where
T: encoding::Encodable + ?Sized,
H: HashEngine,
{
let mut encoder = object.encoder();
loop {
engine.input(encoder.current_chunk());
if !encoder.advance() {
break;
}
}
engine
}
pub trait Hash:
Copy + Clone + PartialEq + Eq + PartialOrd + Ord + hash::Hash + convert::AsRef<[u8]>
{
type Bytes: Copy + IsByteArray;
const LEN: usize = Self::Bytes::LEN;
const DISPLAY_BACKWARD: bool = false;
fn from_byte_array(bytes: Self::Bytes) -> Self;
fn to_byte_array(self) -> Self::Bytes;
fn as_byte_array(&self) -> &Self::Bytes;
}
pub trait IsByteArray: AsRef<[u8]> + sealed::IsByteArray {
const LEN: usize;
}
impl<const N: usize> IsByteArray for [u8; N] {
const LEN: usize = N;
}
mod sealed {
pub trait IsByteArray {}
impl<const N: usize> IsByteArray for [u8; N] {}
}
fn incomplete_block_len<H: HashEngine>(eng: &H) -> usize {
let block_size = H::BLOCK_SIZE as u64;
(eng.n_bytes_hashed() % block_size) as usize
}
pub fn debug_hex<'a>(
bytes: impl IntoIterator<Item = &'a u8>,
f: &mut fmt::Formatter,
) -> fmt::Result {
const HEX_TABLE: [u8; 16] = *b"0123456789abcdef";
for &b in bytes {
let lower = HEX_TABLE[usize::from(b >> 4)];
let upper = HEX_TABLE[usize::from(b & 0b00001111)];
f.write_char(char::from(lower))?;
f.write_char(char::from(upper))?;
}
Ok(())
}
#[cfg(test)]
mod tests {
use crate::sha256d;
hash_newtype! {
struct TestNewtype(sha256d::Hash);
struct TestNewtype2(sha256d::Hash);
}
#[cfg(feature = "hex")]
crate::impl_hex_for_newtype!(TestNewtype, TestNewtype2);
#[cfg(not(feature = "hex"))]
crate::impl_debug_only_for_newtype!(TestNewtype, TestNewtype2);
#[test]
#[cfg(feature = "alloc")]
#[cfg(feature = "hex")]
fn newtype_fmt_roundtrip() {
use alloc::format;
#[rustfmt::skip]
const DUMMY: TestNewtype = TestNewtype::from_byte_array([
0x12, 0x23, 0x34, 0x45, 0x56, 0x67, 0x78, 0x89,
0x13, 0x24, 0x35, 0x46, 0x57, 0x68, 0x79, 0x8a,
0x14, 0x25, 0x36, 0x47, 0x58, 0x69, 0x7a, 0x8b,
0x15, 0x26, 0x37, 0x48, 0x59, 0x6a, 0x7b, 0x8c,
]);
let orig = DUMMY;
let hex = format!("{}", orig);
let roundtrip = hex.parse::<TestNewtype>().expect("failed to parse hex");
assert_eq!(roundtrip, orig)
}
}