1#![cfg_attr(not(feature = "std"), no_std)]
10
11#[cfg(feature = "std")]
12use std::io;
13
14pub use primitive_types::H256;
15use tiny_keccak::{Hasher, Keccak};
16
17pub const KECCAK_EMPTY: H256 = H256([
19 0xc5, 0xd2, 0x46, 0x01, 0x86, 0xf7, 0x23, 0x3c, 0x92, 0x7e, 0x7d, 0xb2, 0xdc, 0xc7, 0x03, 0xc0, 0xe5, 0x00, 0xb6,
20 0x53, 0xca, 0x82, 0x27, 0x3b, 0x7b, 0xfa, 0xd8, 0x04, 0x5d, 0x85, 0xa4, 0x70,
21]);
22
23pub const KECCAK_NULL_RLP: H256 = H256([
25 0x56, 0xe8, 0x1f, 0x17, 0x1b, 0xcc, 0x55, 0xa6, 0xff, 0x83, 0x45, 0xe6, 0x92, 0xc0, 0xf8, 0x6e, 0x5b, 0x48, 0xe0,
26 0x1b, 0x99, 0x6c, 0xad, 0xc0, 0x01, 0x62, 0x2f, 0xb5, 0xe3, 0x63, 0xb4, 0x21,
27]);
28
29pub const KECCAK_EMPTY_LIST_RLP: H256 = H256([
31 0x1d, 0xcc, 0x4d, 0xe8, 0xde, 0xc7, 0x5d, 0x7a, 0xab, 0x85, 0xb5, 0x67, 0xb6, 0xcc, 0xd4, 0x1a, 0xd3, 0x12, 0x45,
32 0x1b, 0x94, 0x8a, 0x74, 0x13, 0xf0, 0xa1, 0x42, 0xfd, 0x40, 0xd4, 0x93, 0x47,
33]);
34
35pub fn keccak<T: AsRef<[u8]>>(s: T) -> H256 {
36 let mut result = [0u8; 32];
37 write_keccak(s, &mut result);
38 H256(result)
39}
40
41pub fn keccak256(data: &mut [u8]) {
43 let mut keccak256 = Keccak::v256();
44 keccak256.update(data.as_ref());
45 keccak256.finalize(data);
46}
47
48pub fn keccak256_range(data: &mut [u8], range: core::ops::Range<usize>) {
69 let mut keccak256 = Keccak::v256();
70 keccak256.update(&data[range]);
71 keccak256.finalize(data);
72}
73
74pub fn keccak512(data: &mut [u8]) {
76 let mut keccak512 = Keccak::v512();
77 keccak512.update(data.as_ref());
78 keccak512.finalize(data);
79}
80
81pub fn keccak512_range(data: &mut [u8], range: core::ops::Range<usize>) {
101 let mut keccak512 = Keccak::v512();
102 keccak512.update(&data[range]);
103 keccak512.finalize(data);
104}
105
106pub fn keccak_256(input: &[u8], output: &mut [u8]) {
107 write_keccak(input, output);
108}
109
110pub fn keccak_512(input: &[u8], output: &mut [u8]) {
111 let mut keccak512 = Keccak::v512();
112 keccak512.update(input);
113 keccak512.finalize(output);
114}
115
116pub fn write_keccak<T: AsRef<[u8]>>(s: T, dest: &mut [u8]) {
117 let mut keccak256 = Keccak::v256();
118 keccak256.update(s.as_ref());
119 keccak256.finalize(dest);
120}
121
122#[cfg(feature = "std")]
123pub fn keccak_pipe(r: &mut dyn io::BufRead, w: &mut dyn io::Write) -> Result<H256, io::Error> {
124 let mut output = [0u8; 32];
125 let mut input = [0u8; 1024];
126 let mut keccak256 = Keccak::v256();
127
128 loop {
130 let some = r.read(&mut input)?;
131 if some == 0 {
132 break
133 }
134 keccak256.update(&input[0..some]);
135 w.write_all(&input[0..some])?;
136 }
137
138 keccak256.finalize(&mut output);
139 Ok(output.into())
140}
141
142#[cfg(feature = "std")]
143pub fn keccak_buffer(r: &mut dyn io::BufRead) -> Result<H256, io::Error> {
144 keccak_pipe(r, &mut io::sink())
145}
146
147#[cfg(test)]
148mod tests {
149 #[cfg(not(feature = "std"))]
150 extern crate alloc;
151 #[cfg(not(feature = "std"))]
152 use alloc::{vec, vec::Vec};
153
154 use super::*;
155
156 #[test]
157 fn keccak_empty() {
158 assert_eq!(keccak([0u8; 0]), KECCAK_EMPTY);
159 }
160
161 #[test]
162 fn keccak_as() {
163 assert_eq!(
164 keccak([0x41u8; 32]),
165 H256([
166 0x59, 0xca, 0xd5, 0x94, 0x86, 0x73, 0x62, 0x2c, 0x1d, 0x64, 0xe2, 0x32, 0x24, 0x88, 0xbf, 0x01, 0x61,
167 0x9f, 0x7f, 0xf4, 0x57, 0x89, 0x74, 0x1b, 0x15, 0xa9, 0xf7, 0x82, 0xce, 0x92, 0x90, 0xa8
168 ]),
169 );
170 }
171
172 #[test]
173 fn write_keccak_with_content() {
174 let data: Vec<u8> = From::from("hello world");
175 let expected = vec![
176 0x47, 0x17, 0x32, 0x85, 0xa8, 0xd7, 0x34, 0x1e, 0x5e, 0x97, 0x2f, 0xc6, 0x77, 0x28, 0x63, 0x84, 0xf8, 0x02,
177 0xf8, 0xef, 0x42, 0xa5, 0xec, 0x5f, 0x03, 0xbb, 0xfa, 0x25, 0x4c, 0xb0, 0x1f, 0xad,
178 ];
179 let mut dest = [0u8; 32];
180 write_keccak(data, &mut dest);
181
182 assert_eq!(dest, expected.as_ref());
183 }
184
185 #[cfg(feature = "std")]
186 #[test]
187 fn should_keccak_a_file() {
188 use std::{
189 fs,
190 io::{BufReader, Write},
191 };
192
193 let tmpdir = tempfile::Builder::new().prefix("keccak").tempdir().unwrap();
195 let mut path = tmpdir.path().to_owned();
196 path.push("should_keccak_a_file");
197 {
199 let mut file = fs::File::create(&path).unwrap();
200 file.write_all(b"something").unwrap();
201 }
202
203 let mut file = BufReader::new(fs::File::open(&path).unwrap());
204 let hash = keccak_buffer(&mut file).unwrap();
206
207 assert_eq!(format!("{:x}", hash), "68371d7e884c168ae2022c82bd837d51837718a7f7dfb7aa3f753074a35e1d87");
209 }
210}