sp_crypto_hashing/
lib.rs

1// This file is part of Substrate.
2
3// Copyright (C) Parity Technologies (UK) Ltd.
4// SPDX-License-Identifier: Apache-2.0
5
6// Licensed under the Apache License, Version 2.0 (the "License");
7// you may not use this file except in compliance with the License.
8// You may obtain a copy of the License at
9//
10// 	http://www.apache.org/licenses/LICENSE-2.0
11//
12// Unless required by applicable law or agreed to in writing, software
13// distributed under the License is distributed on an "AS IS" BASIS,
14// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15// See the License for the specific language governing permissions and
16// limitations under the License.
17
18//! Hashing Functions.
19
20#![warn(missing_docs)]
21#![cfg_attr(not(feature = "std"), no_std)]
22
23use core::hash::Hasher;
24
25use byteorder::{ByteOrder, LittleEndian};
26use digest::Digest;
27
28#[inline(always)]
29fn blake2<const N: usize>(data: &[u8]) -> [u8; N] {
30	blake2b_simd::Params::new()
31		.hash_length(N)
32		.hash(data)
33		.as_bytes()
34		.try_into()
35		.expect("slice is always the necessary length")
36}
37
38/// Do a Blake2 512-bit hash and place result in `dest`.
39pub fn blake2_512_into(data: &[u8], dest: &mut [u8; 64]) {
40	*dest = blake2(data);
41}
42
43/// Do a Blake2 512-bit hash and return result.
44pub fn blake2_512(data: &[u8]) -> [u8; 64] {
45	blake2(data)
46}
47
48/// Do a Blake2 256-bit hash and return result.
49pub fn blake2_256(data: &[u8]) -> [u8; 32] {
50	blake2(data)
51}
52
53/// Do a Blake2 128-bit hash and return result.
54pub fn blake2_128(data: &[u8]) -> [u8; 16] {
55	blake2(data)
56}
57
58/// Do a Blake2 64-bit hash and return result.
59pub fn blake2_64(data: &[u8]) -> [u8; 8] {
60	blake2(data)
61}
62
63/// Do a XX 64-bit hash and place result in `dest`.
64pub fn twox_64_into(data: &[u8], dest: &mut [u8; 8]) {
65	let r0 = twox_hash::XxHash::with_seed(0).chain_update(data).finish();
66	LittleEndian::write_u64(&mut dest[0..8], r0);
67}
68
69/// Do a XX 64-bit hash and return result.
70pub fn twox_64(data: &[u8]) -> [u8; 8] {
71	let mut r: [u8; 8] = [0; 8];
72	twox_64_into(data, &mut r);
73	r
74}
75
76/// Do a XX 128-bit hash and place result in `dest`.
77pub fn twox_128_into(data: &[u8], dest: &mut [u8; 16]) {
78	let r0 = twox_hash::XxHash::with_seed(0).chain_update(data).finish();
79	let r1 = twox_hash::XxHash::with_seed(1).chain_update(data).finish();
80	LittleEndian::write_u64(&mut dest[0..8], r0);
81	LittleEndian::write_u64(&mut dest[8..16], r1);
82}
83
84/// Do a XX 128-bit hash and return result.
85pub fn twox_128(data: &[u8]) -> [u8; 16] {
86	let mut r: [u8; 16] = [0; 16];
87	twox_128_into(data, &mut r);
88	r
89}
90
91/// Do a XX 256-bit hash and place result in `dest`.
92pub fn twox_256_into(data: &[u8], dest: &mut [u8; 32]) {
93	let r0 = twox_hash::XxHash::with_seed(0).chain_update(data).finish();
94	let r1 = twox_hash::XxHash::with_seed(1).chain_update(data).finish();
95	let r2 = twox_hash::XxHash::with_seed(2).chain_update(data).finish();
96	let r3 = twox_hash::XxHash::with_seed(3).chain_update(data).finish();
97	LittleEndian::write_u64(&mut dest[0..8], r0);
98	LittleEndian::write_u64(&mut dest[8..16], r1);
99	LittleEndian::write_u64(&mut dest[16..24], r2);
100	LittleEndian::write_u64(&mut dest[24..32], r3);
101}
102
103/// Do a XX 256-bit hash and return result.
104pub fn twox_256(data: &[u8]) -> [u8; 32] {
105	let mut r: [u8; 32] = [0; 32];
106	twox_256_into(data, &mut r);
107	r
108}
109
110/// Do a keccak 256-bit hash and return result.
111pub fn keccak_256(data: &[u8]) -> [u8; 32] {
112	sha3::Keccak256::digest(data).into()
113}
114
115/// Do a keccak 512-bit hash and return result.
116pub fn keccak_512(data: &[u8]) -> [u8; 64] {
117	sha3::Keccak512::digest(data).into()
118}
119
120/// Do a sha2 256-bit hash and return result.
121pub fn sha2_256(data: &[u8]) -> [u8; 32] {
122	sha2::Sha256::digest(data).into()
123}
124
125#[cfg(test)]
126mod test {
127	use super::*;
128
129	#[test]
130	fn blake2b() {
131		assert_eq!(sp_crypto_hashing_proc_macro::blake2b_64!(b""), blake2_64(b"")[..]);
132		assert_eq!(sp_crypto_hashing_proc_macro::blake2b_256!(b"test"), blake2_256(b"test")[..]);
133		assert_eq!(sp_crypto_hashing_proc_macro::blake2b_512!(b""), blake2_512(b"")[..]);
134	}
135
136	#[test]
137	fn keccak() {
138		assert_eq!(sp_crypto_hashing_proc_macro::keccak_256!(b"test"), keccak_256(b"test")[..]);
139		assert_eq!(sp_crypto_hashing_proc_macro::keccak_512!(b"test"), keccak_512(b"test")[..]);
140	}
141
142	#[test]
143	fn sha2() {
144		assert_eq!(sp_crypto_hashing_proc_macro::sha2_256!(b"test"), sha2_256(b"test")[..]);
145	}
146
147	#[test]
148	fn twox() {
149		assert_eq!(sp_crypto_hashing_proc_macro::twox_128!(b"test"), twox_128(b"test")[..]);
150		assert_eq!(sp_crypto_hashing_proc_macro::twox_64!(b""), twox_64(b"")[..]);
151	}
152
153	#[test]
154	fn twox_concats() {
155		assert_eq!(
156			sp_crypto_hashing_proc_macro::twox_128!(b"test", b"123", b"45", b"", b"67890"),
157			twox_128(&b"test1234567890"[..]),
158		);
159		assert_eq!(
160			sp_crypto_hashing_proc_macro::twox_128!(b"test", test, b"45", b"", b"67890"),
161			twox_128(&b"testtest4567890"[..]),
162		);
163	}
164}