openvm_keccak256_guest/
lib.rs

1#![no_std]
2
3#[cfg(target_os = "zkvm")]
4use core::mem::MaybeUninit;
5
6/// This is custom-0 defined in RISC-V spec document
7pub const OPCODE: u8 = 0x0b;
8pub const KECCAK256_FUNCT3: u8 = 0b100;
9pub const KECCAK256_FUNCT7: u8 = 0;
10
11/// The keccak256 cryptographic hash function.
12#[inline(always)]
13pub fn keccak256(input: &[u8]) -> [u8; 32] {
14    #[cfg(not(target_os = "zkvm"))]
15    {
16        let mut output = [0u8; 32];
17        set_keccak256(input, &mut output);
18        output
19    }
20    #[cfg(target_os = "zkvm")]
21    {
22        let mut output = MaybeUninit::<[u8; 32]>::uninit();
23        native_keccak256(input.as_ptr(), input.len(), output.as_mut_ptr() as *mut u8);
24        unsafe { output.assume_init() }
25    }
26}
27
28/// Native hook for keccak256 for use with `alloy-primitives` "native-keccak" feature.
29///
30/// # Safety
31///
32/// The VM accepts the preimage by pointer and length, and writes the
33/// 32-byte hash.
34/// - `bytes` must point to an input buffer at least `len` long.
35/// - `output` must point to a buffer that is at least 32-bytes long.
36///
37/// [`keccak256`]: https://en.wikipedia.org/wiki/SHA-3
38/// [`sha3`]: https://docs.rs/sha3/latest/sha3/
39/// [`tiny_keccak`]: https://docs.rs/tiny-keccak/latest/tiny_keccak/
40#[cfg(target_os = "zkvm")]
41#[inline(always)]
42#[no_mangle]
43extern "C" fn native_keccak256(bytes: *const u8, len: usize, output: *mut u8) {
44    openvm_platform::custom_insn_r!(
45        opcode = OPCODE,
46        funct3 = KECCAK256_FUNCT3,
47        funct7 = KECCAK256_FUNCT7,
48        rd = In output,
49        rs1 = In bytes,
50        rs2 = In len
51    );
52}
53
54/// Sets `output` to the keccak256 hash of `input`.
55pub fn set_keccak256(input: &[u8], output: &mut [u8; 32]) {
56    #[cfg(not(target_os = "zkvm"))]
57    {
58        use tiny_keccak::Hasher;
59        let mut hasher = tiny_keccak::Keccak::v256();
60        hasher.update(input);
61        hasher.finalize(output);
62    }
63    #[cfg(target_os = "zkvm")]
64    native_keccak256(input.as_ptr(), input.len(), output.as_mut_ptr() as *mut u8);
65}