| // Copyright 2023 The BoringSSL Authors | |
| // | |
| // Licensed under the Apache License, Version 2.0 (the "License"); | |
| // you may not use this file except in compliance with the License. | |
| // You may obtain a copy of the License at | |
| // | |
| // https://www.apache.org/licenses/LICENSE-2.0 | |
| // | |
| // Unless required by applicable law or agreed to in writing, software | |
| // distributed under the License is distributed on an "AS IS" BASIS, | |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
| // See the License for the specific language governing permissions and | |
| // limitations under the License. | |
| //! Hash functions. | |
| //! | |
| //! ``` | |
| //! use bssl_crypto::digest; | |
| //! | |
| //! // One-shot hashing. | |
| //! let digest: [u8; 32] = digest::Sha256::hash(b"hello"); | |
| //! | |
| //! // Incremental hashing. | |
| //! let mut ctx = digest::Sha256::new(); | |
| //! ctx.update(b"hel"); | |
| //! ctx.update(b"lo"); | |
| //! let digest2: [u8; 32] = ctx.digest(); | |
| //! | |
| //! assert_eq!(digest, digest2); | |
| //! | |
| //! // Hashing with dynamic dispatch. | |
| //! #[cfg(feature = "std")] | |
| //! { | |
| //! fn update_hash(ctx: &mut dyn std::io::Write) { | |
| //! ctx.write(b"hel"); | |
| //! ctx.write(b"lo"); | |
| //! } | |
| //! | |
| //! let mut ctx = digest::Sha256::new(); | |
| //! update_hash(&mut ctx); | |
| //! assert_eq!(ctx.digest(), digest); | |
| //! } | |
| //! ``` | |
| use crate::{sealed, FfiSlice, ForeignTypeRef}; | |
| use alloc::vec::Vec; | |
| #[non_exhaustive] | |
| #[doc(hidden)] | |
| pub struct MdRef; | |
| unsafe impl ForeignTypeRef for MdRef { | |
| type CType = bssl_sys::EVP_MD; | |
| } | |
| /// Provides the ability to hash in an algorithm-agnostic manner. | |
| pub trait Algorithm { | |
| /// The size of the resulting digest. | |
| const OUTPUT_LEN: usize; | |
| /// The block length (in bytes). | |
| const BLOCK_LEN: usize; | |
| /// Gets a reference to a message digest algorithm to be used by the HKDF implementation. | |
| #[doc(hidden)] | |
| fn get_md(_: sealed::SealedType) -> &'static MdRef; | |
| /// Hashes a message. | |
| fn hash_to_vec(input: &[u8]) -> Vec<u8>; | |
| /// Create a new context for incremental hashing. | |
| fn new() -> Self; | |
| /// Hash the contents of `input`. | |
| fn update(&mut self, input: &[u8]); | |
| /// Finish the hashing and return the digest. | |
| fn digest_to_vec(self) -> Vec<u8>; | |
| } | |
| /// The insecure SHA-1 hash algorithm. | |
| /// | |
| /// Some existing protocols depend on SHA-1 and so it is provided here, but it | |
| /// does not provide collision resistance and should not be used if at all | |
| /// avoidable. Use SHA-256 instead. | |
| #[derive(Clone)] | |
| pub struct InsecureSha1 { | |
| ctx: bssl_sys::SHA_CTX, | |
| } | |
| unsafe_iuf_algo!( | |
| InsecureSha1, | |
| 20, | |
| 64, | |
| EVP_sha1, | |
| SHA1, | |
| SHA1_Init, | |
| SHA1_Update, | |
| SHA1_Final | |
| ); | |
| /// The SHA-256 hash algorithm. | |
| #[derive(Clone)] | |
| pub struct Sha256 { | |
| ctx: bssl_sys::SHA256_CTX, | |
| } | |
| unsafe_iuf_algo!( | |
| Sha256, | |
| 32, | |
| 64, | |
| EVP_sha256, | |
| SHA256, | |
| SHA256_Init, | |
| SHA256_Update, | |
| SHA256_Final | |
| ); | |
| /// The SHA-384 hash algorithm. | |
| #[derive(Clone)] | |
| pub struct Sha384 { | |
| ctx: bssl_sys::SHA512_CTX, | |
| } | |
| unsafe_iuf_algo!( | |
| Sha384, | |
| 48, | |
| 128, | |
| EVP_sha384, | |
| SHA384, | |
| SHA384_Init, | |
| SHA384_Update, | |
| SHA384_Final | |
| ); | |
| /// The SHA-512 hash algorithm. | |
| #[derive(Clone)] | |
| pub struct Sha512 { | |
| ctx: bssl_sys::SHA512_CTX, | |
| } | |
| unsafe_iuf_algo!( | |
| Sha512, | |
| 64, | |
| 128, | |
| EVP_sha512, | |
| SHA512, | |
| SHA512_Init, | |
| SHA512_Update, | |
| SHA512_Final | |
| ); | |
| /// The SHA-512/256 hash algorithm. | |
| #[derive(Clone)] | |
| pub struct Sha512_256 { | |
| ctx: bssl_sys::SHA512_CTX, | |
| } | |
| unsafe_iuf_algo!( | |
| Sha512_256, | |
| 32, | |
| 128, | |
| EVP_sha512_256, | |
| SHA512_256, | |
| SHA512_256_Init, | |
| SHA512_256_Update, | |
| SHA512_256_Final | |
| ); | |
| #[cfg(test)] | |
| mod test { | |
| use super::*; | |
| use crate::test_helpers::decode_hex; | |
| #[test] | |
| fn sha256_c_type() { | |
| unsafe { | |
| assert_eq!( | |
| MdRef::from_ptr(bssl_sys::EVP_sha256() as *mut _).as_ptr(), | |
| bssl_sys::EVP_sha256() as *mut _ | |
| ) | |
| } | |
| } | |
| #[test] | |
| fn sha512_c_type() { | |
| unsafe { | |
| assert_eq!( | |
| MdRef::from_ptr(bssl_sys::EVP_sha512() as *mut _).as_ptr(), | |
| bssl_sys::EVP_sha512() as *mut _ | |
| ) | |
| } | |
| } | |
| #[test] | |
| fn sha1() { | |
| assert_eq!( | |
| decode_hex("a9993e364706816aba3e25717850c26c9cd0d89d"), | |
| InsecureSha1::hash(b"abc") | |
| ); | |
| } | |
| #[test] | |
| fn sha256() { | |
| let msg: [u8; 4] = decode_hex("74ba2521"); | |
| let expected_digest: [u8; 32] = | |
| decode_hex("b16aa56be3880d18cd41e68384cf1ec8c17680c45a02b1575dc1518923ae8b0e"); | |
| assert_eq!(Sha256::hash(&msg), expected_digest); | |
| let mut ctx = Sha256::new(); | |
| ctx.update(&msg); | |
| assert_eq!(expected_digest, ctx.digest()); | |
| let mut ctx = Sha256::new(); | |
| ctx.update(&msg[0..1]); | |
| let mut ctx2 = ctx.clone(); | |
| ctx2.update(&msg[1..]); | |
| assert_eq!(expected_digest, ctx2.digest()); | |
| } | |
| #[test] | |
| fn sha384() { | |
| assert_eq!( | |
| decode_hex("cb00753f45a35e8bb5a03d699ac65007272c32ab0eded1631a8b605a43ff5bed8086072ba1e7cc2358baeca134c825a7"), | |
| Sha384::hash(b"abc") | |
| ); | |
| } | |
| #[test] | |
| fn sha512() { | |
| let msg: [u8; 4] = decode_hex("23be86d5"); | |
| let expected_digest: [u8; 64] = decode_hex(concat!( | |
| "76d42c8eadea35a69990c63a762f330614a4699977f058adb988f406fb0be8f2", | |
| "ea3dce3a2bbd1d827b70b9b299ae6f9e5058ee97b50bd4922d6d37ddc761f8eb" | |
| )); | |
| assert_eq!(Sha512::hash(&msg), expected_digest); | |
| let mut ctx = Sha512::new(); | |
| ctx.update(&msg); | |
| assert_eq!(expected_digest, ctx.digest()); | |
| } | |
| #[test] | |
| fn sha512_256() { | |
| assert_eq!( | |
| decode_hex("53048e2681941ef99b2e29b76b4c7dabe4c2d0c634fc6d46e0e2f13107e7af23"), | |
| Sha512_256::hash(b"abc") | |
| ); | |
| } | |
| } |