48
48
//! - BLAKE2b is not suitable for password hashing. See [`orion::pwhash`](super::pwhash)
49
49
//! instead.
50
50
//!
51
- //! # Example:
51
+ //! # Examples
52
+ //!
53
+ //! ## Hashing in-memory data
52
54
//! ```rust
53
55
//! use orion::hash::{digest, Digest};
54
56
//!
55
57
//! let hash: Digest = digest(b"Some data")?;
56
58
//! # Ok::<(), orion::errors::UnknownCryptoError>(())
57
59
//! ```
60
+ //!
61
+ //! ## Hashing data from an arbitrary reader
62
+ //! ```rust
63
+ //! use orion::hash::{digest_from_reader, Digest};
64
+ //!
65
+ //! // `reader` could instead be `File::open("file.txt")?`
66
+ //! let reader = std::io::Cursor::new(b"some data");
67
+ //! let hash: Digest = digest_from_reader(reader)?;
68
+ //! # Ok::<(), orion::errors::UnknownCryptoError>(())
69
+ //! ```
58
70
59
71
#![ cfg_attr( docsrs, doc( cfg( feature = "safe_api" ) ) ) ]
60
72
@@ -67,6 +79,27 @@ pub fn digest(data: &[u8]) -> Result<Digest, UnknownCryptoError> {
67
79
blake2b:: Hasher :: Blake2b256 . digest ( data)
68
80
}
69
81
82
+ /// Hash data from `impl Read` using BLAKE2b-256.
83
+ ///
84
+ /// See the [module-level docs](crate::hash) for an example of how to use this function.
85
+ /// Internally calls `std::io::copy()` to move data from the reader into the Blake2b writer.
86
+ /// The `std::io::copy` function buffers reads, so passing in a `BufReader` may be unnecessary.
87
+ ///
88
+ /// For lower-level control over reads, writes, buffer sizes, *etc.*, consider using the
89
+ /// [`Blake2b`](crate::hazardous::hash::blake2::blake2b::Blake2b) type and its
90
+ /// [`Write`](std::io::Write) implementation directly. See the Blake2b type's source code
91
+ /// for an example.
92
+ ///
93
+ /// Note that if an error is returned, data may still have been consumed
94
+ /// from the given reader.
95
+ #[ cfg( feature = "safe_api" ) ]
96
+ #[ must_use = "SECURITY WARNING: Ignoring a Result can have real security implications." ]
97
+ pub fn digest_from_reader ( mut reader : impl std:: io:: Read ) -> Result < Digest , UnknownCryptoError > {
98
+ let mut hasher = blake2b:: Blake2b :: new ( 32 ) ?;
99
+ std:: io:: copy ( & mut reader, & mut hasher) . map_err ( |_| UnknownCryptoError ) ?;
100
+ hasher. finalize ( )
101
+ }
102
+
70
103
// Testing public functions in the module.
71
104
#[ cfg( feature = "safe_api" ) ]
72
105
#[ cfg( test) ]
@@ -79,6 +112,15 @@ mod public {
79
112
digest ( & input[ ..] ) . unwrap ( ) == digest ( & input[ ..] ) . unwrap ( )
80
113
}
81
114
115
+ #[ quickcheck]
116
+ /// Hashing all input should be the same as wrapping it in a
117
+ /// cursor and using digest_from_reader.
118
+ fn prop_digest_same_as_digest_from_reader ( input : Vec < u8 > ) -> bool {
119
+ let digest_a = digest_from_reader ( std:: io:: Cursor :: new ( & input) ) . unwrap ( ) ;
120
+ let digest_b = digest ( & input) . unwrap ( ) ;
121
+ digest_a == digest_b
122
+ }
123
+
82
124
#[ quickcheck]
83
125
/// Hashing twice with different input should never produce same output.
84
126
fn prop_digest_diff_result ( input : Vec < u8 > ) -> bool {
0 commit comments