summaryrefslogtreecommitdiff
path: root/openssl
diff options
context:
space:
mode:
authorSteven Fackler <sfackler@gmail.com>2018-11-22 09:32:24 -0700
committerGitHub <noreply@github.com>2018-11-22 09:32:24 -0700
commit894b924f1d76efd3e9698840f1ac0753093a8c2c (patch)
treefc092d101c5448d0b5bee3494a93528036fd940a /openssl
parentb88778bc76b039e26aaa3d54f03716433986fae1 (diff)
parentfd8c9d7336e06116638bebaf2165787fb646e73b (diff)
downloadrust-openssl-894b924f1d76efd3e9698840f1ac0753093a8c2c.zip
Merge pull request #1018 from sameer/master
Add SHA3 & SHAKE128/256 EVP message digest functions in OpenSSL 1.1.1, fixes #1017.
Diffstat (limited to 'openssl')
-rw-r--r--openssl/src/hash.rs160
1 files changed, 158 insertions, 2 deletions
diff --git a/openssl/src/hash.rs b/openssl/src/hash.rs
index dd4d136c..c4a836dd 100644
--- a/openssl/src/hash.rs
+++ b/openssl/src/hash.rs
@@ -64,6 +64,36 @@ impl MessageDigest {
unsafe { MessageDigest(ffi::EVP_sha512()) }
}
+ #[cfg(ossl111)]
+ pub fn sha3_224() -> MessageDigest {
+ unsafe { MessageDigest(ffi::EVP_sha3_224()) }
+ }
+
+ #[cfg(ossl111)]
+ pub fn sha3_256() -> MessageDigest {
+ unsafe { MessageDigest(ffi::EVP_sha3_256()) }
+ }
+
+ #[cfg(ossl111)]
+ pub fn sha3_384() -> MessageDigest {
+ unsafe { MessageDigest(ffi::EVP_sha3_384()) }
+ }
+
+ #[cfg(ossl111)]
+ pub fn sha3_512() -> MessageDigest {
+ unsafe { MessageDigest(ffi::EVP_sha3_512()) }
+ }
+
+ #[cfg(ossl111)]
+ pub fn shake_128() -> MessageDigest {
+ unsafe { MessageDigest(ffi::EVP_shake128()) }
+ }
+
+ #[cfg(ossl111)]
+ pub fn shake_256() -> MessageDigest {
+ unsafe { MessageDigest(ffi::EVP_shake256()) }
+ }
+
pub fn ripemd160() -> MessageDigest {
unsafe { MessageDigest(ffi::EVP_ripemd160()) }
}
@@ -119,11 +149,29 @@ use self::State::*;
/// assert_eq!(&*res, spec);
/// ```
///
+/// Use an XOF hasher (OpenSSL 1.1.1+):
+///
+/// ```
+/// #[cfg(ossl111)]
+/// {
+/// use openssl::hash::{hash_xof, MessageDigest};
+///
+/// let data = b"\x41\x6c\x6c\x20\x79\x6f\x75\x72\x20\x62\x61\x73\x65\x20\x61\x72\x65\x20\x62\x65\x6c\x6f\x6e\x67\x20\x74\x6f\x20\x75\x73";
+/// let spec = b"\x49\xd0\x69\x7f\xf5\x08\x11\x1d\x8b\x84\xf1\x5e\x46\xda\xf1\x35";
+/// let mut buf = vec![0; 16];
+/// hash_xof(MessageDigest::shake_128(), data, buf.as_mut_slice()).unwrap();
+/// assert_eq!(buf, spec);
+/// }
+/// ```
+///
/// # Warning
///
/// Don't actually use MD5 and SHA-1 hashes, they're not secure anymore.
///
/// Don't ever hash passwords, use the functions in the `pkcs5` module or bcrypt/scrypt instead.
+///
+/// For extendable output functions (XOFs, i.e. SHAKE128/SHAKE256), you must use finish_xof instead
+/// of finish and provide a buf to store the hash. The hash will be as long as the buf.
pub struct Hasher {
ctx: *mut ffi::EVP_MD_CTX,
md: *const ffi::EVP_MD,
@@ -182,7 +230,7 @@ impl Hasher {
Ok(())
}
- /// Returns the hash of the data written and resets the hasher.
+ /// Returns the hash of the data written and resets the non-XOF hasher.
pub fn finish(&mut self) -> Result<DigestBytes, ErrorStack> {
if self.state == Finalized {
self.init()?;
@@ -202,6 +250,24 @@ impl Hasher {
})
}
}
+
+ /// Writes the hash of the data into the supplied buf and resets the XOF hasher.
+ /// The hash will be as long as the buf.
+ #[cfg(ossl111)]
+ pub fn finish_xof(&mut self, buf: &mut[u8]) -> Result<(), ErrorStack> {
+ if self.state == Finalized {
+ self.init()?;
+ }
+ unsafe {
+ cvt(ffi::EVP_DigestFinalXOF(
+ self.ctx,
+ buf.as_mut_ptr(),
+ buf.len(),
+ ))?;
+ self.state = Finalized;
+ Ok(())
+ }
+ }
}
impl Write for Hasher {
@@ -291,13 +357,21 @@ impl fmt::Debug for DigestBytes {
}
}
-/// Computes the hash of the `data` with the hash `t`.
+/// Computes the hash of the `data` with the non-XOF hasher `t`.
pub fn hash(t: MessageDigest, data: &[u8]) -> Result<DigestBytes, ErrorStack> {
let mut h = Hasher::new(t)?;
h.update(data)?;
h.finish()
}
+/// Computes the hash of the `data` with the XOF hasher `t` and stores it in `buf`.
+#[cfg(ossl111)]
+pub fn hash_xof(t: MessageDigest, data: &[u8], buf: &mut[u8]) -> Result<(), ErrorStack> {
+ let mut h = Hasher::new(t)?;
+ h.update(data)?;
+ h.finish_xof(buf)
+}
+
#[cfg(test)]
mod tests {
use hex::{self, FromHex};
@@ -310,6 +384,14 @@ mod tests {
assert_eq!(hex::encode(res), hashtest.1);
}
+ #[cfg(ossl111)]
+ fn hash_xof_test(hashtype: MessageDigest, hashtest: &(&str, &str)) {
+ let expected = Vec::from_hex(hashtest.1).unwrap();
+ let mut buf = vec![0; expected.len()];
+ hash_xof(hashtype, &Vec::from_hex(hashtest.0).unwrap(), buf.as_mut_slice()).unwrap();
+ assert_eq!(buf, expected);
+ }
+
fn hash_recycle_test(h: &mut Hasher, hashtest: &(&str, &str)) {
let _ = h.write_all(&Vec::from_hex(hashtest.0).unwrap()).unwrap();
let res = h.finish().unwrap();
@@ -414,6 +496,80 @@ mod tests {
}
}
+ #[cfg(ossl111)]
+ #[test]
+ fn test_sha3_224() {
+ let tests = [("416c6c20796f75722062617365206172652062656c6f6e6720746f207573",
+ "1de092dd9fbcbbf450f26264f4778abd48af851f2832924554c56913"
+ )];
+
+ for test in tests.iter() {
+ hash_test(MessageDigest::sha3_224(), test);
+ }
+ }
+
+ #[cfg(ossl111)]
+ #[test]
+ fn test_sha3_256() {
+ let tests = [("416c6c20796f75722062617365206172652062656c6f6e6720746f207573",
+ "b38e38f08bc1c0091ed4b5f060fe13e86aa4179578513ad11a6e3abba0062f61"
+ )];
+
+ for test in tests.iter() {
+ hash_test(MessageDigest::sha3_256(), test);
+ }
+ }
+
+ #[cfg(ossl111)]
+ #[test]
+ fn test_sha3_384() {
+ let tests = [("416c6c20796f75722062617365206172652062656c6f6e6720746f207573",
+ "966ee786ab3482dd811bf7c8fa8db79aa1f52f6c3c369942ef14240ebd857c6ff626ec35d9e131ff64d328\
+ ef2008ff16"
+ )];
+
+ for test in tests.iter() {
+ hash_test(MessageDigest::sha3_384(), test);
+ }
+ }
+
+ #[cfg(ossl111)]
+ #[test]
+ fn test_sha3_512() {
+ let tests = [("416c6c20796f75722062617365206172652062656c6f6e6720746f207573",
+ "c072288ef728cd53a029c47687960b9225893532f42b923156e37020bdc1eda753aafbf30af859d4f4c3a1\
+ 807caee3a79f8eb02dcd61589fbbdf5f40c8787a72"
+ )];
+
+ for test in tests.iter() {
+ hash_test(MessageDigest::sha3_512(), test);
+ }
+ }
+
+ #[cfg(ossl111)]
+ #[test]
+ fn test_shake_128() {
+ let tests = [("416c6c20796f75722062617365206172652062656c6f6e6720746f207573",
+ "49d0697ff508111d8b84f15e46daf135"
+ )];
+
+ for test in tests.iter() {
+ hash_xof_test(MessageDigest::shake_128(), test);
+ }
+ }
+
+ #[cfg(ossl111)]
+ #[test]
+ fn test_shake_256() {
+ let tests = [("416c6c20796f75722062617365206172652062656c6f6e6720746f207573",
+ "4e2dfdaa75d1e049d0eaeffe28e76b17cea47b650fb8826fe48b94664326a697"
+ )];
+
+ for test in tests.iter() {
+ hash_xof_test(MessageDigest::shake_256(), test);
+ }
+ }
+
#[test]
fn test_ripemd160() {
let tests = [("616263", "8eb208f7e05d987a9b044a8e98c6b087f15a0bfc")];