bitcoin_hashes/
lib.rs

1// SPDX-License-Identifier: CC0-1.0
2
3//! Rust hashes library.
4//!
5//! This is a simple, no-dependency library which implements the hash functions
6//! needed by Bitcoin. These are SHA256, SHA256d, and RIPEMD160. As an ancillary
7//! thing, it exposes hexadecimal serialization and deserialization, since these
8//! are needed to display hashes anway.
9//!
10//! ## Commonly used operations
11//!
12//! Hashing a single byte slice or a string:
13//!
14//! ```rust
15//! use bitcoin_hashes::sha256;
16//! use bitcoin_hashes::Hash;
17//!
18//! let bytes = [0u8; 5];
19//! let hash_of_bytes = sha256::Hash::hash(&bytes);
20//! let hash_of_string = sha256::Hash::hash("some string".as_bytes());
21//! ```
22//!
23//!
24//! Hashing content from a reader:
25//!
26//! ```rust
27//! use bitcoin_hashes::sha256;
28//! use bitcoin_hashes::Hash;
29//!
30//! #[cfg(std)]
31//! # fn main() -> std::io::Result<()> {
32//! let mut reader: &[u8] = b"hello"; // in real code, this could be a `File` or `TcpStream`
33//! let mut engine = sha256::HashEngine::default();
34//! std::io::copy(&mut reader, &mut engine)?;
35//! let hash = sha256::Hash::from_engine(engine);
36//! # Ok(())
37//! # }
38//!
39//! #[cfg(not(std))]
40//! # fn main() {}
41//! ```
42//!
43//!
44//! Hashing content by [`std::io::Write`] on HashEngine:
45//!
46//! ```rust
47//! use bitcoin_hashes::sha256;
48//! use bitcoin_hashes::Hash;
49//! use std::io::Write;
50//!
51//! #[cfg(std)]
52//! # fn main() -> std::io::Result<()> {
53//! let mut part1: &[u8] = b"hello";
54//! let mut part2: &[u8] = b" ";
55//! let mut part3: &[u8] = b"world";
56//! let mut engine = sha256::HashEngine::default();
57//! engine.write_all(part1)?;
58//! engine.write_all(part2)?;
59//! engine.write_all(part3)?;
60//! let hash = sha256::Hash::from_engine(engine);
61//! # Ok(())
62//! # }
63//!
64//! #[cfg(not(std))]
65//! # fn main() {}
66//! ```
67
68// Coding conventions
69#![warn(missing_docs)]
70// Experimental features we need.
71#![cfg_attr(docsrs, feature(doc_auto_cfg))]
72#![cfg_attr(bench, feature(test))]
73// In general, rust is absolutely horrid at supporting users doing things like,
74// for example, compiling Rust code for real environments. Disable useless lints
75// that don't do anything but annoy us and cant actually ever be resolved.
76#![allow(bare_trait_objects)]
77#![allow(ellipsis_inclusive_range_patterns)]
78#![cfg_attr(all(not(test), not(feature = "std")), no_std)]
79// Instead of littering the codebase for non-fuzzing code just globally allow.
80#![cfg_attr(hashes_fuzz, allow(dead_code, unused_imports))]
81
82#[cfg(all(not(test), not(feature = "std"), feature = "core2"))]
83extern crate actual_core2 as core2;
84#[cfg(all(feature = "alloc", not(feature = "std")))]
85extern crate alloc;
86#[cfg(any(test, feature = "std"))]
87extern crate core;
88
89#[cfg(feature = "serde")]
90/// A generic serialization/deserialization framework.
91pub extern crate serde;
92
93#[cfg(all(test, feature = "serde"))]
94extern crate serde_test;
95#[cfg(bench)]
96extern crate test;
97
98/// Re-export the `hex-conservative` crate.
99pub extern crate hex;
100
101#[doc(hidden)]
102pub mod _export {
103    /// A re-export of core::*
104    pub mod _core {
105        pub use core::*;
106    }
107}
108
109#[cfg(feature = "schemars")]
110extern crate schemars;
111
112mod internal_macros;
113#[macro_use]
114mod util;
115#[macro_use]
116pub mod serde_macros;
117pub mod cmp;
118pub mod hash160;
119pub mod hmac;
120#[cfg(any(test, feature = "std", feature = "core2"))]
121mod impls;
122pub mod ripemd160;
123pub mod sha1;
124pub mod sha256;
125pub mod sha256d;
126pub mod sha256t;
127pub mod sha512;
128pub mod sha512_256;
129pub mod siphash24;
130
131use core::{borrow, fmt, hash, ops};
132// You get I/O if you enable "std" or "core2" (as well as during testing).
133#[cfg(any(test, feature = "std"))]
134use std::io;
135
136#[cfg(all(not(test), not(feature = "std"), feature = "core2"))]
137use core2::io;
138pub use hmac::{Hmac, HmacEngine};
139
140/// A hashing engine which bytes can be serialized into.
141pub trait HashEngine: Clone + Default {
142    /// Byte array representing the internal state of the hash engine.
143    type MidState;
144
145    /// Outputs the midstate of the hash engine. This function should not be
146    /// used directly unless you really know what you're doing.
147    fn midstate(&self) -> Self::MidState;
148
149    /// Length of the hash's internal block size, in bytes.
150    const BLOCK_SIZE: usize;
151
152    /// Add data to the hash engine.
153    fn input(&mut self, data: &[u8]);
154
155    /// Return the number of bytes already n_bytes_hashed(inputted).
156    fn n_bytes_hashed(&self) -> usize;
157}
158
159/// Trait which applies to hashes of all types.
160pub trait Hash:
161    Copy
162    + Clone
163    + PartialEq
164    + Eq
165    + PartialOrd
166    + Ord
167    + hash::Hash
168    + fmt::Debug
169    + fmt::Display
170    + fmt::LowerHex
171    + ops::Index<ops::RangeFull, Output = [u8]>
172    + ops::Index<ops::RangeFrom<usize>, Output = [u8]>
173    + ops::Index<ops::RangeTo<usize>, Output = [u8]>
174    + ops::Index<ops::Range<usize>, Output = [u8]>
175    + ops::Index<usize, Output = u8>
176    + borrow::Borrow<[u8]>
177{
178    /// A hashing engine which bytes can be serialized into. It is expected
179    /// to implement the `io::Write` trait, and to never return errors under
180    /// any conditions.
181    type Engine: HashEngine;
182
183    /// The byte array that represents the hash internally.
184    type Bytes: hex::FromHex + Copy;
185
186    /// Constructs a new engine.
187    fn engine() -> Self::Engine { Self::Engine::default() }
188
189    /// Produces a hash from the current state of a given engine.
190    fn from_engine(e: Self::Engine) -> Self;
191
192    /// Length of the hash, in bytes.
193    const LEN: usize;
194
195    /// Copies a byte slice into a hash object.
196    fn from_slice(sl: &[u8]) -> Result<Self, FromSliceError>;
197
198    /// Hashes some bytes.
199    fn hash(data: &[u8]) -> Self {
200        let mut engine = Self::engine();
201        engine.input(data);
202        Self::from_engine(engine)
203    }
204
205    /// Flag indicating whether user-visible serializations of this hash
206    /// should be backward. For some reason Satoshi decided this should be
207    /// true for `Sha256dHash`, so here we are.
208    const DISPLAY_BACKWARD: bool = false;
209
210    /// Returns the underlying byte array.
211    fn to_byte_array(self) -> Self::Bytes;
212
213    /// Returns a reference to the underlying byte array.
214    fn as_byte_array(&self) -> &Self::Bytes;
215
216    /// Constructs a hash from the underlying byte array.
217    fn from_byte_array(bytes: Self::Bytes) -> Self;
218
219    /// Returns an all zero hash.
220    ///
221    /// An all zeros hash is a made up construct because there is not a known input that can create
222    /// it, however it is used in various places in Bitcoin e.g., the Bitcoin genesis block's
223    /// previous blockhash and the coinbase transaction's outpoint txid.
224    fn all_zeros() -> Self;
225}
226
227/// Attempted to create a hash from an invalid length slice.
228#[derive(Debug, Copy, Clone, PartialEq, Eq)]
229pub struct FromSliceError {
230    expected: usize,
231    got: usize,
232}
233
234impl fmt::Display for FromSliceError {
235    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
236        write!(f, "invalid slice length {} (expected {})", self.got, self.expected)
237    }
238}
239
240#[cfg(feature = "std")]
241impl std::error::Error for FromSliceError {
242    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { None }
243}
244
245#[cfg(test)]
246mod tests {
247    use crate::{sha256d, Hash};
248
249    hash_newtype! {
250        /// A test newtype
251        struct TestNewtype(sha256d::Hash);
252
253        /// A test newtype
254        struct TestNewtype2(sha256d::Hash);
255    }
256
257    #[test]
258    fn convert_newtypes() {
259        let h1 = TestNewtype::hash(&[]);
260        let h2: TestNewtype2 = h1.to_raw_hash().into();
261        assert_eq!(&h1[..], &h2[..]);
262
263        let h = sha256d::Hash::hash(&[]);
264        let h2: TestNewtype = h.to_string().parse().unwrap();
265        assert_eq!(h2.to_raw_hash(), h);
266    }
267}