1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56
use crate::bits::FixedBytes;
#[cfg(all(feature = "native-keccak", not(feature = "tiny-keccak")))]
#[link(wasm_import_module = "vm_hooks")]
extern "C" {
/// When targeting VMs with native keccak hooks, the `native-keccak` feature
/// can be enabled to import and use the host environment's implementation
/// of [`keccak256`] in place of [`tiny_keccak`]. This is overridden when
/// the `tiny-keccak` feature is enabled.
///
/// # SAFETY
///
/// The VM accepts the preimage by pointer and length, and writes the
/// 32-byte hash.
/// - `bytes` must point to an input buffer at least `len` long.
/// - `output` must point to a buffer that is at least 32-bytes long.
///
/// [`keccak256`]: https://en.wikipedia.org/wiki/SHA-3
/// [`tiny_keccak`]: https://docs.rs/tiny-keccak/latest/tiny_keccak/
fn native_keccak256(bytes: *const u8, len: usize, output: *mut u8);
}
/// Simple interface to the [`keccak256`] hash function.
///
/// [`keccak256`]: https://en.wikipedia.org/wiki/SHA-3
pub fn keccak256<T: AsRef<[u8]>>(bytes: T) -> FixedBytes<32> {
cfg_if::cfg_if! {
if #[cfg(all(feature = "native-keccak", not(feature = "tiny-keccak")))] {
/// Calls an external native keccak hook when `native-keccak` is enabled.
/// This is overridden when `tiny-keccak` is enabled.
fn keccak256(bytes: &[u8]) -> FixedBytes<32> {
let mut output = [0u8; 32];
// SAFETY: The output is 32-bytes, and the input comes from a slice.
unsafe { native_keccak256(bytes.as_ptr(), bytes.len(), output.as_mut_ptr()) };
output.into()
}
} else {
/// Calls [`tiny-keccak`] when the `tiny-keccak` feature is enabled or
/// when no particular keccak feature flag is specified.
///
/// [`tiny_keccak`]: https://docs.rs/tiny-keccak/latest/tiny_keccak/
fn keccak256(bytes: &[u8]) -> FixedBytes<32> {
use tiny_keccak::{Hasher, Keccak};
let mut output = [0u8; 32];
let mut hasher = Keccak::v256();
hasher.update(bytes);
hasher.finalize(&mut output);
output.into()
}
}
}
keccak256(bytes.as_ref())
}