├── .editorconfig ├── .gitignore ├── .travis.yml ├── Cargo.toml ├── LICENSE ├── README.md ├── benches ├── kangaroo.rs └── keccak.rs ├── build.rs ├── comparison ├── Cargo.toml ├── benches │ └── sha3.rs └── src │ └── lib.rs ├── examples └── sha3.rs ├── src ├── cshake.rs ├── k12.rs ├── keccak.rs ├── keccakf.rs ├── keccakp.rs ├── kmac.rs ├── lib.rs ├── parallel_hash.rs ├── sha3.rs ├── shake.rs └── tuple_hash.rs └── tests ├── cshake.rs ├── kangaroo.rs ├── keccak.rs ├── kmac.rs ├── parallel_hash.rs ├── sha3.rs ├── shake.rs └── tuple_hash.rs /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | [*] 3 | indent_style=space 4 | indent_size=4 5 | tab_width=4 6 | end_of_line=lf 7 | charset=utf-8 8 | trim_trailing_whitespace=true 9 | max_line_length=100 10 | insert_final_newline=true 11 | 12 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | target 2 | Cargo.lock 3 | *.swp 4 | .idea 5 | .DS_Store 6 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: rust 2 | services: docker 3 | sudo: required 4 | 5 | branches: 6 | only: 7 | - master 8 | 9 | matrix: 10 | fast_finish: false 11 | include: 12 | - env: TARGET=x86_64-unknown-linux-gnu FEATURES=--all-features 13 | rust: stable 14 | - env: TARGET=i686-unknown-linux-gnu FEATURES=--all-features 15 | rust: stable 16 | - env: TARGET=powerpc-unknown-linux-gnu FEATURES=--all-features 17 | rust: stable 18 | - env: TARGET=powerpc64-unknown-linux-gnu FEATURES=--all-features 19 | rust: stable 20 | 21 | - env: TARGET=x86_64-unknown-linux-gnu FEATURES=--all-features 22 | rust: nightly 23 | 24 | - env: TARGET=x86_64-unknown-linux-gnu FEATURES="--features cshake" 25 | rust: stable 26 | - env: TARGET=x86_64-unknown-linux-gnu FEATURES="--features fips202" 27 | rust: stable 28 | - env: TARGET=x86_64-unknown-linux-gnu FEATURES="--features k12" 29 | rust: stable 30 | - env: TARGET=x86_64-unknown-linux-gnu FEATURES="--features keccak" 31 | rust: stable 32 | - env: TARGET=x86_64-unknown-linux-gnu FEATURES="--features kmac" 33 | rust: stable 34 | - env: TARGET=x86_64-unknown-linux-gnu FEATURES="--features sha3" 35 | rust: stable 36 | - env: TARGET=x86_64-unknown-linux-gnu FEATURES="--features shake" 37 | rust: stable 38 | - env: TARGET=x86_64-unknown-linux-gnu FEATURES="--features sp800" 39 | rust: stable 40 | - env: TARGET=x86_64-unknown-linux-gnu FEATURES="--features tuple_hash" 41 | rust: stable 42 | - env: TARGET=x86_64-unknown-linux-gnu FEATURES="--features parallel_hash" 43 | rust: stable 44 | 45 | install: 46 | - cargo install cross --force 47 | - source ~/.cargo/env || true 48 | 49 | script: 50 | - cross test $FEATURES --verbose --all --release --target $TARGET 51 | 52 | cache: cargo 53 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | edition = "2018" 3 | description = "An implementation of Keccak derived functions." 4 | homepage = "https://github.com/debris/tiny-keccak" 5 | documentation = "https://docs.rs/tiny-keccak/" 6 | repository = "https://github.com/debris/tiny-keccak" 7 | license = "CC0-1.0" 8 | name = "tiny-keccak" 9 | version = "2.0.2" 10 | authors = ["debris "] 11 | keywords = ["hash", "sha3", "keccak", "crypto", "kangarootwelve"] 12 | categories = ["cryptography", "no-std"] 13 | 14 | [dependencies] 15 | crunchy = "0.2.2" 16 | 17 | [profile.dev] 18 | opt-level = 3 # Controls the --opt-level the compiler builds with 19 | debug = false # Controls whether the compiler passes `-g` 20 | 21 | [profile.test] 22 | opt-level = 3 # Controls the --opt-level the compiler builds with 23 | debug = false # Controls whether the compiler passes `-g` 24 | 25 | [workspace] 26 | members = ["comparison"] 27 | 28 | [badges] 29 | travis-ci = { repository = "debris/tiny-keccak", branch = "master"} 30 | 31 | [features] 32 | default = [] 33 | cshake = [] 34 | fips202 = ["keccak", "shake", "sha3"] 35 | k12 = [] 36 | keccak = [] 37 | kmac = ["cshake"] 38 | parallel_hash = ["cshake"] 39 | sha3 = [] 40 | shake = [] 41 | sp800 = ["cshake", "kmac", "tuple_hash"] 42 | tuple_hash = ["cshake"] 43 | 44 | [[test]] 45 | name = "keccak" 46 | required-features = ["keccak"] 47 | 48 | [[test]] 49 | name = "cshake" 50 | required-features = ["cshake"] 51 | 52 | [[test]] 53 | name = "tuple_hash" 54 | required-features = ["tuple_hash"] 55 | 56 | [[test]] 57 | name = "kangaroo" 58 | required-features = ["k12"] 59 | 60 | [[test]] 61 | name = "sha3" 62 | required-features = ["sha3"] 63 | 64 | [[test]] 65 | name = "shake" 66 | required-features = ["shake"] 67 | 68 | [[test]] 69 | name = "kmac" 70 | required-features = ["kmac"] 71 | 72 | [[test]] 73 | name = "parallel_hash" 74 | required-features = ["parallel_hash"] 75 | 76 | [[bench]] 77 | name = "keccak" 78 | required-features = ["keccak"] 79 | 80 | [[bench]] 81 | name = "kangaroo" 82 | required-features = ["k12"] 83 | 84 | [[example]] 85 | name = "sha3" 86 | required-features = ["sha3"] 87 | 88 | [package.metadata.docs.rs] 89 | all-features = true 90 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Creative Commons Legal Code 2 | 3 | CC0 1.0 Universal 4 | 5 | CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE 6 | LEGAL SERVICES. DISTRIBUTION OF THIS DOCUMENT DOES NOT CREATE AN 7 | ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS 8 | INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES 9 | REGARDING THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS 10 | PROVIDED HEREUNDER, AND DISCLAIMS LIABILITY FOR DAMAGES RESULTING FROM 11 | THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED 12 | HEREUNDER. 13 | 14 | Statement of Purpose 15 | 16 | The laws of most jurisdictions throughout the world automatically confer 17 | exclusive Copyright and Related Rights (defined below) upon the creator 18 | and subsequent owner(s) (each and all, an "owner") of an original work of 19 | authorship and/or a database (each, a "Work"). 20 | 21 | Certain owners wish to permanently relinquish those rights to a Work for 22 | the purpose of contributing to a commons of creative, cultural and 23 | scientific works ("Commons") that the public can reliably and without fear 24 | of later claims of infringement build upon, modify, incorporate in other 25 | works, reuse and redistribute as freely as possible in any form whatsoever 26 | and for any purposes, including without limitation commercial purposes. 27 | These owners may contribute to the Commons to promote the ideal of a free 28 | culture and the further production of creative, cultural and scientific 29 | works, or to gain reputation or greater distribution for their Work in 30 | part through the use and efforts of others. 31 | 32 | For these and/or other purposes and motivations, and without any 33 | expectation of additional consideration or compensation, the person 34 | associating CC0 with a Work (the "Affirmer"), to the extent that he or she 35 | is an owner of Copyright and Related Rights in the Work, voluntarily 36 | elects to apply CC0 to the Work and publicly distribute the Work under its 37 | terms, with knowledge of his or her Copyright and Related Rights in the 38 | Work and the meaning and intended legal effect of CC0 on those rights. 39 | 40 | 1. Copyright and Related Rights. A Work made available under CC0 may be 41 | protected by copyright and related or neighboring rights ("Copyright and 42 | Related Rights"). Copyright and Related Rights include, but are not 43 | limited to, the following: 44 | 45 | i. the right to reproduce, adapt, distribute, perform, display, 46 | communicate, and translate a Work; 47 | ii. moral rights retained by the original author(s) and/or performer(s); 48 | iii. publicity and privacy rights pertaining to a person's image or 49 | likeness depicted in a Work; 50 | iv. rights protecting against unfair competition in regards to a Work, 51 | subject to the limitations in paragraph 4(a), below; 52 | v. rights protecting the extraction, dissemination, use and reuse of data 53 | in a Work; 54 | vi. database rights (such as those arising under Directive 96/9/EC of the 55 | European Parliament and of the Council of 11 March 1996 on the legal 56 | protection of databases, and under any national implementation 57 | thereof, including any amended or successor version of such 58 | directive); and 59 | vii. other similar, equivalent or corresponding rights throughout the 60 | world based on applicable law or treaty, and any national 61 | implementations thereof. 62 | 63 | 2. Waiver. To the greatest extent permitted by, but not in contravention 64 | of, applicable law, Affirmer hereby overtly, fully, permanently, 65 | irrevocably and unconditionally waives, abandons, and surrenders all of 66 | Affirmer's Copyright and Related Rights and associated claims and causes 67 | of action, whether now known or unknown (including existing as well as 68 | future claims and causes of action), in the Work (i) in all territories 69 | worldwide, (ii) for the maximum duration provided by applicable law or 70 | treaty (including future time extensions), (iii) in any current or future 71 | medium and for any number of copies, and (iv) for any purpose whatsoever, 72 | including without limitation commercial, advertising or promotional 73 | purposes (the "Waiver"). Affirmer makes the Waiver for the benefit of each 74 | member of the public at large and to the detriment of Affirmer's heirs and 75 | successors, fully intending that such Waiver shall not be subject to 76 | revocation, rescission, cancellation, termination, or any other legal or 77 | equitable action to disrupt the quiet enjoyment of the Work by the public 78 | as contemplated by Affirmer's express Statement of Purpose. 79 | 80 | 3. Public License Fallback. Should any part of the Waiver for any reason 81 | be judged legally invalid or ineffective under applicable law, then the 82 | Waiver shall be preserved to the maximum extent permitted taking into 83 | account Affirmer's express Statement of Purpose. In addition, to the 84 | extent the Waiver is so judged Affirmer hereby grants to each affected 85 | person a royalty-free, non transferable, non sublicensable, non exclusive, 86 | irrevocable and unconditional license to exercise Affirmer's Copyright and 87 | Related Rights in the Work (i) in all territories worldwide, (ii) for the 88 | maximum duration provided by applicable law or treaty (including future 89 | time extensions), (iii) in any current or future medium and for any number 90 | of copies, and (iv) for any purpose whatsoever, including without 91 | limitation commercial, advertising or promotional purposes (the 92 | "License"). The License shall be deemed effective as of the date CC0 was 93 | applied by Affirmer to the Work. Should any part of the License for any 94 | reason be judged legally invalid or ineffective under applicable law, such 95 | partial invalidity or ineffectiveness shall not invalidate the remainder 96 | of the License, and in such case Affirmer hereby affirms that he or she 97 | will not (i) exercise any of his or her remaining Copyright and Related 98 | Rights in the Work or (ii) assert any associated claims and causes of 99 | action with respect to the Work, in either case contrary to Affirmer's 100 | express Statement of Purpose. 101 | 102 | 4. Limitations and Disclaimers. 103 | 104 | a. No trademark or patent rights held by Affirmer are waived, abandoned, 105 | surrendered, licensed or otherwise affected by this document. 106 | b. Affirmer offers the Work as-is and makes no representations or 107 | warranties of any kind concerning the Work, express, implied, 108 | statutory or otherwise, including without limitation warranties of 109 | title, merchantability, fitness for a particular purpose, non 110 | infringement, or the absence of latent or other defects, accuracy, or 111 | the present or absence of errors, whether or not discoverable, all to 112 | the greatest extent permissible under applicable law. 113 | c. Affirmer disclaims responsibility for clearing rights of other persons 114 | that may apply to the Work or any use thereof, including without 115 | limitation any person's Copyright and Related Rights in the Work. 116 | Further, Affirmer disclaims responsibility for obtaining any necessary 117 | consents, permissions or other rights required for any use of the 118 | Work. 119 | d. Affirmer understands and acknowledges that Creative Commons is not a 120 | party to this document and has no duty or obligation with respect to 121 | this CC0 or use of the Work. 122 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # tiny-keccak 2 | 3 | An implementation of Keccak derived functions specified in [`FIPS-202`], [`SP800-185`] and [`KangarooTwelve`]. 4 | 5 | [![Build Status][travis-image]][travis-url] 6 | 7 | [travis-image]: https://travis-ci.org/debris/tiny-keccak.svg?branch=master 8 | [travis-url]: https://travis-ci.org/debris/tiny-keccak 9 | [`FIPS-202`]: https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.202.pdf 10 | [`SP800-185`]: https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-185.pdf 11 | [`KangarooTwelve`]: https://eprint.iacr.org/2016/770.pdf 12 | 13 | [`Documentation`](https://docs.rs/tiny-keccak) 14 | 15 | The `Keccak-f[1600]` permutation is fully unrolled; it's nearly as fast 16 | as the Keccak team's optimized permutation. 17 | 18 | ## Usage 19 | 20 | In your `Cargo.toml` specify what features (hash functions, you are intending to use). 21 | Available options are: `cshake`, `fips202`, `k12`, `keccak`, `kmac`, `parallel_hash`, `sha3`, 22 | `shake`, `sp800`, `tuple_hash`. 23 | 24 | ```toml 25 | [dependencies] 26 | tiny-keccak = { version = "2.0", features = ["sha3"] } 27 | ``` 28 | 29 | ## Example 30 | 31 | ```rust 32 | use tiny_keccak::Sha3; 33 | 34 | fn main() { 35 | let mut sha3 = Sha3::v256(); 36 | let mut output = [0u8; 32]; 37 | let expected = b"\ 38 | \x64\x4b\xcc\x7e\x56\x43\x73\x04\x09\x99\xaa\xc8\x9e\x76\x22\xf3\ 39 | \xca\x71\xfb\xa1\xd9\x72\xfd\x94\xa3\x1c\x3b\xfb\xf2\x4e\x39\x38\ 40 | "; 41 | 42 | sha3.update(b"hello"); 43 | sha3.update(b" "); 44 | sha3.update(b"world"); 45 | sha3.finalize(&mut output); 46 | 47 | assert_eq!(expected, &output); 48 | } 49 | ``` 50 | 51 | ## Benchmarks 52 | 53 | Benchmarked with [rust-crypto](https://github.com/RustCrypto) sha3 on: 54 | 55 | ``` 56 | MacBook Pro (Retina, 15-inch, Mid 2015) 57 | 2,5 GHz Intel Core i7 58 | 16 GB 1600 MHz DDR3 59 | Intel Iris Pro 1536 MB 60 | ``` 61 | 62 | Benchmark code is available [here](https://github.com/debris/tiny-keccak/blob/master/comparison/benches/sha3.rs) 63 | 64 | ``` 65 | running 4 tests 66 | test rust_crypto_sha3_256_input_32_bytes ... bench: 677 ns/iter (+/- 113) = 47 MB/s 67 | test rust_crypto_sha3_256_input_4096_bytes ... bench: 17,619 ns/iter (+/- 4,174) = 232 MB/s 68 | test tiny_keccak_sha3_256_input_32_bytes ... bench: 569 ns/iter (+/- 204) = 56 MB/s 69 | test tiny_keccak_sha3_256_input_4096_bytes ... bench: 17,185 ns/iter (+/- 4,575) = 238 MB/s 70 | ``` 71 | -------------------------------------------------------------------------------- /benches/kangaroo.rs: -------------------------------------------------------------------------------- 1 | #![feature(test)] 2 | 3 | extern crate test; 4 | 5 | use test::Bencher; 6 | use tiny_keccak::{KangarooTwelve, Hasher}; 7 | 8 | #[bench] 9 | fn bench_k12(b: &mut Bencher) { 10 | let data = [0u8; 32]; 11 | b.bytes = data.len() as u64; 12 | 13 | b.iter(|| { 14 | let mut res = [0u8; 32]; 15 | let mut k12 = KangarooTwelve::new(&[]); 16 | k12.update(&data); 17 | k12.finalize(&mut res); 18 | }); 19 | } 20 | -------------------------------------------------------------------------------- /benches/keccak.rs: -------------------------------------------------------------------------------- 1 | #![feature(test)] 2 | 3 | extern crate test; 4 | 5 | use test::Bencher; 6 | use tiny_keccak::{keccakf, Keccak, Hasher}; 7 | 8 | #[bench] 9 | fn bench_keccak_256_input_4096_bytes(b: &mut Bencher) { 10 | let data = [254u8; 4096]; 11 | b.bytes = data.len() as u64; 12 | 13 | b.iter(|| { 14 | let mut res: [u8; 32] = [0; 32]; 15 | let mut keccak = Keccak::v256(); 16 | keccak.update(&data); 17 | keccak.finalize(&mut res); 18 | }); 19 | } 20 | 21 | #[bench] 22 | fn keccakf_u64(b: &mut Bencher) { 23 | const WORDS: usize = 25; 24 | b.bytes = (WORDS * 8) as u64; 25 | 26 | b.iter(|| { 27 | let mut data = [0u64; WORDS]; 28 | keccakf(&mut data); 29 | }); 30 | } 31 | 32 | #[bench] 33 | fn bench_keccak256(b: &mut Bencher) { 34 | let data = [0u8; 32]; 35 | b.bytes = data.len() as u64; 36 | 37 | b.iter(|| { 38 | let mut res: [u8; 32] = [0; 32]; 39 | let mut keccak = Keccak::v256(); 40 | keccak.update(&data); 41 | keccak.finalize(&mut res); 42 | }); 43 | } 44 | -------------------------------------------------------------------------------- /build.rs: -------------------------------------------------------------------------------- 1 | #[cfg(not(any( 2 | feature = "keccak", 3 | feature = "shake", 4 | feature = "sha3", 5 | feature = "cshake", 6 | feature = "kmac", 7 | feature = "tuple_hash", 8 | feature = "parallel_hash", 9 | feature = "k12", 10 | feature = "fips202", 11 | feature = "sp800" 12 | )))] 13 | compile_error!( 14 | "You need to specify at least one hash function you intend to use. \ 15 | Available options:\n\ 16 | keccak, shake, sha3, cshake, kmac, tuple_hash, parallel_hash, k12, fips202, sp800\n\ 17 | e.g.\n\ 18 | tiny-keccak = { version = \"2.0.0\", features = [\"sha3\"] }" 19 | ); 20 | 21 | fn main() { 22 | } 23 | -------------------------------------------------------------------------------- /comparison/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | edition = "2018" 3 | name = "comparison" 4 | version = "0.1.0" 5 | authors = ["debris "] 6 | 7 | [dependencies] 8 | tiny-keccak = { path = "../", features = ["sha3"] } 9 | sha3 = "0.8.2" 10 | -------------------------------------------------------------------------------- /comparison/benches/sha3.rs: -------------------------------------------------------------------------------- 1 | #![feature(test)] 2 | 3 | extern crate test; 4 | 5 | use test::Bencher; 6 | 7 | #[bench] 8 | fn tiny_keccak_sha3_256_input_32_bytes(b: &mut Bencher) { 9 | use tiny_keccak::{Sha3, Hasher}; 10 | let data = vec![254u8; 32]; 11 | b.bytes = data.len() as u64; 12 | 13 | b.iter(|| { 14 | let mut res: [u8; 32] = [0; 32]; 15 | let mut sha3 = Sha3::v256(); 16 | sha3.update(&data); 17 | sha3.finalize(&mut res); 18 | }); 19 | } 20 | 21 | #[bench] 22 | fn tiny_keccak_sha3_256_input_4096_bytes(b: &mut Bencher) { 23 | use tiny_keccak::{Sha3, Hasher}; 24 | let data = vec![254u8; 4096]; 25 | b.bytes = data.len() as u64; 26 | 27 | b.iter(|| { 28 | let mut res: [u8; 32] = [0; 32]; 29 | let mut sha3 = Sha3::v256(); 30 | sha3.update(&data); 31 | sha3.finalize(&mut res); 32 | }); 33 | } 34 | 35 | #[bench] 36 | fn rust_crypto_sha3_256_input_32_bytes(b: &mut Bencher) { 37 | use sha3::{Digest, Sha3_256}; 38 | let data = vec![254u8; 32]; 39 | b.bytes = data.len() as u64; 40 | 41 | b.iter(|| { 42 | let mut sha3 = Sha3_256::default(); 43 | sha3.input(&data); 44 | sha3.result(); 45 | }); 46 | } 47 | 48 | #[bench] 49 | fn rust_crypto_sha3_256_input_4096_bytes(b: &mut Bencher) { 50 | use sha3::{Digest, Sha3_256}; 51 | let data = vec![254u8; 4096]; 52 | b.bytes = data.len() as u64; 53 | 54 | b.iter(|| { 55 | let mut sha3 = Sha3_256::default(); 56 | sha3.input(&data); 57 | sha3.result(); 58 | }); 59 | } 60 | -------------------------------------------------------------------------------- /comparison/src/lib.rs: -------------------------------------------------------------------------------- 1 | #[cfg(test)] 2 | mod tests { 3 | #[test] 4 | fn it_works() {} 5 | } 6 | -------------------------------------------------------------------------------- /examples/sha3.rs: -------------------------------------------------------------------------------- 1 | use tiny_keccak::{Hasher, Sha3}; 2 | 3 | fn main() { 4 | let mut sha3 = Sha3::v256(); 5 | let mut output = [0; 32]; 6 | let expected = b"\ 7 | \x64\x4b\xcc\x7e\x56\x43\x73\x04\x09\x99\xaa\xc8\x9e\x76\x22\xf3\ 8 | \xca\x71\xfb\xa1\xd9\x72\xfd\x94\xa3\x1c\x3b\xfb\xf2\x4e\x39\x38\ 9 | "; 10 | 11 | sha3.update(b"hello"); 12 | sha3.update(b" "); 13 | sha3.update(b"world"); 14 | sha3.finalize(&mut output); 15 | 16 | assert_eq!(expected, &output); 17 | } 18 | -------------------------------------------------------------------------------- /src/cshake.rs: -------------------------------------------------------------------------------- 1 | //! The `cSHAKE` extendable-output functions defined in [`SP800-185`]. 2 | //! 3 | //! [`SP800-185`]: https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-185.pdf 4 | 5 | use crate::{bits_to_rate, keccakf::KeccakF, left_encode, Hasher, KeccakState, Xof}; 6 | 7 | /// The `cSHAKE` extendable-output functions defined in [`SP800-185`]. 8 | /// 9 | /// # Usage 10 | /// 11 | /// ```toml 12 | /// [dependencies] 13 | /// tiny-keccak = { version = "2.0.0", features = ["cshake"] } 14 | /// ``` 15 | /// 16 | /// [`SP800-185`]: https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-185.pdf 17 | #[derive(Clone)] 18 | pub struct CShake { 19 | state: KeccakState, 20 | } 21 | 22 | impl CShake { 23 | const DELIM: u8 = 0x04; 24 | 25 | /// Creates new [`CShake`] hasher with a security level of 128 bits. 26 | /// 27 | /// [`CShake`]: struct.CShake.html 28 | pub fn v128(name: &[u8], custom_string: &[u8]) -> CShake { 29 | CShake::new(name, custom_string, 128) 30 | } 31 | 32 | /// Creates new [`CShake`] hasher with a security level of 256 bits. 33 | /// 34 | /// [`CShake`]: struct.CShake.html 35 | pub fn v256(name: &[u8], custom_string: &[u8]) -> CShake { 36 | CShake::new(name, custom_string, 256) 37 | } 38 | 39 | pub(crate) fn new(name: &[u8], custom_string: &[u8], bits: usize) -> CShake { 40 | let rate = bits_to_rate(bits); 41 | // if there is no name and no customization string 42 | // cSHAKE is SHAKE 43 | if name.is_empty() && custom_string.is_empty() { 44 | let state = KeccakState::new(rate, 0x1f); 45 | return CShake { state }; 46 | } 47 | 48 | let mut state = KeccakState::new(rate, Self::DELIM); 49 | state.update(left_encode(rate).value()); 50 | state.update(left_encode(name.len() * 8).value()); 51 | state.update(name); 52 | state.update(left_encode(custom_string.len() * 8).value()); 53 | state.update(custom_string); 54 | state.fill_block(); 55 | CShake { state } 56 | } 57 | 58 | pub(crate) fn fill_block(&mut self) { 59 | self.state.fill_block(); 60 | } 61 | } 62 | 63 | impl Hasher for CShake { 64 | fn update(&mut self, input: &[u8]) { 65 | self.state.update(input); 66 | } 67 | 68 | fn finalize(self, output: &mut [u8]) { 69 | self.state.finalize(output); 70 | } 71 | } 72 | 73 | impl Xof for CShake { 74 | fn squeeze(&mut self, output: &mut [u8]) { 75 | self.state.squeeze(output); 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /src/k12.rs: -------------------------------------------------------------------------------- 1 | //! The `KangarooTwelve` hash function defined [`here`]. 2 | //! 3 | //! [`here`]: https://eprint.iacr.org/2016/770.pdf 4 | 5 | use crate::{bits_to_rate, keccakp::KeccakP, EncodedLen, Hasher, IntoXof, KeccakState, Xof}; 6 | 7 | fn encode_len(len: usize) -> EncodedLen { 8 | let len_view = (len as u64).to_be_bytes(); 9 | let offset = len_view.iter().position(|i| *i != 0).unwrap_or(8); 10 | let mut buffer = [0u8; 9]; 11 | buffer[..8].copy_from_slice(&len_view); 12 | buffer[8] = 8 - offset as u8; 13 | 14 | EncodedLen { offset, buffer } 15 | } 16 | 17 | /// The `KangarooTwelve` hash function defined [`here`]. 18 | /// 19 | /// # Usage 20 | /// 21 | /// ```toml 22 | /// [dependencies] 23 | /// tiny-keccak = { version = "2.0.0", features = ["k12"] } 24 | /// ``` 25 | /// 26 | /// [`here`]: https://eprint.iacr.org/2016/770.pdf 27 | #[derive(Clone)] 28 | pub struct KangarooTwelve { 29 | state: KeccakState, 30 | current_chunk: KeccakState, 31 | custom_string: Option, 32 | written: usize, 33 | chunks: usize, 34 | } 35 | 36 | impl KangarooTwelve { 37 | const MAX_CHUNK_SIZE: usize = 8192; 38 | 39 | /// Creates new [`KangarooTwelve`] hasher with a security level of 128 bits. 40 | /// 41 | /// [`KangarooTwelve`]: struct.KangarooTwelve.html 42 | pub fn new(custom_string: T) -> Self { 43 | let rate = bits_to_rate(128); 44 | KangarooTwelve { 45 | state: KeccakState::new(rate, 0), 46 | current_chunk: KeccakState::new(rate, 0x0b), 47 | custom_string: Some(custom_string), 48 | written: 0, 49 | chunks: 0, 50 | } 51 | } 52 | } 53 | 54 | impl> Hasher for KangarooTwelve { 55 | fn update(&mut self, input: &[u8]) { 56 | let mut to_absorb = input; 57 | if self.chunks == 0 { 58 | let todo = core::cmp::min(Self::MAX_CHUNK_SIZE - self.written, to_absorb.len()); 59 | self.state.update(&to_absorb[..todo]); 60 | self.written += todo; 61 | to_absorb = &to_absorb[todo..]; 62 | 63 | if to_absorb.len() > 0 && self.written == Self::MAX_CHUNK_SIZE { 64 | self.state.update(&[0x03, 0, 0, 0, 0, 0, 0, 0]); 65 | self.written = 0; 66 | self.chunks += 1; 67 | } 68 | } 69 | 70 | while to_absorb.len() > 0 { 71 | if self.written == Self::MAX_CHUNK_SIZE { 72 | let mut chunk_hash = [0u8; 32]; 73 | let current_chunk = self.current_chunk.clone(); 74 | self.current_chunk.reset(); 75 | current_chunk.finalize(&mut chunk_hash); 76 | self.state.update(&chunk_hash); 77 | self.written = 0; 78 | self.chunks += 1; 79 | } 80 | 81 | let todo = core::cmp::min(Self::MAX_CHUNK_SIZE - self.written, to_absorb.len()); 82 | self.current_chunk.update(&to_absorb[..todo]); 83 | self.written += todo; 84 | to_absorb = &to_absorb[todo..]; 85 | } 86 | } 87 | 88 | fn finalize(self, output: &mut [u8]) { 89 | let mut xof = self.into_xof(); 90 | xof.squeeze(output); 91 | } 92 | } 93 | 94 | /// The `KangarooTwelve` extendable-output function defined [`here`]. 95 | /// 96 | /// # Usage 97 | /// 98 | /// ```toml 99 | /// [dependencies] 100 | /// tiny-keccak = { version = "2.0.0", features = ["k12"] } 101 | /// ``` 102 | /// 103 | /// # Example 104 | /// 105 | /// ``` 106 | /// # use tiny_keccak::{KangarooTwelve, Xof, IntoXof, Hasher}; 107 | /// let input = b"hello world"; 108 | /// let mut output = [0u8; 64]; 109 | /// let mut hasher = KangarooTwelve::new(b""); 110 | /// hasher.update(input); 111 | /// let mut xof = hasher.into_xof(); 112 | /// xof.squeeze(&mut output[..32]); 113 | /// xof.squeeze(&mut output[32..]); 114 | /// ``` 115 | /// 116 | /// --- 117 | /// 118 | /// [`KangarooTwelveXof`] can be created only by using [`KangarooTwelve::IntoXof`] interface. 119 | /// 120 | /// [`here`]: https://eprint.iacr.org/2016/770.pdf 121 | /// [`KangarooTwelveXof`]: struct.KangarooTwelveXof.html 122 | /// [`KangarooTwelve::IntoXof`]: struct.KangarooTwelve.html#impl-IntoXof 123 | #[derive(Clone)] 124 | pub struct KangarooTwelveXof { 125 | state: KeccakState, 126 | } 127 | 128 | impl> IntoXof for KangarooTwelve { 129 | type Xof = KangarooTwelveXof; 130 | 131 | fn into_xof(mut self) -> KangarooTwelveXof { 132 | let custom_string = self 133 | .custom_string 134 | .take() 135 | .expect("KangarooTwelve cannot be initialized without custom_string; qed"); 136 | let encoded_len = encode_len(custom_string.as_ref().len()); 137 | self.update(custom_string.as_ref()); 138 | self.update(encoded_len.value()); 139 | 140 | if self.chunks == 0 { 141 | self.state.delim = 0x07; 142 | } else { 143 | let encoded_chunks = encode_len(self.chunks); 144 | let mut tmp_chunk = [0u8; 32]; 145 | self.current_chunk.finalize(&mut tmp_chunk); 146 | self.state.update(&tmp_chunk); 147 | self.state.update(encoded_chunks.value()); 148 | self.state.update(&[0xff, 0xff]); 149 | self.state.delim = 0x06; 150 | } 151 | 152 | KangarooTwelveXof { state: self.state } 153 | } 154 | } 155 | 156 | impl Xof for KangarooTwelveXof { 157 | fn squeeze(&mut self, output: &mut [u8]) { 158 | self.state.squeeze(output); 159 | } 160 | } 161 | -------------------------------------------------------------------------------- /src/keccak.rs: -------------------------------------------------------------------------------- 1 | //! The `Keccak` hash functions. 2 | 3 | use super::{bits_to_rate, keccakf::KeccakF, Hasher, KeccakState}; 4 | 5 | /// The `Keccak` hash functions defined in [`Keccak SHA3 submission`]. 6 | /// 7 | /// # Usage 8 | /// 9 | /// ```toml 10 | /// [dependencies] 11 | /// tiny-keccak = { version = "2.0.0", features = ["keccak"] } 12 | /// ``` 13 | /// 14 | /// [`Keccak SHA3 submission`]: https://keccak.team/files/Keccak-submission-3.pdf 15 | #[derive(Clone)] 16 | pub struct Keccak { 17 | state: KeccakState, 18 | } 19 | 20 | impl Keccak { 21 | const DELIM: u8 = 0x01; 22 | 23 | /// Creates new [`Keccak`] hasher with a security level of 224 bits. 24 | /// 25 | /// [`Keccak`]: struct.Keccak.html 26 | pub fn v224() -> Keccak { 27 | Keccak::new(224) 28 | } 29 | 30 | /// Creates new [`Keccak`] hasher with a security level of 256 bits. 31 | /// 32 | /// [`Keccak`]: struct.Keccak.html 33 | pub fn v256() -> Keccak { 34 | Keccak::new(256) 35 | } 36 | 37 | /// Creates new [`Keccak`] hasher with a security level of 384 bits. 38 | /// 39 | /// [`Keccak`]: struct.Keccak.html 40 | pub fn v384() -> Keccak { 41 | Keccak::new(384) 42 | } 43 | 44 | /// Creates new [`Keccak`] hasher with a security level of 512 bits. 45 | /// 46 | /// [`Keccak`]: struct.Keccak.html 47 | pub fn v512() -> Keccak { 48 | Keccak::new(512) 49 | } 50 | 51 | fn new(bits: usize) -> Keccak { 52 | Keccak { 53 | state: KeccakState::new(bits_to_rate(bits), Self::DELIM), 54 | } 55 | } 56 | } 57 | 58 | impl Hasher for Keccak { 59 | /// Absorb additional input. Can be called multiple times. 60 | /// 61 | /// # Example 62 | /// 63 | /// ``` 64 | /// # use tiny_keccak::{Hasher, Keccak}; 65 | /// # 66 | /// # fn main() { 67 | /// # let mut keccak = Keccak::v256(); 68 | /// keccak.update(b"hello"); 69 | /// keccak.update(b" world"); 70 | /// # } 71 | /// ``` 72 | fn update(&mut self, input: &[u8]) { 73 | self.state.update(input); 74 | } 75 | 76 | /// Pad and squeeze the state to the output. 77 | /// 78 | /// # Example 79 | /// 80 | /// ``` 81 | /// # use tiny_keccak::{Hasher, Keccak}; 82 | /// # 83 | /// # fn main() { 84 | /// # let keccak = Keccak::v256(); 85 | /// # let mut output = [0u8; 32]; 86 | /// keccak.finalize(&mut output); 87 | /// # } 88 | /// # 89 | /// ``` 90 | fn finalize(self, output: &mut [u8]) { 91 | self.state.finalize(output); 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /src/keccakf.rs: -------------------------------------------------------------------------------- 1 | use crate::{Buffer, Permutation}; 2 | 3 | const ROUNDS: usize = 24; 4 | 5 | const RC: [u64; ROUNDS] = [ 6 | 1u64, 7 | 0x8082u64, 8 | 0x800000000000808au64, 9 | 0x8000000080008000u64, 10 | 0x808bu64, 11 | 0x80000001u64, 12 | 0x8000000080008081u64, 13 | 0x8000000000008009u64, 14 | 0x8au64, 15 | 0x88u64, 16 | 0x80008009u64, 17 | 0x8000000au64, 18 | 0x8000808bu64, 19 | 0x800000000000008bu64, 20 | 0x8000000000008089u64, 21 | 0x8000000000008003u64, 22 | 0x8000000000008002u64, 23 | 0x8000000000000080u64, 24 | 0x800au64, 25 | 0x800000008000000au64, 26 | 0x8000000080008081u64, 27 | 0x8000000000008080u64, 28 | 0x80000001u64, 29 | 0x8000000080008008u64, 30 | ]; 31 | 32 | keccak_function!("`keccak-f[1600, 24]`", keccakf, ROUNDS, RC); 33 | 34 | pub struct KeccakF; 35 | 36 | impl Permutation for KeccakF { 37 | fn execute(buffer: &mut Buffer) { 38 | keccakf(buffer.words()); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/keccakp.rs: -------------------------------------------------------------------------------- 1 | use crate::{Buffer, Permutation}; 2 | 3 | const ROUNDS: usize = 12; 4 | 5 | const RC: [u64; ROUNDS] = [ 6 | 0x000000008000808b, 7 | 0x800000000000008b, 8 | 0x8000000000008089, 9 | 0x8000000000008003, 10 | 0x8000000000008002, 11 | 0x8000000000000080, 12 | 0x000000000000800a, 13 | 0x800000008000000a, 14 | 0x8000000080008081, 15 | 0x8000000000008080, 16 | 0x0000000080000001, 17 | 0x8000000080008008, 18 | ]; 19 | 20 | keccak_function!("`keccak-p[1600, 12]`", keccakp, ROUNDS, RC); 21 | 22 | pub struct KeccakP; 23 | 24 | impl Permutation for KeccakP { 25 | fn execute(buffer: &mut Buffer) { 26 | keccakp(buffer.words()); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/kmac.rs: -------------------------------------------------------------------------------- 1 | use crate::{bits_to_rate, left_encode, right_encode, CShake, Hasher, IntoXof, Xof}; 2 | 3 | /// The `KMAC` pseudo-random functions defined in [`SP800-185`]. 4 | /// 5 | /// The KECCAK Message Authentication Code (`KMAC`) algorithm is a `PRF` and keyed hash function based 6 | /// on KECCAK. It provides variable-length output, and unlike [`SHAKE`] and [`cSHAKE`], altering the 7 | /// requested output length generates a new, unrelated output. KMAC has two variants, [`KMAC128`] and 8 | /// [`KMAC256`], built from [`cSHAKE128`] and [`cSHAKE256`], respectively. The two variants differ somewhat in 9 | /// their technical security properties. 10 | /// 11 | /// # Usage 12 | /// 13 | /// ```toml 14 | /// [dependencies] 15 | /// tiny-keccak = { version = "2.0.0", features = ["kmac"] } 16 | /// ``` 17 | /// 18 | /// [`SP800-185`]: https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-185.pdf 19 | /// [`KMAC128`]: struct.Kmac.html#method.v128 20 | /// [`KMAC256`]: struct.Kmac.html#method.v256 21 | /// [`SHAKE`]: struct.Shake.html 22 | /// [`cSHAKE`]: struct.CShake.html 23 | /// [`cSHAKE128`]: struct.CShake.html#method.v128 24 | /// [`cSHAKE256`]: struct.CShake.html#method.v256 25 | #[derive(Clone)] 26 | pub struct Kmac { 27 | state: CShake, 28 | } 29 | 30 | impl Kmac { 31 | /// Creates new [`Kmac`] hasher with a security level of 128 bits. 32 | /// 33 | /// [`Kmac`]: struct.Kmac.html 34 | pub fn v128(key: &[u8], custom_string: &[u8]) -> Kmac { 35 | Kmac::new(key, custom_string, 128) 36 | } 37 | 38 | /// Creates new [`Kmac`] hasher with a security level of 256 bits. 39 | /// 40 | /// [`Kmac`]: struct.Kmac.html 41 | pub fn v256(key: &[u8], custom_string: &[u8]) -> Kmac { 42 | Kmac::new(key, custom_string, 256) 43 | } 44 | 45 | fn new(key: &[u8], custom_string: &[u8], bits: usize) -> Kmac { 46 | let rate = bits_to_rate(bits); 47 | let mut state = CShake::new(b"KMAC", custom_string, bits); 48 | state.update(left_encode(rate).value()); 49 | state.update(left_encode(key.len() * 8).value()); 50 | state.update(key); 51 | state.fill_block(); 52 | Kmac { state } 53 | } 54 | } 55 | 56 | impl Hasher for Kmac { 57 | fn update(&mut self, input: &[u8]) { 58 | self.state.update(input) 59 | } 60 | 61 | fn finalize(mut self, output: &mut [u8]) { 62 | self.state.update(right_encode(output.len() * 8).value()); 63 | self.state.finalize(output) 64 | } 65 | } 66 | 67 | /// The `KMACXOF` extendable-output functions defined in [`SP800-185`]. 68 | /// 69 | /// # Usage 70 | /// 71 | /// ```toml 72 | /// [dependencies] 73 | /// tiny-keccak = { version = "2.0.0", features = ["kmac"] } 74 | /// ``` 75 | /// 76 | /// # Example 77 | /// 78 | /// ``` 79 | /// # use tiny_keccak::{Kmac, Xof, IntoXof, Hasher}; 80 | /// let input = b"hello world"; 81 | /// let mut output = [0u8; 64]; 82 | /// let mut kmac = Kmac::v256(b"", b""); 83 | /// kmac.update(input); 84 | /// let mut xof = kmac.into_xof(); 85 | /// xof.squeeze(&mut output[..32]); 86 | /// xof.squeeze(&mut output[32..]); 87 | /// ``` 88 | /// 89 | /// --- 90 | /// 91 | /// [`KmacXof`] can be created only by using [`Kmac::IntoXof`] interface. 92 | /// 93 | /// [`SP800-185`]: https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-185.pdf 94 | /// [`KmacXof`]: struct.KmacXof.html 95 | /// [`Kmac::IntoXof`]: struct.Kmac.html#impl-IntoXof 96 | #[derive(Clone)] 97 | pub struct KmacXof { 98 | state: CShake, 99 | } 100 | 101 | impl IntoXof for Kmac { 102 | type Xof = KmacXof; 103 | 104 | fn into_xof(mut self) -> Self::Xof { 105 | self.state.update(right_encode(0).value()); 106 | KmacXof { state: self.state } 107 | } 108 | } 109 | 110 | impl Xof for KmacXof { 111 | fn squeeze(&mut self, output: &mut [u8]) { 112 | self.state.squeeze(output) 113 | } 114 | } 115 | -------------------------------------------------------------------------------- /src/lib.rs: -------------------------------------------------------------------------------- 1 | //! Keccak derived functions specified in [`FIPS-202`], [`SP800-185`] and [`KangarooTwelve`]. 2 | //! 3 | //! # Example 4 | //! 5 | //! ``` 6 | //! # use tiny_keccak::Hasher; 7 | //! # 8 | //! # fn foo(mut hasher: H) { 9 | //! let input_a = b"hello world"; 10 | //! let input_b = b"!"; 11 | //! let mut output = [0u8; 32]; 12 | //! hasher.update(input_a); 13 | //! hasher.update(input_b); 14 | //! hasher.finalize(&mut output); 15 | //! # } 16 | //! ``` 17 | //! 18 | //! # Credits 19 | //! 20 | //! - [`coruus/keccak-tiny`] for C implementation of keccak function 21 | //! - [`@quininer`] for `no-std` support and rust implementation [`SP800-185`] 22 | //! - [`mimoo/GoKangarooTwelve`] for GO implementation of `KangarooTwelve` 23 | //! - [`@Vurich`] for optimizations 24 | //! - [`@oleganza`] for adding support for half-duplex use 25 | //! 26 | //! # License 27 | //! 28 | //! [`CC0`]. Attribution kindly requested. Blame taken too, 29 | //! but not liability. 30 | //! 31 | //! [`FIPS-202`]: https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.202.pdf 32 | //! [`SP800-185`]: https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-185.pdf 33 | //! [`KangarooTwelve`]: https://eprint.iacr.org/2016/770.pdf 34 | //! [`coruus/keccak-tiny`]: https://github.com/coruus/keccak-tiny 35 | //! [`mimoo/GoKangarooTwelve`]: https://github.com/mimoo/GoKangarooTwelve 36 | //! [`@quininer`]: https://github.com/quininer 37 | //! [`@Vurich`]: https://github.com/Vurich 38 | //! [`@oleganza`]: https://github.com/oleganza 39 | //! [`CC0`]: https://github.com/debris/tiny-keccak/blob/master/LICENSE 40 | 41 | #![no_std] 42 | #![deny(missing_docs)] 43 | 44 | const RHO: [u32; 24] = [ 45 | 1, 3, 6, 10, 15, 21, 28, 36, 45, 55, 2, 14, 27, 41, 56, 8, 25, 43, 62, 18, 39, 61, 20, 44, 46 | ]; 47 | 48 | const PI: [usize; 24] = [ 49 | 10, 7, 11, 17, 18, 3, 5, 16, 8, 21, 24, 4, 15, 23, 19, 13, 12, 2, 20, 14, 22, 9, 6, 1, 50 | ]; 51 | 52 | const WORDS: usize = 25; 53 | 54 | macro_rules! keccak_function { 55 | ($doc: expr, $name: ident, $rounds: expr, $rc: expr) => { 56 | #[doc = $doc] 57 | #[allow(unused_assignments)] 58 | #[allow(non_upper_case_globals)] 59 | pub fn $name(a: &mut [u64; $crate::WORDS]) { 60 | use crunchy::unroll; 61 | 62 | for i in 0..$rounds { 63 | let mut array: [u64; 5] = [0; 5]; 64 | 65 | // Theta 66 | unroll! { 67 | for x in 0..5 { 68 | unroll! { 69 | for y_count in 0..5 { 70 | let y = y_count * 5; 71 | array[x] ^= a[x + y]; 72 | } 73 | } 74 | } 75 | } 76 | 77 | unroll! { 78 | for x in 0..5 { 79 | unroll! { 80 | for y_count in 0..5 { 81 | let y = y_count * 5; 82 | a[y + x] ^= array[(x + 4) % 5] ^ array[(x + 1) % 5].rotate_left(1); 83 | } 84 | } 85 | } 86 | } 87 | 88 | // Rho and pi 89 | let mut last = a[1]; 90 | unroll! { 91 | for x in 0..24 { 92 | array[0] = a[$crate::PI[x]]; 93 | a[$crate::PI[x]] = last.rotate_left($crate::RHO[x]); 94 | last = array[0]; 95 | } 96 | } 97 | 98 | // Chi 99 | unroll! { 100 | for y_step in 0..5 { 101 | let y = y_step * 5; 102 | 103 | unroll! { 104 | for x in 0..5 { 105 | array[x] = a[y + x]; 106 | } 107 | } 108 | 109 | unroll! { 110 | for x in 0..5 { 111 | a[y + x] = array[x] ^ ((!array[(x + 1) % 5]) & (array[(x + 2) % 5])); 112 | } 113 | } 114 | } 115 | }; 116 | 117 | // Iota 118 | a[0] ^= $rc[i]; 119 | } 120 | } 121 | } 122 | } 123 | 124 | #[cfg(feature = "k12")] 125 | mod keccakp; 126 | 127 | #[cfg(feature = "k12")] 128 | pub use keccakp::keccakp; 129 | 130 | #[cfg(any( 131 | feature = "keccak", 132 | feature = "shake", 133 | feature = "sha3", 134 | feature = "cshake", 135 | feature = "kmac", 136 | feature = "tuple_hash", 137 | feature = "parallel_hash" 138 | ))] 139 | mod keccakf; 140 | 141 | #[cfg(any( 142 | feature = "keccak", 143 | feature = "shake", 144 | feature = "sha3", 145 | feature = "cshake", 146 | feature = "kmac", 147 | feature = "tuple_hash", 148 | feature = "parallel_hash" 149 | ))] 150 | pub use keccakf::keccakf; 151 | 152 | #[cfg(feature = "k12")] 153 | mod k12; 154 | 155 | #[cfg(feature = "k12")] 156 | pub use k12::{KangarooTwelve, KangarooTwelveXof}; 157 | 158 | #[cfg(feature = "keccak")] 159 | mod keccak; 160 | 161 | #[cfg(feature = "keccak")] 162 | pub use keccak::Keccak; 163 | 164 | #[cfg(feature = "shake")] 165 | mod shake; 166 | 167 | #[cfg(feature = "shake")] 168 | pub use shake::Shake; 169 | 170 | #[cfg(feature = "sha3")] 171 | mod sha3; 172 | 173 | #[cfg(feature = "sha3")] 174 | pub use sha3::Sha3; 175 | 176 | #[cfg(feature = "cshake")] 177 | mod cshake; 178 | 179 | #[cfg(feature = "cshake")] 180 | pub use cshake::CShake; 181 | 182 | #[cfg(feature = "kmac")] 183 | mod kmac; 184 | 185 | #[cfg(feature = "kmac")] 186 | pub use kmac::{Kmac, KmacXof}; 187 | 188 | #[cfg(feature = "tuple_hash")] 189 | mod tuple_hash; 190 | 191 | #[cfg(feature = "tuple_hash")] 192 | pub use tuple_hash::{TupleHash, TupleHashXof}; 193 | 194 | #[cfg(feature = "parallel_hash")] 195 | mod parallel_hash; 196 | 197 | #[cfg(feature = "parallel_hash")] 198 | pub use parallel_hash::{ParallelHash, ParallelHashXof}; 199 | 200 | /// A trait for hashing an arbitrary stream of bytes. 201 | /// 202 | /// # Example 203 | /// 204 | /// ``` 205 | /// # use tiny_keccak::Hasher; 206 | /// # 207 | /// # fn foo(mut hasher: H) { 208 | /// let input_a = b"hello world"; 209 | /// let input_b = b"!"; 210 | /// let mut output = [0u8; 32]; 211 | /// hasher.update(input_a); 212 | /// hasher.update(input_b); 213 | /// hasher.finalize(&mut output); 214 | /// # } 215 | /// ``` 216 | pub trait Hasher { 217 | /// Absorb additional input. Can be called multiple times. 218 | fn update(&mut self, input: &[u8]); 219 | 220 | /// Pad and squeeze the state to the output. 221 | fn finalize(self, output: &mut [u8]); 222 | } 223 | 224 | /// A trait used to convert [`Hasher`] into it's [`Xof`] counterpart. 225 | /// 226 | /// # Example 227 | /// 228 | /// ``` 229 | /// # use tiny_keccak::IntoXof; 230 | /// # 231 | /// # fn foo(hasher: H) { 232 | /// let xof = hasher.into_xof(); 233 | /// # } 234 | /// ``` 235 | /// 236 | /// [`Hasher`]: trait.Hasher.html 237 | /// [`Xof`]: trait.Xof.html 238 | pub trait IntoXof { 239 | /// A type implementing [`Xof`], eXtendable-output function interface. 240 | /// 241 | /// [`Xof`]: trait.Xof.html 242 | type Xof: Xof; 243 | 244 | /// A method used to convert type into [`Xof`]. 245 | /// 246 | /// [`Xof`]: trait.Xof.html 247 | fn into_xof(self) -> Self::Xof; 248 | } 249 | 250 | /// Extendable-output function (`XOF`) is a function on bit strings in which the output can be 251 | /// extended to any desired length. 252 | /// 253 | /// # Example 254 | /// 255 | /// ``` 256 | /// # use tiny_keccak::Xof; 257 | /// # 258 | /// # fn foo(mut xof: X) { 259 | /// let mut output = [0u8; 64]; 260 | /// xof.squeeze(&mut output[0..32]); 261 | /// xof.squeeze(&mut output[32..]); 262 | /// # } 263 | /// ``` 264 | pub trait Xof { 265 | /// A method used to retrieve another part of hash function output. 266 | fn squeeze(&mut self, output: &mut [u8]); 267 | } 268 | 269 | struct EncodedLen { 270 | offset: usize, 271 | buffer: [u8; 9], 272 | } 273 | 274 | impl EncodedLen { 275 | fn value(&self) -> &[u8] { 276 | &self.buffer[self.offset..] 277 | } 278 | } 279 | 280 | fn left_encode(len: usize) -> EncodedLen { 281 | let mut buffer = [0u8; 9]; 282 | buffer[1..].copy_from_slice(&(len as u64).to_be_bytes()); 283 | let offset = buffer.iter().position(|i| *i != 0).unwrap_or(8); 284 | buffer[offset - 1] = 9 - offset as u8; 285 | 286 | EncodedLen { 287 | offset: offset - 1, 288 | buffer, 289 | } 290 | } 291 | 292 | fn right_encode(len: usize) -> EncodedLen { 293 | let mut buffer = [0u8; 9]; 294 | buffer[..8].copy_from_slice(&(len as u64).to_be_bytes()); 295 | let offset = buffer.iter().position(|i| *i != 0).unwrap_or(7); 296 | buffer[8] = 8 - offset as u8; 297 | EncodedLen { offset, buffer } 298 | } 299 | 300 | #[derive(Default, Clone)] 301 | struct Buffer([u64; WORDS]); 302 | 303 | impl Buffer { 304 | fn words(&mut self) -> &mut [u64; WORDS] { 305 | &mut self.0 306 | } 307 | 308 | #[cfg(target_endian = "little")] 309 | #[inline] 310 | fn execute(&mut self, offset: usize, len: usize, f: F) { 311 | let buffer: &mut [u8; WORDS * 8] = unsafe { core::mem::transmute(&mut self.0) }; 312 | f(&mut buffer[offset..][..len]); 313 | } 314 | 315 | #[cfg(target_endian = "big")] 316 | #[inline] 317 | fn execute(&mut self, offset: usize, len: usize, f: F) { 318 | fn swap_endianess(buffer: &mut [u64]) { 319 | for item in buffer { 320 | *item = item.swap_bytes(); 321 | } 322 | } 323 | 324 | let start = offset / 8; 325 | let end = (offset + len + 7) / 8; 326 | swap_endianess(&mut self.0[start..end]); 327 | let buffer: &mut [u8; WORDS * 8] = unsafe { core::mem::transmute(&mut self.0) }; 328 | f(&mut buffer[offset..][..len]); 329 | swap_endianess(&mut self.0[start..end]); 330 | } 331 | 332 | fn setout(&mut self, dst: &mut [u8], offset: usize, len: usize) { 333 | self.execute(offset, len, |buffer| dst[..len].copy_from_slice(buffer)); 334 | } 335 | 336 | fn xorin(&mut self, src: &[u8], offset: usize, len: usize) { 337 | self.execute(offset, len, |dst| { 338 | assert!(dst.len() <= src.len()); 339 | let len = dst.len(); 340 | let mut dst_ptr = dst.as_mut_ptr(); 341 | let mut src_ptr = src.as_ptr(); 342 | for _ in 0..len { 343 | unsafe { 344 | *dst_ptr ^= *src_ptr; 345 | src_ptr = src_ptr.offset(1); 346 | dst_ptr = dst_ptr.offset(1); 347 | } 348 | } 349 | }); 350 | } 351 | 352 | fn pad(&mut self, offset: usize, delim: u8, rate: usize) { 353 | self.execute(offset, 1, |buff| buff[0] ^= delim); 354 | self.execute(rate - 1, 1, |buff| buff[0] ^= 0x80); 355 | } 356 | } 357 | 358 | trait Permutation { 359 | fn execute(a: &mut Buffer); 360 | } 361 | 362 | #[derive(Clone, Copy)] 363 | enum Mode { 364 | Absorbing, 365 | Squeezing, 366 | } 367 | 368 | struct KeccakState

{ 369 | buffer: Buffer, 370 | offset: usize, 371 | rate: usize, 372 | delim: u8, 373 | mode: Mode, 374 | permutation: core::marker::PhantomData

, 375 | } 376 | 377 | impl

Clone for KeccakState

{ 378 | fn clone(&self) -> Self { 379 | KeccakState { 380 | buffer: self.buffer.clone(), 381 | offset: self.offset, 382 | rate: self.rate, 383 | delim: self.delim, 384 | mode: self.mode, 385 | permutation: core::marker::PhantomData, 386 | } 387 | } 388 | } 389 | 390 | impl KeccakState

{ 391 | fn new(rate: usize, delim: u8) -> Self { 392 | assert!(rate != 0, "rate cannot be equal 0"); 393 | KeccakState { 394 | buffer: Buffer::default(), 395 | offset: 0, 396 | rate, 397 | delim, 398 | mode: Mode::Absorbing, 399 | permutation: core::marker::PhantomData, 400 | } 401 | } 402 | 403 | fn keccak(&mut self) { 404 | P::execute(&mut self.buffer); 405 | } 406 | 407 | fn update(&mut self, input: &[u8]) { 408 | if let Mode::Squeezing = self.mode { 409 | self.mode = Mode::Absorbing; 410 | self.fill_block(); 411 | } 412 | 413 | //first foldp 414 | let mut ip = 0; 415 | let mut l = input.len(); 416 | let mut rate = self.rate - self.offset; 417 | let mut offset = self.offset; 418 | while l >= rate { 419 | self.buffer.xorin(&input[ip..], offset, rate); 420 | self.keccak(); 421 | ip += rate; 422 | l -= rate; 423 | rate = self.rate; 424 | offset = 0; 425 | } 426 | 427 | self.buffer.xorin(&input[ip..], offset, l); 428 | self.offset = offset + l; 429 | } 430 | 431 | fn pad(&mut self) { 432 | self.buffer.pad(self.offset, self.delim, self.rate); 433 | } 434 | 435 | fn squeeze(&mut self, output: &mut [u8]) { 436 | if let Mode::Absorbing = self.mode { 437 | self.mode = Mode::Squeezing; 438 | self.pad(); 439 | self.fill_block(); 440 | } 441 | 442 | // second foldp 443 | let mut op = 0; 444 | let mut l = output.len(); 445 | let mut rate = self.rate - self.offset; 446 | let mut offset = self.offset; 447 | while l >= rate { 448 | self.buffer.setout(&mut output[op..], offset, rate); 449 | self.keccak(); 450 | op += rate; 451 | l -= rate; 452 | rate = self.rate; 453 | offset = 0; 454 | } 455 | 456 | self.buffer.setout(&mut output[op..], offset, l); 457 | self.offset = offset + l; 458 | } 459 | 460 | fn finalize(mut self, output: &mut [u8]) { 461 | self.squeeze(output); 462 | } 463 | 464 | fn fill_block(&mut self) { 465 | self.keccak(); 466 | self.offset = 0; 467 | } 468 | 469 | fn reset(&mut self) { 470 | self.buffer = Buffer::default(); 471 | self.offset = 0; 472 | self.mode = Mode::Absorbing; 473 | } 474 | } 475 | 476 | fn bits_to_rate(bits: usize) -> usize { 477 | 200 - bits / 4 478 | } 479 | 480 | #[cfg(test)] 481 | mod tests { 482 | use crate::{left_encode, right_encode}; 483 | 484 | #[test] 485 | fn test_left_encode() { 486 | assert_eq!(left_encode(0).value(), &[1, 0]); 487 | assert_eq!(left_encode(128).value(), &[1, 128]); 488 | assert_eq!(left_encode(65536).value(), &[3, 1, 0, 0]); 489 | assert_eq!(left_encode(4096).value(), &[2, 16, 0]); 490 | assert_eq!(left_encode(54321).value(), &[2, 212, 49]); 491 | } 492 | 493 | #[test] 494 | fn test_right_encode() { 495 | assert_eq!(right_encode(0).value(), &[0, 1]); 496 | assert_eq!(right_encode(128).value(), &[128, 1]); 497 | assert_eq!(right_encode(65536).value(), &[1, 0, 0, 3]); 498 | assert_eq!(right_encode(4096).value(), &[16, 0, 2]); 499 | assert_eq!(right_encode(54321).value(), &[212, 49, 2]); 500 | } 501 | } 502 | -------------------------------------------------------------------------------- /src/parallel_hash.rs: -------------------------------------------------------------------------------- 1 | use crate::{left_encode, right_encode, CShake, Hasher, IntoXof, Xof}; 2 | 3 | #[derive(Clone)] 4 | struct UnfinishedState { 5 | state: CShake, 6 | absorbed: usize, 7 | } 8 | 9 | struct Suboutout { 10 | state: [u8; 64], 11 | size: usize, 12 | } 13 | 14 | impl Suboutout { 15 | fn security(bits: usize) -> Suboutout { 16 | Suboutout { 17 | state: [0u8; 64], 18 | // 128 => 32, 256 => 64 19 | size: bits / 4, 20 | } 21 | } 22 | 23 | #[inline] 24 | fn as_bytes(&self) -> &[u8] { 25 | &self.state[..self.size] 26 | } 27 | 28 | #[inline] 29 | fn as_bytes_mut(&mut self) -> &mut [u8] { 30 | &mut self.state[..self.size] 31 | } 32 | } 33 | 34 | /// The `ParallelHash` hash functions defined in [`SP800-185`]. 35 | /// 36 | /// The purpose of `ParallelHash` is to support the efficient hashing of very long strings, by 37 | /// taking advantage of the parallelism available in modern processors. `ParallelHash` supports the 38 | /// [`128-bit`] and [`256-bit`] security strengths, and also provides variable-length output. 39 | /// 40 | /// # Usage 41 | /// 42 | /// ```toml 43 | /// [dependencies] 44 | /// tiny-keccak = { version = "2.0.0", features = ["parallel_hash"] } 45 | /// ``` 46 | /// 47 | /// [`SP800-185`]: https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-185.pdf 48 | /// [`128-bit`]: struct.ParallelHash.html#method.v128 49 | /// [`256-bit`]: struct.ParallelHash.html#method.v256 50 | #[derive(Clone)] 51 | pub struct ParallelHash { 52 | state: CShake, 53 | block_size: usize, 54 | bits: usize, 55 | blocks: usize, 56 | unfinished: Option, 57 | } 58 | 59 | impl ParallelHash { 60 | /// Creates new [`ParallelHash`] hasher with a security level of 128 bits. 61 | /// 62 | /// [`ParallelHash`]: struct.ParallelHash.html 63 | pub fn v128(custom_string: &[u8], block_size: usize) -> ParallelHash { 64 | ParallelHash::new(custom_string, block_size, 128) 65 | } 66 | 67 | /// Creates new [`ParallelHash`] hasher with a security level of 256 bits. 68 | /// 69 | /// [`ParallelHash`]: struct.ParallelHash.html 70 | pub fn v256(custom_string: &[u8], block_size: usize) -> ParallelHash { 71 | ParallelHash::new(custom_string, block_size, 256) 72 | } 73 | 74 | fn new(custom_string: &[u8], block_size: usize, bits: usize) -> ParallelHash { 75 | let mut state = CShake::new(b"ParallelHash", custom_string, bits); 76 | state.update(left_encode(block_size).value()); 77 | ParallelHash { 78 | state, 79 | block_size, 80 | bits, 81 | blocks: 0, 82 | unfinished: None, 83 | } 84 | } 85 | } 86 | 87 | impl Hasher for ParallelHash { 88 | fn update(&mut self, mut input: &[u8]) { 89 | if let Some(mut unfinished) = self.unfinished.take() { 90 | let to_absorb = self.block_size - unfinished.absorbed; 91 | if input.len() >= to_absorb { 92 | unfinished.state.update(&input[..to_absorb]); 93 | input = &input[to_absorb..]; 94 | 95 | let mut suboutput = Suboutout::security(self.bits); 96 | unfinished.state.finalize(suboutput.as_bytes_mut()); 97 | self.state.update(suboutput.as_bytes()); 98 | self.blocks += 1; 99 | } else { 100 | unfinished.state.update(input); 101 | unfinished.absorbed += input.len(); 102 | self.unfinished = Some(unfinished); 103 | return; 104 | } 105 | } 106 | 107 | let bits = self.bits; 108 | let input_blocks_end = input.len() / self.block_size * self.block_size; 109 | let input_blocks = &input[..input_blocks_end]; 110 | let input_end = &input[input_blocks_end..]; 111 | let parts = input_blocks.chunks(self.block_size).map(|chunk| { 112 | let mut state = CShake::new(b"", b"", bits); 113 | state.update(chunk); 114 | let mut suboutput = Suboutout::security(bits); 115 | state.finalize(suboutput.as_bytes_mut()); 116 | suboutput 117 | }); 118 | 119 | for part in parts { 120 | self.state.update(part.as_bytes()); 121 | self.blocks += 1; 122 | } 123 | 124 | if !input_end.is_empty() { 125 | assert!(self.unfinished.is_none()); 126 | let mut state = CShake::new(b"", b"", bits); 127 | state.update(input_end); 128 | self.unfinished = Some(UnfinishedState { 129 | state, 130 | absorbed: input_end.len(), 131 | }); 132 | } 133 | } 134 | 135 | fn finalize(mut self, output: &mut [u8]) { 136 | if let Some(unfinished) = self.unfinished.take() { 137 | let mut suboutput = Suboutout::security(self.bits); 138 | unfinished.state.finalize(suboutput.as_bytes_mut()); 139 | self.state.update(suboutput.as_bytes()); 140 | self.blocks += 1; 141 | } 142 | 143 | self.state.update(right_encode(self.blocks).value()); 144 | self.state.update(right_encode(output.len() * 8).value()); 145 | self.state.finalize(output); 146 | } 147 | } 148 | 149 | /// The `ParallelHashXOF` extendable-output functions defined in [`SP800-185`]. 150 | /// 151 | /// # Usage 152 | /// 153 | /// ```toml 154 | /// [dependencies] 155 | /// tiny-keccak = { version = "2.0.0", features = ["parallel_hash"] } 156 | /// ``` 157 | /// 158 | /// # Example 159 | /// 160 | /// ``` 161 | /// # use tiny_keccak::{ParallelHash, Xof, IntoXof, Hasher}; 162 | /// let input = b"hello world"; 163 | /// let mut output = [0u8; 64]; 164 | /// let mut hasher = ParallelHash::v256(b"", 8); 165 | /// hasher.update(input); 166 | /// let mut xof = hasher.into_xof(); 167 | /// xof.squeeze(&mut output[..32]); 168 | /// xof.squeeze(&mut output[32..]); 169 | /// ``` 170 | /// 171 | /// --- 172 | /// 173 | /// [`ParallelHashXof`] can be created only by using [`ParallelHash::IntoXof`] interface. 174 | /// 175 | /// 176 | /// [`SP800-185`]: https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-185.pdf 177 | /// [`ParallelHashXof`]: struct.ParallelHashXof.html 178 | /// [`ParallelHash::IntoXof`]: struct.ParallelHash.html#impl-IntoXof 179 | #[derive(Clone)] 180 | pub struct ParallelHashXof { 181 | state: CShake, 182 | } 183 | 184 | impl IntoXof for ParallelHash { 185 | type Xof = ParallelHashXof; 186 | 187 | fn into_xof(mut self) -> Self::Xof { 188 | if let Some(unfinished) = self.unfinished.take() { 189 | let mut suboutput = Suboutout::security(self.bits); 190 | unfinished.state.finalize(suboutput.as_bytes_mut()); 191 | self.state.update(suboutput.as_bytes()); 192 | self.blocks += 1; 193 | } 194 | 195 | self.state.update(right_encode(self.blocks).value()); 196 | self.state.update(right_encode(0).value()); 197 | 198 | ParallelHashXof { state: self.state } 199 | } 200 | } 201 | 202 | impl Xof for ParallelHashXof { 203 | fn squeeze(&mut self, output: &mut [u8]) { 204 | self.state.squeeze(output); 205 | } 206 | } 207 | -------------------------------------------------------------------------------- /src/sha3.rs: -------------------------------------------------------------------------------- 1 | use crate::{bits_to_rate, keccakf::KeccakF, Hasher, KeccakState}; 2 | 3 | /// The `SHA3` hash functions defined in [`FIPS-202`]. 4 | /// 5 | /// [`FIPS-202`]: https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.202.pdf 6 | /// 7 | /// # Usage 8 | /// 9 | /// ```toml 10 | /// [dependencies] 11 | /// tiny-keccak = { version = "2.0.0", features = ["sha3"] } 12 | /// ``` 13 | /// 14 | /// # Example 15 | /// 16 | /// ``` 17 | /// # use tiny_keccak::{Hasher, Sha3}; 18 | /// # 19 | /// # fn main() { 20 | /// let input = b"hello world"; 21 | /// let mut output = [0; 32]; 22 | /// let expected = b"\ 23 | /// \x64\x4b\xcc\x7e\x56\x43\x73\x04\x09\x99\xaa\xc8\x9e\x76\x22\xf3\ 24 | /// \xca\x71\xfb\xa1\xd9\x72\xfd\x94\xa3\x1c\x3b\xfb\xf2\x4e\x39\x38\ 25 | /// "; 26 | /// let mut sha3 = Sha3::v256(); 27 | /// sha3.update(input); 28 | /// sha3.finalize(&mut output); 29 | /// assert_eq!(expected, &output); 30 | /// # } 31 | /// ``` 32 | #[derive(Clone)] 33 | pub struct Sha3 { 34 | state: KeccakState, 35 | } 36 | 37 | impl Sha3 { 38 | const DELIM: u8 = 0x06; 39 | 40 | /// Creates new [`Sha3`] hasher with a security level of 224 bits. 41 | /// 42 | /// [`Sha3`]: struct.Sha3.html 43 | pub fn v224() -> Sha3 { 44 | Sha3::new(224) 45 | } 46 | 47 | /// Creates new [`Sha3`] hasher with a security level of 256 bits. 48 | /// 49 | /// [`Sha3`]: struct.Sha3.html 50 | pub fn v256() -> Sha3 { 51 | Sha3::new(256) 52 | } 53 | 54 | /// Creates new [`Sha3`] hasher with a security level of 384 bits. 55 | /// 56 | /// [`Sha3`]: struct.Sha3.html 57 | pub fn v384() -> Sha3 { 58 | Sha3::new(384) 59 | } 60 | 61 | /// Creates new [`Sha3`] hasher with a security level of 512 bits. 62 | /// 63 | /// [`Sha3`]: struct.Sha3.html 64 | pub fn v512() -> Sha3 { 65 | Sha3::new(512) 66 | } 67 | 68 | fn new(bits: usize) -> Sha3 { 69 | Sha3 { 70 | state: KeccakState::new(bits_to_rate(bits), Self::DELIM), 71 | } 72 | } 73 | } 74 | 75 | impl Hasher for Sha3 { 76 | fn update(&mut self, input: &[u8]) { 77 | self.state.update(input); 78 | } 79 | 80 | fn finalize(self, output: &mut [u8]) { 81 | self.state.finalize(output); 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /src/shake.rs: -------------------------------------------------------------------------------- 1 | use crate::{bits_to_rate, keccakf::KeccakF, Hasher, KeccakState, Xof}; 2 | 3 | /// The `SHAKE` extendable-output functions defined in [`FIPS-202`]. 4 | /// 5 | /// # Usage 6 | /// 7 | /// ```toml 8 | /// [dependencies] 9 | /// tiny-keccak = { version = "2.0.0", features = ["shake"] } 10 | /// ``` 11 | /// 12 | /// [`FIPS-202`]: https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.202.pdf 13 | #[derive(Clone)] 14 | pub struct Shake { 15 | state: KeccakState, 16 | } 17 | 18 | impl Shake { 19 | const DELIM: u8 = 0x1f; 20 | 21 | /// Creates new [`Shake`] hasher with a security level of 128 bits. 22 | /// 23 | /// [`Shake`]: struct.Shake.html 24 | pub fn v128() -> Shake { 25 | Shake::new(128) 26 | } 27 | 28 | /// Creates new [`Shake`] hasher with a security level of 256 bits. 29 | /// 30 | /// [`Shake`]: struct.Shake.html 31 | pub fn v256() -> Shake { 32 | Shake::new(256) 33 | } 34 | 35 | pub(crate) fn new(bits: usize) -> Shake { 36 | Shake { 37 | state: KeccakState::new(bits_to_rate(bits), Self::DELIM), 38 | } 39 | } 40 | } 41 | 42 | impl Hasher for Shake { 43 | fn update(&mut self, input: &[u8]) { 44 | self.state.update(input); 45 | } 46 | 47 | fn finalize(self, output: &mut [u8]) { 48 | self.state.finalize(output); 49 | } 50 | } 51 | 52 | impl Xof for Shake { 53 | fn squeeze(&mut self, output: &mut [u8]) { 54 | self.state.squeeze(output) 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/tuple_hash.rs: -------------------------------------------------------------------------------- 1 | use crate::{left_encode, right_encode, CShake, Hasher, IntoXof, Xof}; 2 | 3 | /// The `TupleHash` hash functions defined in [`SP800-185`]. 4 | /// 5 | /// `TupleHash` is designed to provide a generic, misuse-resistant way to combine a sequence of 6 | /// strings for hashing such that, for example, a `TupleHash` computed on the tuple (`"abc"` ,`"d"`) will 7 | /// produce a different hash value than a `TupleHash` computed on the tuple (`"ab"`,`"cd"`), even though 8 | /// all the remaining input parameters are kept the same, and the two resulting concatenated 9 | /// strings, without string encoding, are identical. 10 | /// 11 | /// # Usage 12 | /// 13 | /// ```toml 14 | /// [dependencies] 15 | /// tiny-keccak = { version = "2.0.0", features = ["tuple_hash"] } 16 | /// ``` 17 | /// 18 | /// [`SP800-185`]: https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-185.pdf 19 | #[derive(Clone)] 20 | pub struct TupleHash { 21 | state: CShake, 22 | } 23 | 24 | impl TupleHash { 25 | /// Creates new [`TupleHash`] hasher with a security level of 128 bits. 26 | /// 27 | /// [`TupleHash`]: struct.TupleHash.html 28 | pub fn v128(custom_string: &[u8]) -> TupleHash { 29 | TupleHash::new(custom_string, 128) 30 | } 31 | 32 | /// Creates new [`TupleHash`] hasher with a security level of 256 bits. 33 | /// 34 | /// [`TupleHash`]: struct.TupleHash.html 35 | pub fn v256(custom_string: &[u8]) -> TupleHash { 36 | TupleHash::new(custom_string, 256) 37 | } 38 | 39 | fn new(custom_string: &[u8], bits: usize) -> TupleHash { 40 | TupleHash { 41 | state: CShake::new(b"TupleHash", custom_string, bits), 42 | } 43 | } 44 | } 45 | 46 | impl Hasher for TupleHash { 47 | fn update(&mut self, input: &[u8]) { 48 | self.state.update(left_encode(input.len() * 8).value()); 49 | self.state.update(input) 50 | } 51 | 52 | fn finalize(mut self, output: &mut [u8]) { 53 | self.state.update(right_encode(output.len() * 8).value()); 54 | self.state.finalize(output) 55 | } 56 | } 57 | 58 | /// The `TupleHashXOF` extendable-output functions defined in [`SP800-185`]. 59 | /// 60 | /// # Usage 61 | /// 62 | /// ```toml 63 | /// [dependencies] 64 | /// tiny-keccak = { version = "2.0.0", features = ["tuple_hash"] } 65 | /// ``` 66 | /// 67 | /// # Example 68 | /// 69 | /// ``` 70 | /// # use tiny_keccak::{TupleHash, Xof, IntoXof, Hasher}; 71 | /// let input = b"hello world"; 72 | /// let mut output = [0u8; 64]; 73 | /// let mut hasher = TupleHash::v256(b""); 74 | /// hasher.update(input); 75 | /// let mut xof = hasher.into_xof(); 76 | /// xof.squeeze(&mut output[..32]); 77 | /// xof.squeeze(&mut output[32..]); 78 | /// ``` 79 | /// 80 | /// --- 81 | /// 82 | /// [`TupleHashXof`] can be created only by using [`TupleHash::IntoXof`] interface. 83 | /// 84 | /// 85 | /// [`SP800-185`]: https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-185.pdf 86 | /// [`TupleHashXof`]: struct.TupleHashXof.html 87 | /// [`TupleHash::IntoXof`]: struct.TupleHash.html#impl-IntoXof 88 | #[derive(Clone)] 89 | pub struct TupleHashXof { 90 | state: CShake, 91 | } 92 | 93 | impl IntoXof for TupleHash { 94 | type Xof = TupleHashXof; 95 | 96 | fn into_xof(mut self) -> TupleHashXof { 97 | self.state.update(right_encode(0).value()); 98 | TupleHashXof { state: self.state } 99 | } 100 | } 101 | 102 | impl Xof for TupleHashXof { 103 | fn squeeze(&mut self, output: &mut [u8]) { 104 | self.state.squeeze(output) 105 | } 106 | } 107 | -------------------------------------------------------------------------------- /tests/cshake.rs: -------------------------------------------------------------------------------- 1 | use tiny_keccak::{CShake, Hasher, Xof}; 2 | 3 | #[test] 4 | fn test_cshake128_one() { 5 | let input = b"\x00\x01\x02\x03"; 6 | let mut output = [0u8; 32]; 7 | let name = b""; 8 | let custom = b"Email Signature"; 9 | let expected = b"\ 10 | \xC1\xC3\x69\x25\xB6\x40\x9A\x04\xF1\xB5\x04\xFC\xBC\xA9\xD8\x2B\ 11 | \x40\x17\x27\x7C\xB5\xED\x2B\x20\x65\xFC\x1D\x38\x14\xD5\xAA\xF5\ 12 | "; 13 | 14 | let mut cshake = CShake::v128(name, custom); 15 | cshake.update(input); 16 | cshake.finalize(&mut output); 17 | assert_eq!(expected, &output); 18 | } 19 | 20 | #[test] 21 | fn test_cshake128_two() { 22 | let input = b"\ 23 | \x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F\ 24 | \x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F\ 25 | \x20\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2A\x2B\x2C\x2D\x2E\x2F\ 26 | \x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x3A\x3B\x3C\x3D\x3E\x3F\ 27 | \x40\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4A\x4B\x4C\x4D\x4E\x4F\ 28 | \x50\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5A\x5B\x5C\x5D\x5E\x5F\ 29 | \x60\x61\x62\x63\x64\x65\x66\x67\x68\x69\x6A\x6B\x6C\x6D\x6E\x6F\ 30 | \x70\x71\x72\x73\x74\x75\x76\x77\x78\x79\x7A\x7B\x7C\x7D\x7E\x7F\ 31 | \x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8A\x8B\x8C\x8D\x8E\x8F\ 32 | \x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9A\x9B\x9C\x9D\x9E\x9F\ 33 | \xA0\xA1\xA2\xA3\xA4\xA5\xA6\xA7\xA8\xA9\xAA\xAB\xAC\xAD\xAE\xAF\ 34 | \xB0\xB1\xB2\xB3\xB4\xB5\xB6\xB7\xB8\xB9\xBA\xBB\xBC\xBD\xBE\xBF\ 35 | \xC0\xC1\xC2\xC3\xC4\xC5\xC6\xC7\ 36 | "; 37 | let mut output = [0u8; 32]; 38 | let name = b""; 39 | let custom = b"Email Signature"; 40 | let expected = b"\ 41 | \xC5\x22\x1D\x50\xE4\xF8\x22\xD9\x6A\x2E\x88\x81\xA9\x61\x42\x0F\ 42 | \x29\x4B\x7B\x24\xFE\x3D\x20\x94\xBA\xED\x2C\x65\x24\xCC\x16\x6B\ 43 | "; 44 | 45 | let mut cshake = CShake::v128(name, custom); 46 | cshake.update(input); 47 | cshake.finalize(&mut output); 48 | assert_eq!(expected, &output); 49 | } 50 | 51 | #[test] 52 | fn test_cshake256_one() { 53 | let input = b"\x00\x01\x02\x03"; 54 | let mut output = [0u8; 64]; 55 | let name = b""; 56 | let custom = b"Email Signature"; 57 | let expected = b"\ 58 | \xD0\x08\x82\x8E\x2B\x80\xAC\x9D\x22\x18\xFF\xEE\x1D\x07\x0C\x48\ 59 | \xB8\xE4\xC8\x7B\xFF\x32\xC9\x69\x9D\x5B\x68\x96\xEE\xE0\xED\xD1\ 60 | \x64\x02\x0E\x2B\xE0\x56\x08\x58\xD9\xC0\x0C\x03\x7E\x34\xA9\x69\ 61 | \x37\xC5\x61\xA7\x4C\x41\x2B\xB4\xC7\x46\x46\x95\x27\x28\x1C\x8C\ 62 | "; 63 | 64 | let mut cshake = CShake::v256(name, custom); 65 | cshake.update(input); 66 | cshake.finalize(&mut output); 67 | assert_eq!(expected as &[u8], &output as &[u8]); 68 | } 69 | 70 | #[test] 71 | fn test_cshake256_two() { 72 | let input = b"\ 73 | \x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F\ 74 | \x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F\ 75 | \x20\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2A\x2B\x2C\x2D\x2E\x2F\ 76 | \x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x3A\x3B\x3C\x3D\x3E\x3F\ 77 | \x40\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4A\x4B\x4C\x4D\x4E\x4F\ 78 | \x50\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5A\x5B\x5C\x5D\x5E\x5F\ 79 | \x60\x61\x62\x63\x64\x65\x66\x67\x68\x69\x6A\x6B\x6C\x6D\x6E\x6F\ 80 | \x70\x71\x72\x73\x74\x75\x76\x77\x78\x79\x7A\x7B\x7C\x7D\x7E\x7F\ 81 | \x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8A\x8B\x8C\x8D\x8E\x8F\ 82 | \x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9A\x9B\x9C\x9D\x9E\x9F\ 83 | \xA0\xA1\xA2\xA3\xA4\xA5\xA6\xA7\xA8\xA9\xAA\xAB\xAC\xAD\xAE\xAF\ 84 | \xB0\xB1\xB2\xB3\xB4\xB5\xB6\xB7\xB8\xB9\xBA\xBB\xBC\xBD\xBE\xBF\ 85 | \xC0\xC1\xC2\xC3\xC4\xC5\xC6\xC7\ 86 | "; 87 | let mut output = [0u8; 64]; 88 | let name = b""; 89 | let custom = b"Email Signature"; 90 | let expected = b"\ 91 | \x07\xDC\x27\xB1\x1E\x51\xFB\xAC\x75\xBC\x7B\x3C\x1D\x98\x3E\x8B\ 92 | \x4B\x85\xFB\x1D\xEF\xAF\x21\x89\x12\xAC\x86\x43\x02\x73\x09\x17\ 93 | \x27\xF4\x2B\x17\xED\x1D\xF6\x3E\x8E\xC1\x18\xF0\x4B\x23\x63\x3C\ 94 | \x1D\xFB\x15\x74\xC8\xFB\x55\xCB\x45\xDA\x8E\x25\xAF\xB0\x92\xBB\ 95 | "; 96 | let mut cshake = CShake::v256(name, custom); 97 | cshake.update(input); 98 | cshake.finalize(&mut output); 99 | assert_eq!(expected as &[u8], &output as &[u8]); 100 | } 101 | 102 | #[test] 103 | fn test_cshake_as_shake() { 104 | let mut shake = CShake::v128(&[], &[]); 105 | let mut output = [0; 32]; 106 | let expected = b"\ 107 | \x43\xE4\x1B\x45\xA6\x53\xF2\xA5\xC4\x49\x2C\x1A\xDD\x54\x45\x12\ 108 | \xDD\xA2\x52\x98\x33\x46\x2B\x71\xA4\x1A\x45\xBE\x97\x29\x0B\x6F\ 109 | "; 110 | 111 | for _ in 0..16 { 112 | shake.squeeze(&mut output); 113 | } 114 | 115 | assert_eq!(expected, &output); 116 | } 117 | -------------------------------------------------------------------------------- /tests/kangaroo.rs: -------------------------------------------------------------------------------- 1 | use tiny_keccak::{Hasher, KangarooTwelve}; 2 | 3 | fn pattern(len: usize) -> Vec { 4 | (0..len).map(|j| (j % 251) as u8).collect() 5 | } 6 | 7 | fn test_kangaroo_twelve, B: AsRef<[u8]>>( 8 | custom_string: A, 9 | message: B, 10 | output_len: usize, 11 | expected: &[u8], 12 | ) { 13 | let mut kangaroo = KangarooTwelve::new(custom_string.as_ref()); 14 | kangaroo.update(message.as_ref()); 15 | let mut res = vec![0; output_len]; 16 | kangaroo.finalize(&mut res); 17 | assert_eq!(&res[output_len - expected.len()..], expected); 18 | } 19 | 20 | #[test] 21 | fn empty_kangaroo_twelve() { 22 | let expected = b"\ 23 | \x1a\xc2\xd4\x50\xfc\x3b\x42\x05\xd1\x9d\xa7\xbf\xca\x1b\x37\x51\ 24 | \x3c\x08\x03\x57\x7a\xc7\x16\x7f\x06\xfe\x2c\xe1\xf0\xef\x39\xe5\ 25 | "; 26 | test_kangaroo_twelve("", "", 32, expected); 27 | } 28 | 29 | #[test] 30 | fn kangaroo_twelve_long() { 31 | let expected = b"\ 32 | \xe8\xdc\x56\x36\x42\xf7\x22\x8c\x84\x68\x4c\x89\x84\x05\xd3\xa8\ 33 | \x34\x79\x91\x58\xc0\x79\xb1\x28\x80\x27\x7a\x1d\x28\xe2\xff\x6d\ 34 | "; 35 | test_kangaroo_twelve("", "", 10032, expected); 36 | } 37 | 38 | #[test] 39 | fn kangaroo_twelve_with_message() { 40 | let expected = b"\ 41 | \x2b\xda\x92\x45\x0e\x8b\x14\x7f\x8a\x7c\xb6\x29\xe7\x84\xa0\x58\ 42 | \xef\xca\x7c\xf7\xd8\x21\x8e\x02\xd3\x45\xdf\xaa\x65\x24\x4a\x1f\ 43 | "; 44 | test_kangaroo_twelve("", pattern(1), 32, expected); 45 | } 46 | 47 | #[test] 48 | fn kangaroo_twelve_with_message2() { 49 | let expected = b"\ 50 | \x6b\xf7\x5f\xa2\x23\x91\x98\xdb\x47\x72\xe3\x64\x78\xf8\xe1\x9b\ 51 | \x0f\x37\x12\x05\xf6\xa9\xa9\x3a\x27\x3f\x51\xdf\x37\x12\x28\x88\ 52 | "; 53 | test_kangaroo_twelve("", pattern(17), 32, expected); 54 | } 55 | 56 | #[test] 57 | fn kangaroo_twelve_with_custom_string() { 58 | let expected = b"\ 59 | \xfa\xb6\x58\xdb\x63\xe9\x4a\x24\x61\x88\xbf\x7a\xf6\x9a\x13\x30\ 60 | \x45\xf4\x6e\xe9\x84\xc5\x6e\x3c\x33\x28\xca\xaf\x1a\xa1\xa5\x83\ 61 | "; 62 | test_kangaroo_twelve(pattern(1), "", 32, expected); 63 | } 64 | 65 | #[test] 66 | fn kangaroo_twelve_with_custom_string_and_message() { 67 | let expected = b"\ 68 | \xd8\x48\xc5\x06\x8c\xed\x73\x6f\x44\x62\x15\x9b\x98\x67\xfd\x4c\ 69 | \x20\xb8\x08\xac\xc3\xd5\xbc\x48\xe0\xb0\x6b\xa0\xa3\x76\x2e\xc4\ 70 | "; 71 | test_kangaroo_twelve(pattern(41), &[0xff], 32, expected); 72 | } 73 | 74 | #[test] 75 | fn kangaroo_twelve_with_custom_string_and_message2() { 76 | let expected = b"\ 77 | \x75\xd2\xf8\x6a\x2e\x64\x45\x66\x72\x6b\x4f\xbc\xfc\x56\x57\xb9\ 78 | \xdb\xcf\x07\x0c\x7b\x0d\xca\x06\x45\x0a\xb2\x91\xd7\x44\x3b\xcf\ 79 | "; 80 | test_kangaroo_twelve( 81 | pattern(68921), 82 | &[0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff], 83 | 32, 84 | expected, 85 | ); 86 | } 87 | -------------------------------------------------------------------------------- /tests/keccak.rs: -------------------------------------------------------------------------------- 1 | use tiny_keccak::{Hasher, Keccak}; 2 | 3 | #[test] 4 | fn empty_keccak() { 5 | let keccak = Keccak::v256(); 6 | let mut output = [0; 32]; 7 | let expected = b"\ 8 | \xc5\xd2\x46\x01\x86\xf7\x23\x3c\x92\x7e\x7d\xb2\xdc\xc7\x03\xc0\ 9 | \xe5\x00\xb6\x53\xca\x82\x27\x3b\x7b\xfa\xd8\x04\x5d\x85\xa4\x70\ 10 | "; 11 | 12 | keccak.finalize(&mut output); 13 | assert_eq!(expected, &output); 14 | } 15 | 16 | #[test] 17 | fn string_keccak_256() { 18 | let mut keccak = Keccak::v256(); 19 | let mut in_and_out: [u8; 32] = [0; 32]; 20 | for i in 1..6 { 21 | in_and_out[i as usize - 1] = i 22 | } 23 | let expected = b"\ 24 | \x7d\x87\xc5\xea\x75\xf7\x37\x8b\xb7\x01\xe4\x04\xc5\x06\x39\x16\ 25 | \x1a\xf3\xef\xf6\x62\x93\xe9\xf3\x75\xb5\xf1\x7e\xb5\x04\x76\xf4\ 26 | "; 27 | keccak.update(&in_and_out[0..5]); 28 | keccak.finalize(&mut in_and_out); 29 | assert_eq!(expected, &in_and_out); 30 | } 31 | -------------------------------------------------------------------------------- /tests/kmac.rs: -------------------------------------------------------------------------------- 1 | use tiny_keccak::{Hasher, IntoXof, Kmac, Xof}; 2 | 3 | #[test] 4 | fn test_kmac128_one() { 5 | let key = b"\ 6 | \x40\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4A\x4B\x4C\x4D\x4E\x4F\ 7 | \x50\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5A\x5B\x5C\x5D\x5E\x5F\ 8 | "; 9 | let data = b"\x00\x01\x02\x03"; 10 | let custom = b""; 11 | let expected = b"\ 12 | \xE5\x78\x0B\x0D\x3E\xA6\xF7\xD3\xA4\x29\xC5\x70\x6A\xA4\x3A\x00\ 13 | \xFA\xDB\xD7\xD4\x96\x28\x83\x9E\x31\x87\x24\x3F\x45\x6E\xE1\x4E\ 14 | "; 15 | let mut output = [0u8; 32]; 16 | 17 | let mut kmac = Kmac::v128(key, custom); 18 | kmac.update(data); 19 | kmac.finalize(&mut output); 20 | assert_eq!(expected, &output); 21 | } 22 | 23 | #[test] 24 | fn test_kmac128_two() { 25 | let key = b"\ 26 | \x40\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4A\x4B\x4C\x4D\x4E\x4F\ 27 | \x50\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5A\x5B\x5C\x5D\x5E\x5F\ 28 | "; 29 | let data = b"\x00\x01\x02\x03"; 30 | let custom = b"My Tagged Application"; 31 | let expected = b"\ 32 | \x3B\x1F\xBA\x96\x3C\xD8\xB0\xB5\x9E\x8C\x1A\x6D\x71\x88\x8B\x71\ 33 | \x43\x65\x1A\xF8\xBA\x0A\x70\x70\xC0\x97\x9E\x28\x11\x32\x4A\xA5\ 34 | "; 35 | let mut output = [0u8; 32]; 36 | let mut kmac = Kmac::v128(key, custom); 37 | kmac.update(data); 38 | kmac.finalize(&mut output); 39 | assert_eq!(expected, &output); 40 | } 41 | 42 | #[test] 43 | fn test_kmac128_three() { 44 | let key = b"\ 45 | \x40\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4A\x4B\x4C\x4D\x4E\x4F\ 46 | \x50\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5A\x5B\x5C\x5D\x5E\x5F\ 47 | "; 48 | let data = b"\ 49 | \x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F\ 50 | \x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F\ 51 | \x20\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2A\x2B\x2C\x2D\x2E\x2F\ 52 | \x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x3A\x3B\x3C\x3D\x3E\x3F\ 53 | \x40\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4A\x4B\x4C\x4D\x4E\x4F\ 54 | \x50\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5A\x5B\x5C\x5D\x5E\x5F\ 55 | \x60\x61\x62\x63\x64\x65\x66\x67\x68\x69\x6A\x6B\x6C\x6D\x6E\x6F\ 56 | \x70\x71\x72\x73\x74\x75\x76\x77\x78\x79\x7A\x7B\x7C\x7D\x7E\x7F\ 57 | \x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8A\x8B\x8C\x8D\x8E\x8F\ 58 | \x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9A\x9B\x9C\x9D\x9E\x9F\ 59 | \xA0\xA1\xA2\xA3\xA4\xA5\xA6\xA7\xA8\xA9\xAA\xAB\xAC\xAD\xAE\xAF\ 60 | \xB0\xB1\xB2\xB3\xB4\xB5\xB6\xB7\xB8\xB9\xBA\xBB\xBC\xBD\xBE\xBF\ 61 | \xC0\xC1\xC2\xC3\xC4\xC5\xC6\xC7\ 62 | "; 63 | let custom = b"My Tagged Application"; 64 | let expected = b"\ 65 | \x1F\x5B\x4E\x6C\xCA\x02\x20\x9E\x0D\xCB\x5C\xA6\x35\xB8\x9A\x15\ 66 | \xE2\x71\xEC\xC7\x60\x07\x1D\xFD\x80\x5F\xAA\x38\xF9\x72\x92\x30\ 67 | "; 68 | let mut output = [0u8; 32]; 69 | 70 | let mut kmac = Kmac::v128(key, custom); 71 | kmac.update(data); 72 | kmac.finalize(&mut output); 73 | assert_eq!(expected, &output); 74 | } 75 | 76 | #[test] 77 | fn test_kmac256_one() { 78 | let key = b"\ 79 | \x40\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4A\x4B\x4C\x4D\x4E\x4F\ 80 | \x50\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5A\x5B\x5C\x5D\x5E\x5F\ 81 | "; 82 | let data = b"\x00\x01\x02\x03"; 83 | let custom = b"My Tagged Application"; 84 | let expected = b"\ 85 | \x20\xC5\x70\xC3\x13\x46\xF7\x03\xC9\xAC\x36\xC6\x1C\x03\xCB\x64\ 86 | \xC3\x97\x0D\x0C\xFC\x78\x7E\x9B\x79\x59\x9D\x27\x3A\x68\xD2\xF7\ 87 | \xF6\x9D\x4C\xC3\xDE\x9D\x10\x4A\x35\x16\x89\xF2\x7C\xF6\xF5\x95\ 88 | \x1F\x01\x03\xF3\x3F\x4F\x24\x87\x10\x24\xD9\xC2\x77\x73\xA8\xDD\ 89 | "; 90 | let mut output = [0u8; 64]; 91 | let mut kmac = Kmac::v256(key, custom); 92 | kmac.update(data); 93 | kmac.finalize(&mut output); 94 | assert_eq!(expected as &[u8], &output as &[u8]); 95 | } 96 | 97 | #[test] 98 | fn test_kmac256_two() { 99 | let key = b"\ 100 | \x40\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4A\x4B\x4C\x4D\x4E\x4F\ 101 | \x50\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5A\x5B\x5C\x5D\x5E\x5F\ 102 | "; 103 | let data = b"\ 104 | \x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F\ 105 | \x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F\ 106 | \x20\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2A\x2B\x2C\x2D\x2E\x2F\ 107 | \x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x3A\x3B\x3C\x3D\x3E\x3F\ 108 | \x40\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4A\x4B\x4C\x4D\x4E\x4F\ 109 | \x50\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5A\x5B\x5C\x5D\x5E\x5F\ 110 | \x60\x61\x62\x63\x64\x65\x66\x67\x68\x69\x6A\x6B\x6C\x6D\x6E\x6F\ 111 | \x70\x71\x72\x73\x74\x75\x76\x77\x78\x79\x7A\x7B\x7C\x7D\x7E\x7F\ 112 | \x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8A\x8B\x8C\x8D\x8E\x8F\ 113 | \x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9A\x9B\x9C\x9D\x9E\x9F\ 114 | \xA0\xA1\xA2\xA3\xA4\xA5\xA6\xA7\xA8\xA9\xAA\xAB\xAC\xAD\xAE\xAF\ 115 | \xB0\xB1\xB2\xB3\xB4\xB5\xB6\xB7\xB8\xB9\xBA\xBB\xBC\xBD\xBE\xBF\ 116 | \xC0\xC1\xC2\xC3\xC4\xC5\xC6\xC7\ 117 | "; 118 | let custom = b""; 119 | let expected = b"\ 120 | \x75\x35\x8C\xF3\x9E\x41\x49\x4E\x94\x97\x07\x92\x7C\xEE\x0A\xF2\ 121 | \x0A\x3F\xF5\x53\x90\x4C\x86\xB0\x8F\x21\xCC\x41\x4B\xCF\xD6\x91\ 122 | \x58\x9D\x27\xCF\x5E\x15\x36\x9C\xBB\xFF\x8B\x9A\x4C\x2E\xB1\x78\ 123 | \x00\x85\x5D\x02\x35\xFF\x63\x5D\xA8\x25\x33\xEC\x6B\x75\x9B\x69\ 124 | "; 125 | let mut output = [0u8; 64]; 126 | let mut kmac = Kmac::v256(key, custom); 127 | kmac.update(data); 128 | kmac.finalize(&mut output); 129 | assert_eq!(expected as &[u8], &output as &[u8]); 130 | } 131 | 132 | #[test] 133 | fn test_kmac256_three() { 134 | let key = b"\ 135 | \x40\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4A\x4B\x4C\x4D\x4E\x4F\ 136 | \x50\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5A\x5B\x5C\x5D\x5E\x5F\ 137 | "; 138 | let data = b"\ 139 | \x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F\ 140 | \x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F\ 141 | \x20\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2A\x2B\x2C\x2D\x2E\x2F\ 142 | \x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x3A\x3B\x3C\x3D\x3E\x3F\ 143 | \x40\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4A\x4B\x4C\x4D\x4E\x4F\ 144 | \x50\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5A\x5B\x5C\x5D\x5E\x5F\ 145 | \x60\x61\x62\x63\x64\x65\x66\x67\x68\x69\x6A\x6B\x6C\x6D\x6E\x6F\ 146 | \x70\x71\x72\x73\x74\x75\x76\x77\x78\x79\x7A\x7B\x7C\x7D\x7E\x7F\ 147 | \x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8A\x8B\x8C\x8D\x8E\x8F\ 148 | \x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9A\x9B\x9C\x9D\x9E\x9F\ 149 | \xA0\xA1\xA2\xA3\xA4\xA5\xA6\xA7\xA8\xA9\xAA\xAB\xAC\xAD\xAE\xAF\ 150 | \xB0\xB1\xB2\xB3\xB4\xB5\xB6\xB7\xB8\xB9\xBA\xBB\xBC\xBD\xBE\xBF\ 151 | \xC0\xC1\xC2\xC3\xC4\xC5\xC6\xC7\ 152 | "; 153 | let custom = b"My Tagged Application"; 154 | let expected = b"\ 155 | \xB5\x86\x18\xF7\x1F\x92\xE1\xD5\x6C\x1B\x8C\x55\xDD\xD7\xCD\x18\ 156 | \x8B\x97\xB4\xCA\x4D\x99\x83\x1E\xB2\x69\x9A\x83\x7D\xA2\xE4\xD9\ 157 | \x70\xFB\xAC\xFD\xE5\x00\x33\xAE\xA5\x85\xF1\xA2\x70\x85\x10\xC3\ 158 | \x2D\x07\x88\x08\x01\xBD\x18\x28\x98\xFE\x47\x68\x76\xFC\x89\x65\ 159 | "; 160 | let mut output = [0u8; 64]; 161 | let mut kmac = Kmac::v256(key, custom); 162 | kmac.update(data); 163 | kmac.finalize(&mut output); 164 | assert_eq!(expected as &[u8], &output as &[u8]); 165 | } 166 | 167 | #[test] 168 | fn test_kmac128_xof_one() { 169 | let key = b"\ 170 | \x40\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4A\x4B\x4C\x4D\x4E\x4F\ 171 | \x50\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5A\x5B\x5C\x5D\x5E\x5F\ 172 | "; 173 | let data = b"\x00\x01\x02\x03"; 174 | let custom = b""; 175 | let expected = b"\ 176 | \xCD\x83\x74\x0B\xBD\x92\xCC\xC8\xCF\x03\x2B\x14\x81\xA0\xF4\x46\ 177 | \x0E\x7C\xA9\xDD\x12\xB0\x8A\x0C\x40\x31\x17\x8B\xAC\xD6\xEC\x35\ 178 | "; 179 | let mut output = [0u8; 32]; 180 | let mut kmac = Kmac::v128(key, custom); 181 | kmac.update(data); 182 | let mut xof = kmac.into_xof(); 183 | xof.squeeze(&mut output); 184 | assert_eq!(expected, &output); 185 | } 186 | 187 | #[test] 188 | fn test_kmac128_xof_two() { 189 | let key = b"\ 190 | \x40\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4A\x4B\x4C\x4D\x4E\x4F\ 191 | \x50\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5A\x5B\x5C\x5D\x5E\x5F\ 192 | "; 193 | let data = b"\x00\x01\x02\x03"; 194 | let custom = b"My Tagged Application"; 195 | let expected = b"\ 196 | \x31\xA4\x45\x27\xB4\xED\x9F\x5C\x61\x01\xD1\x1D\xE6\xD2\x6F\x06\ 197 | \x20\xAA\x5C\x34\x1D\xEF\x41\x29\x96\x57\xFE\x9D\xF1\xA3\xB1\x6C\ 198 | "; 199 | let mut output = [0u8; 32]; 200 | let mut kmac = Kmac::v128(key, custom); 201 | kmac.update(data); 202 | let mut xof = kmac.into_xof(); 203 | xof.squeeze(&mut output); 204 | assert_eq!(expected, &output); 205 | } 206 | 207 | #[test] 208 | fn test_kmac128_xof_three() { 209 | let key = b"\ 210 | \x40\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4A\x4B\x4C\x4D\x4E\x4F\ 211 | \x50\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5A\x5B\x5C\x5D\x5E\x5F\ 212 | "; 213 | let data = b"\ 214 | \x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F\ 215 | \x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F\ 216 | \x20\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2A\x2B\x2C\x2D\x2E\x2F\ 217 | \x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x3A\x3B\x3C\x3D\x3E\x3F\ 218 | \x40\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4A\x4B\x4C\x4D\x4E\x4F\ 219 | \x50\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5A\x5B\x5C\x5D\x5E\x5F\ 220 | \x60\x61\x62\x63\x64\x65\x66\x67\x68\x69\x6A\x6B\x6C\x6D\x6E\x6F\ 221 | \x70\x71\x72\x73\x74\x75\x76\x77\x78\x79\x7A\x7B\x7C\x7D\x7E\x7F\ 222 | \x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8A\x8B\x8C\x8D\x8E\x8F\ 223 | \x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9A\x9B\x9C\x9D\x9E\x9F\ 224 | \xA0\xA1\xA2\xA3\xA4\xA5\xA6\xA7\xA8\xA9\xAA\xAB\xAC\xAD\xAE\xAF\ 225 | \xB0\xB1\xB2\xB3\xB4\xB5\xB6\xB7\xB8\xB9\xBA\xBB\xBC\xBD\xBE\xBF\ 226 | \xC0\xC1\xC2\xC3\xC4\xC5\xC6\xC7\ 227 | "; 228 | let custom = b"My Tagged Application"; 229 | let expected = b"\ 230 | \x47\x02\x6C\x7C\xD7\x93\x08\x4A\xA0\x28\x3C\x25\x3E\xF6\x58\x49\ 231 | \x0C\x0D\xB6\x14\x38\xB8\x32\x6F\xE9\xBD\xDF\x28\x1B\x83\xAE\x0F\ 232 | "; 233 | let mut output = [0u8; 32]; 234 | let mut kmac = Kmac::v128(key, custom); 235 | kmac.update(data); 236 | let mut xof = kmac.into_xof(); 237 | xof.squeeze(&mut output); 238 | assert_eq!(expected, &output); 239 | } 240 | 241 | #[test] 242 | fn test_kmac256_xof_one() { 243 | let key = b"\ 244 | \x40\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4A\x4B\x4C\x4D\x4E\x4F\ 245 | \x50\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5A\x5B\x5C\x5D\x5E\x5F\ 246 | "; 247 | let data = b"\x00\x01\x02\x03"; 248 | let custom = b"My Tagged Application"; 249 | let expected = b"\ 250 | \x17\x55\x13\x3F\x15\x34\x75\x2A\xAD\x07\x48\xF2\xC7\x06\xFB\x5C\ 251 | \x78\x45\x12\xCA\xB8\x35\xCD\x15\x67\x6B\x16\xC0\xC6\x64\x7F\xA9\ 252 | \x6F\xAA\x7A\xF6\x34\xA0\xBF\x8F\xF6\xDF\x39\x37\x4F\xA0\x0F\xAD\ 253 | \x9A\x39\xE3\x22\xA7\xC9\x20\x65\xA6\x4E\xB1\xFB\x08\x01\xEB\x2B\ 254 | "; 255 | let mut output = [0u8; 64]; 256 | let mut kmac = Kmac::v256(key, custom); 257 | kmac.update(data); 258 | let mut xof = kmac.into_xof(); 259 | xof.squeeze(&mut output); 260 | assert_eq!(expected as &[u8], &output as &[u8]); 261 | } 262 | 263 | #[test] 264 | fn test_kmac256_xof_two() { 265 | let key = b"\ 266 | \x40\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4A\x4B\x4C\x4D\x4E\x4F\ 267 | \x50\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5A\x5B\x5C\x5D\x5E\x5F\ 268 | "; 269 | let data = b"\ 270 | \x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F\ 271 | \x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F\ 272 | \x20\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2A\x2B\x2C\x2D\x2E\x2F\ 273 | \x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x3A\x3B\x3C\x3D\x3E\x3F\ 274 | \x40\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4A\x4B\x4C\x4D\x4E\x4F\ 275 | \x50\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5A\x5B\x5C\x5D\x5E\x5F\ 276 | \x60\x61\x62\x63\x64\x65\x66\x67\x68\x69\x6A\x6B\x6C\x6D\x6E\x6F\ 277 | \x70\x71\x72\x73\x74\x75\x76\x77\x78\x79\x7A\x7B\x7C\x7D\x7E\x7F\ 278 | \x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8A\x8B\x8C\x8D\x8E\x8F\ 279 | \x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9A\x9B\x9C\x9D\x9E\x9F\ 280 | \xA0\xA1\xA2\xA3\xA4\xA5\xA6\xA7\xA8\xA9\xAA\xAB\xAC\xAD\xAE\xAF\ 281 | \xB0\xB1\xB2\xB3\xB4\xB5\xB6\xB7\xB8\xB9\xBA\xBB\xBC\xBD\xBE\xBF\ 282 | \xC0\xC1\xC2\xC3\xC4\xC5\xC6\xC7\ 283 | "; 284 | let custom = b""; 285 | let expected = b"\ 286 | \xFF\x7B\x17\x1F\x1E\x8A\x2B\x24\x68\x3E\xED\x37\x83\x0E\xE7\x97\ 287 | \x53\x8B\xA8\xDC\x56\x3F\x6D\xA1\xE6\x67\x39\x1A\x75\xED\xC0\x2C\ 288 | \xA6\x33\x07\x9F\x81\xCE\x12\xA2\x5F\x45\x61\x5E\xC8\x99\x72\x03\ 289 | \x1D\x18\x33\x73\x31\xD2\x4C\xEB\x8F\x8C\xA8\xE6\xA1\x9F\xD9\x8B\ 290 | "; 291 | let mut output = [0u8; 64]; 292 | let mut kmac = Kmac::v256(key, custom); 293 | kmac.update(data); 294 | let mut xof = kmac.into_xof(); 295 | xof.squeeze(&mut output); 296 | assert_eq!(expected as &[u8], &output as &[u8]); 297 | } 298 | 299 | #[test] 300 | fn test_kmac256_xof_three() { 301 | let key = b"\ 302 | \x40\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4A\x4B\x4C\x4D\x4E\x4F\ 303 | \x50\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5A\x5B\x5C\x5D\x5E\x5F\ 304 | "; 305 | let data = b"\ 306 | \x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F\ 307 | \x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F\ 308 | \x20\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2A\x2B\x2C\x2D\x2E\x2F\ 309 | \x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x3A\x3B\x3C\x3D\x3E\x3F\ 310 | \x40\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4A\x4B\x4C\x4D\x4E\x4F\ 311 | \x50\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5A\x5B\x5C\x5D\x5E\x5F\ 312 | \x60\x61\x62\x63\x64\x65\x66\x67\x68\x69\x6A\x6B\x6C\x6D\x6E\x6F\ 313 | \x70\x71\x72\x73\x74\x75\x76\x77\x78\x79\x7A\x7B\x7C\x7D\x7E\x7F\ 314 | \x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8A\x8B\x8C\x8D\x8E\x8F\ 315 | \x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9A\x9B\x9C\x9D\x9E\x9F\ 316 | \xA0\xA1\xA2\xA3\xA4\xA5\xA6\xA7\xA8\xA9\xAA\xAB\xAC\xAD\xAE\xAF\ 317 | \xB0\xB1\xB2\xB3\xB4\xB5\xB6\xB7\xB8\xB9\xBA\xBB\xBC\xBD\xBE\xBF\ 318 | \xC0\xC1\xC2\xC3\xC4\xC5\xC6\xC7\ 319 | "; 320 | let custom = b"My Tagged Application"; 321 | let expected = b"\ 322 | \xD5\xBE\x73\x1C\x95\x4E\xD7\x73\x28\x46\xBB\x59\xDB\xE3\xA8\xE3\ 323 | \x0F\x83\xE7\x7A\x4B\xFF\x44\x59\xF2\xF1\xC2\xB4\xEC\xEB\xB8\xCE\ 324 | \x67\xBA\x01\xC6\x2E\x8A\xB8\x57\x8D\x2D\x49\x9B\xD1\xBB\x27\x67\ 325 | \x68\x78\x11\x90\x02\x0A\x30\x6A\x97\xDE\x28\x1D\xCC\x30\x30\x5D\ 326 | "; 327 | let mut output = [0u8; 64]; 328 | let mut kmac = Kmac::v256(key, custom); 329 | kmac.update(data); 330 | let mut xof = kmac.into_xof(); 331 | xof.squeeze(&mut output); 332 | assert_eq!(expected as &[u8], &output as &[u8]); 333 | } 334 | -------------------------------------------------------------------------------- /tests/parallel_hash.rs: -------------------------------------------------------------------------------- 1 | use tiny_keccak::{Hasher, ParallelHash}; 2 | 3 | #[test] 4 | fn test_parallel_hash128_one() { 5 | let custom_string = b""; 6 | let input = b"\ 7 | \x00\x01\x02\x03\x04\x05\x06\x07\x10\x11\x12\x13\ 8 | \x14\x15\x16\x17\x20\x21\x22\x23\x24\x25\x26\x27\ 9 | "; 10 | let block_size = 8; 11 | let mut phash = ParallelHash::v128(custom_string, block_size); 12 | let expected = b"\ 13 | \xBA\x8D\xC1\xD1\xD9\x79\x33\x1D\x3F\x81\x36\x03\xC6\x7F\x72\x60\ 14 | \x9A\xB5\xE4\x4B\x94\xA0\xB8\xF9\xAF\x46\x51\x44\x54\xA2\xB4\xF5\ 15 | "; 16 | let mut output = [0u8; 32]; 17 | phash.update(input); 18 | phash.finalize(&mut output); 19 | assert_eq!(expected, &output); 20 | } 21 | 22 | #[test] 23 | fn test_parallel_hash128_two() { 24 | let custom_string = b"Parallel Data"; 25 | let input = b"\ 26 | \x00\x01\x02\x03\x04\x05\x06\x07\x10\x11\x12\x13\ 27 | \x14\x15\x16\x17\x20\x21\x22\x23\x24\x25\x26\x27\ 28 | "; 29 | let block_size = 8; 30 | let mut phash = ParallelHash::v128(custom_string, block_size); 31 | let expected = b"\ 32 | \xFC\x48\x4D\xCB\x3F\x84\xDC\xEE\xDC\x35\x34\x38\x15\x1B\xEE\x58\ 33 | \x15\x7D\x6E\xFE\xD0\x44\x5A\x81\xF1\x65\xE4\x95\x79\x5B\x72\x06\ 34 | "; 35 | let mut output = [0u8; 32]; 36 | phash.update(input); 37 | phash.finalize(&mut output); 38 | assert_eq!(expected, &output); 39 | } 40 | 41 | #[test] 42 | fn test_parallel_hash128_three() { 43 | let custom_string = b""; 44 | let input = b"\ 45 | \x00\x01\x02\x03\x04\x05\x06\x07\x10\x11\x12\x13\ 46 | \x14\x15\x16\x17\x20\x21\x22\x23\x24\x25\x26\x27\ 47 | "; 48 | let block_size = 8; 49 | let mut phash = ParallelHash::v128(custom_string, block_size); 50 | let expected = b"\ 51 | \xBA\x8D\xC1\xD1\xD9\x79\x33\x1D\x3F\x81\x36\x03\xC6\x7F\x72\x60\ 52 | \x9A\xB5\xE4\x4B\x94\xA0\xB8\xF9\xAF\x46\x51\x44\x54\xA2\xB4\xF5\ 53 | "; 54 | let mut output = [0u8; 32]; 55 | phash.update(&input[..13]); 56 | phash.update(&input[13..]); 57 | phash.finalize(&mut output); 58 | assert_eq!(expected, &output); 59 | } 60 | 61 | #[test] 62 | fn test_parallel_hash256_one() { 63 | let custom_string = b""; 64 | let input = b"\ 65 | \x00\x01\x02\x03\x04\x05\x06\x07\x10\x11\x12\x13\ 66 | \x14\x15\x16\x17\x20\x21\x22\x23\x24\x25\x26\x27\ 67 | "; 68 | let block_size = 8; 69 | let mut phash = ParallelHash::v256(custom_string, block_size); 70 | let expected = b"\ 71 | \xBC\x1E\xF1\x24\xDA\x34\x49\x5E\x94\x8E\xAD\x20\x7D\xD9\x84\x22\ 72 | \x35\xDA\x43\x2D\x2B\xBC\x54\xB4\xC1\x10\xE6\x4C\x45\x11\x05\x53\ 73 | \x1B\x7F\x2A\x3E\x0C\xE0\x55\xC0\x28\x05\xE7\xC2\xDE\x1F\xB7\x46\ 74 | \xAF\x97\xA1\xDD\x01\xF4\x3B\x82\x4E\x31\xB8\x76\x12\x41\x04\x29\ 75 | "; 76 | let mut output = [0u8; 64]; 77 | phash.update(input); 78 | phash.finalize(&mut output); 79 | assert_eq!(expected as &[u8], &output as &[u8]); 80 | } 81 | 82 | #[test] 83 | fn test_parallel_hash256_two() { 84 | let custom_string = b"Parallel Data"; 85 | let input = b"\ 86 | \x00\x01\x02\x03\x04\x05\x06\x07\x10\x11\x12\x13\ 87 | \x14\x15\x16\x17\x20\x21\x22\x23\x24\x25\x26\x27\ 88 | "; 89 | let block_size = 8; 90 | let mut phash = ParallelHash::v256(custom_string, block_size); 91 | let expected = b"\ 92 | \xCD\xF1\x52\x89\xB5\x4F\x62\x12\xB4\xBC\x27\x05\x28\xB4\x95\x26\ 93 | \x00\x6D\xD9\xB5\x4E\x2B\x6A\xDD\x1E\xF6\x90\x0D\xDA\x39\x63\xBB\ 94 | \x33\xA7\x24\x91\xF2\x36\x96\x9C\xA8\xAF\xAE\xA2\x9C\x68\x2D\x47\ 95 | \xA3\x93\xC0\x65\xB3\x8E\x29\xFA\xE6\x51\xA2\x09\x1C\x83\x31\x10\ 96 | "; 97 | let mut output = [0u8; 64]; 98 | phash.update(input); 99 | phash.finalize(&mut output); 100 | assert_eq!(expected as &[u8], &output as &[u8]); 101 | } 102 | 103 | #[test] 104 | fn test_parallel_hash256_three() { 105 | let custom_string = b""; 106 | let input = b"\ 107 | \x00\x01\x02\x03\x04\x05\x06\x07\x10\x11\x12\x13\ 108 | \x14\x15\x16\x17\x20\x21\x22\x23\x24\x25\x26\x27\ 109 | "; 110 | let block_size = 8; 111 | let mut phash = ParallelHash::v256(custom_string, block_size); 112 | let expected = b"\ 113 | \xBC\x1E\xF1\x24\xDA\x34\x49\x5E\x94\x8E\xAD\x20\x7D\xD9\x84\x22\ 114 | \x35\xDA\x43\x2D\x2B\xBC\x54\xB4\xC1\x10\xE6\x4C\x45\x11\x05\x53\ 115 | \x1B\x7F\x2A\x3E\x0C\xE0\x55\xC0\x28\x05\xE7\xC2\xDE\x1F\xB7\x46\ 116 | \xAF\x97\xA1\xDD\x01\xF4\x3B\x82\x4E\x31\xB8\x76\x12\x41\x04\x29\ 117 | "; 118 | let mut output = [0u8; 64]; 119 | phash.update(&input[..13]); 120 | phash.update(&input[13..]); 121 | phash.finalize(&mut output); 122 | assert_eq!(expected as &[u8], &output as &[u8]); 123 | } 124 | -------------------------------------------------------------------------------- /tests/sha3.rs: -------------------------------------------------------------------------------- 1 | use tiny_keccak::{Hasher, Sha3}; 2 | 3 | #[test] 4 | fn empty_sha3_256() { 5 | let sha3 = Sha3::v256(); 6 | let mut output = [0; 32]; 7 | let expected = b"\ 8 | \xa7\xff\xc6\xf8\xbf\x1e\xd7\x66\x51\xc1\x47\x56\xa0\x61\xd6\x62\ 9 | \xf5\x80\xff\x4d\xe4\x3b\x49\xfa\x82\xd8\x0a\x4b\x80\xf8\x43\x4a\ 10 | "; 11 | sha3.finalize(&mut output); 12 | assert_eq!(expected, &output); 13 | } 14 | 15 | #[test] 16 | fn hello_sha3_256() { 17 | let mut sha3 = Sha3::v256(); 18 | let input = b"hello"; 19 | let mut output = [0u8; 32]; 20 | let expected = b"\ 21 | \x33\x38\xbe\x69\x4f\x50\xc5\xf3\x38\x81\x49\x86\xcd\xf0\x68\x64\ 22 | \x53\xa8\x88\xb8\x4f\x42\x4d\x79\x2a\xf4\xb9\x20\x23\x98\xf3\x92\ 23 | "; 24 | sha3.update(input); 25 | sha3.finalize(&mut output); 26 | assert_eq!(expected, &output); 27 | } 28 | 29 | #[test] 30 | fn hello_sha3_256_parts() { 31 | let mut sha3 = Sha3::v256(); 32 | let input_a = b"hell"; 33 | let input_b = b"o"; 34 | let mut output = [0u8; 32]; 35 | let expected = b"\ 36 | \x33\x38\xbe\x69\x4f\x50\xc5\xf3\x38\x81\x49\x86\xcd\xf0\x68\x64\ 37 | \x53\xa8\x88\xb8\x4f\x42\x4d\x79\x2a\xf4\xb9\x20\x23\x98\xf3\x92\ 38 | "; 39 | sha3.update(input_a); 40 | sha3.update(input_b); 41 | sha3.finalize(&mut output); 42 | assert_eq!(expected, &output); 43 | } 44 | 45 | #[test] 46 | fn hello_sha3_256_parts5() { 47 | let mut sha3 = Sha3::v256(); 48 | let mut output = [0u8; 32]; 49 | let expected = b"\ 50 | \x33\x38\xbe\x69\x4f\x50\xc5\xf3\x38\x81\x49\x86\xcd\xf0\x68\x64\ 51 | \x53\xa8\x88\xb8\x4f\x42\x4d\x79\x2a\xf4\xb9\x20\x23\x98\xf3\x92\ 52 | "; 53 | sha3.update(b"h"); 54 | sha3.update(b"e"); 55 | sha3.update(b"l"); 56 | sha3.update(b"l"); 57 | sha3.update(b"o"); 58 | sha3.finalize(&mut output); 59 | assert_eq!(expected, &output); 60 | } 61 | 62 | #[test] 63 | fn long_string_sha3_512() { 64 | let mut sha3 = Sha3::v512(); 65 | let input = b"Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."; 66 | let mut output = [0u8; 64]; 67 | let expected = b"\ 68 | \xf3\x2a\x94\x23\x55\x13\x51\xdf\x0a\x07\xc0\xb8\xc2\x0e\xb9\x72\ 69 | \x36\x7c\x39\x8d\x61\x06\x60\x38\xe1\x69\x86\x44\x8e\xbf\xbc\x3d\ 70 | \x15\xed\xe0\xed\x36\x93\xe3\x90\x5e\x9a\x8c\x60\x1d\x9d\x00\x2a\ 71 | \x06\x85\x3b\x97\x97\xef\x9a\xb1\x0c\xbd\xe1\x00\x9c\x7d\x0f\x09\ 72 | "; 73 | sha3.update(input); 74 | sha3.finalize(&mut output); 75 | assert_eq!(expected as &[u8], &output as &[u8]); 76 | } 77 | 78 | #[test] 79 | fn long_string_sha3_512_parts() { 80 | let mut sha3 = Sha3::v512(); 81 | let input_a = b"Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip "; 82 | let input_b = b"ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."; 83 | let mut output = [0u8; 64]; 84 | let expected = b"\ 85 | \xf3\x2a\x94\x23\x55\x13\x51\xdf\x0a\x07\xc0\xb8\xc2\x0e\xb9\x72\ 86 | \x36\x7c\x39\x8d\x61\x06\x60\x38\xe1\x69\x86\x44\x8e\xbf\xbc\x3d\ 87 | \x15\xed\xe0\xed\x36\x93\xe3\x90\x5e\x9a\x8c\x60\x1d\x9d\x00\x2a\ 88 | \x06\x85\x3b\x97\x97\xef\x9a\xb1\x0c\xbd\xe1\x00\x9c\x7d\x0f\x09\ 89 | "; 90 | sha3.update(input_a); 91 | sha3.update(input_b); 92 | sha3.finalize(&mut output); 93 | assert_eq!(expected as &[u8], &output as &[u8]); 94 | } 95 | -------------------------------------------------------------------------------- /tests/shake.rs: -------------------------------------------------------------------------------- 1 | use tiny_keccak::{Hasher, Shake, Xof}; 2 | 3 | #[test] 4 | fn shake_xof_one() { 5 | let mut shake = Shake::v128(); 6 | let mut output = [0; 32]; 7 | let expected = b"\ 8 | \x43\xE4\x1B\x45\xA6\x53\xF2\xA5\xC4\x49\x2C\x1A\xDD\x54\x45\x12\ 9 | \xDD\xA2\x52\x98\x33\x46\x2B\x71\xA4\x1A\x45\xBE\x97\x29\x0B\x6F\ 10 | "; 11 | 12 | for _ in 0..16 { 13 | shake.squeeze(&mut output); 14 | } 15 | 16 | assert_eq!(expected, &output); 17 | } 18 | 19 | #[test] 20 | fn shake_xof_two() { 21 | let mut shake = Shake::v128(); 22 | let mut output = [0; 32]; 23 | let expected = b"\ 24 | \x44\xC9\xFB\x35\x9F\xD5\x6A\xC0\xA9\xA7\x5A\x74\x3C\xFF\x68\x62\ 25 | \xF1\x7D\x72\x59\xAB\x07\x52\x16\xC0\x69\x95\x11\x64\x3B\x64\x39\ 26 | "; 27 | 28 | for _ in 0..10 { 29 | shake.update(&[0xa3; 20]); 30 | } 31 | 32 | for _ in 0..16 { 33 | shake.squeeze(&mut output); 34 | } 35 | 36 | assert_eq!(expected, &output); 37 | } 38 | -------------------------------------------------------------------------------- /tests/tuple_hash.rs: -------------------------------------------------------------------------------- 1 | use tiny_keccak::{Hasher, TupleHash}; 2 | 3 | #[test] 4 | fn test_tuple_hash128_one() { 5 | let te3 = b"\x00\x01\x02"; 6 | let te6 = b"\x10\x11\x12\x13\x14\x15"; 7 | let s0 = b""; 8 | let expected = b"\ 9 | \xC5\xD8\x78\x6C\x1A\xFB\x9B\x82\x11\x1A\xB3\x4B\x65\xB2\xC0\x04\ 10 | \x8F\xA6\x4E\x6D\x48\xE2\x63\x26\x4C\xE1\x70\x7D\x3F\xFC\x8E\xD1\ 11 | "; 12 | let mut output = [0u8; 32]; 13 | let mut hasher = TupleHash::v128(s0); 14 | hasher.update(te3); 15 | hasher.update(te6); 16 | hasher.finalize(&mut output); 17 | assert_eq!(expected, &output); 18 | } 19 | 20 | #[test] 21 | fn test_tuple_hash128_two() { 22 | let te3 = b"\x00\x01\x02"; 23 | let te6 = b"\x10\x11\x12\x13\x14\x15"; 24 | let s1 = b"My Tuple App"; 25 | let expected = b"\ 26 | \x75\xCD\xB2\x0F\xF4\xDB\x11\x54\xE8\x41\xD7\x58\xE2\x41\x60\xC5\ 27 | \x4B\xAE\x86\xEB\x8C\x13\xE7\xF5\xF4\x0E\xB3\x55\x88\xE9\x6D\xFB\ 28 | "; 29 | let mut output = [0u8; 32]; 30 | let mut hasher = TupleHash::v128(s1); 31 | hasher.update(te3); 32 | hasher.update(te6); 33 | hasher.finalize(&mut output); 34 | assert_eq!(expected, &output); 35 | } 36 | 37 | #[test] 38 | fn test_tuple_hash128_three() { 39 | let te3 = b"\x00\x01\x02"; 40 | let te6 = b"\x10\x11\x12\x13\x14\x15"; 41 | let te9 = b"\x20\x21\x22\x23\x24\x25\x26\x27\x28"; 42 | let s1 = b"My Tuple App"; 43 | let expected = b"\ 44 | \xE6\x0F\x20\x2C\x89\xA2\x63\x1E\xDA\x8D\x4C\x58\x8C\xA5\xFD\x07\ 45 | \xF3\x9E\x51\x51\x99\x8D\xEC\xCF\x97\x3A\xDB\x38\x04\xBB\x6E\x84\ 46 | "; 47 | let mut output = [0u8; 32]; 48 | let mut hasher = TupleHash::v128(s1); 49 | hasher.update(te3); 50 | hasher.update(te6); 51 | hasher.update(te9); 52 | hasher.finalize(&mut output); 53 | assert_eq!(expected, &output); 54 | } 55 | 56 | #[test] 57 | fn test_tuple_hash256() { 58 | let te3 = b"\x00\x01\x02"; 59 | let te6 = b"\x10\x11\x12\x13\x14\x15"; 60 | let s0 = b""; 61 | let expected = b"\ 62 | \xCF\xB7\x05\x8C\xAC\xA5\xE6\x68\xF8\x1A\x12\xA2\x0A\x21\x95\xCE\ 63 | \x97\xA9\x25\xF1\xDB\xA3\xE7\x44\x9A\x56\xF8\x22\x01\xEC\x60\x73\ 64 | \x11\xAC\x26\x96\xB1\xAB\x5E\xA2\x35\x2D\xF1\x42\x3B\xDE\x7B\xD4\ 65 | \xBB\x78\xC9\xAE\xD1\xA8\x53\xC7\x86\x72\xF9\xEB\x23\xBB\xE1\x94\ 66 | "; 67 | let mut output = [0u8; 64]; 68 | let mut hasher = TupleHash::v256(s0); 69 | hasher.update(te3); 70 | hasher.update(te6); 71 | hasher.finalize(&mut output); 72 | assert_eq!(expected as &[u8], &output as &[u8]); 73 | } 74 | 75 | #[test] 76 | fn test_tuple_hash256_two() { 77 | let te3 = b"\x00\x01\x02"; 78 | let te6 = b"\x10\x11\x12\x13\x14\x15"; 79 | let s1 = b"My Tuple App"; 80 | let expected = b"\ 81 | \x14\x7C\x21\x91\xD5\xED\x7E\xFD\x98\xDB\xD9\x6D\x7A\xB5\xA1\x16\ 82 | \x92\x57\x6F\x5F\xE2\xA5\x06\x5F\x3E\x33\xDE\x6B\xBA\x9F\x3A\xA1\ 83 | \xC4\xE9\xA0\x68\xA2\x89\xC6\x1C\x95\xAA\xB3\x0A\xEE\x1E\x41\x0B\ 84 | \x0B\x60\x7D\xE3\x62\x0E\x24\xA4\xE3\xBF\x98\x52\xA1\xD4\x36\x7E\ 85 | "; 86 | let mut output = [0u8; 64]; 87 | let mut hasher = TupleHash::v256(s1); 88 | hasher.update(te3); 89 | hasher.update(te6); 90 | hasher.finalize(&mut output); 91 | assert_eq!(expected as &[u8], &output as &[u8]); 92 | } 93 | 94 | #[test] 95 | fn test_tuple_hash256_three() { 96 | let te3 = b"\x00\x01\x02"; 97 | let te6 = b"\x10\x11\x12\x13\x14\x15"; 98 | let te9 = b"\x20\x21\x22\x23\x24\x25\x26\x27\x28"; 99 | let s1 = b"My Tuple App"; 100 | let expected = b"\ 101 | \x45\x00\x0B\xE6\x3F\x9B\x6B\xFD\x89\xF5\x47\x17\x67\x0F\x69\xA9\ 102 | \xBC\x76\x35\x91\xA4\xF0\x5C\x50\xD6\x88\x91\xA7\x44\xBC\xC6\xE7\ 103 | \xD6\xD5\xB5\xE8\x2C\x01\x8D\xA9\x99\xED\x35\xB0\xBB\x49\xC9\x67\ 104 | \x8E\x52\x6A\xBD\x8E\x85\xC1\x3E\xD2\x54\x02\x1D\xB9\xE7\x90\xCE\ 105 | "; 106 | let mut output = [0u8; 64]; 107 | let mut hasher = TupleHash::v256(s1); 108 | hasher.update(te3); 109 | hasher.update(te6); 110 | hasher.update(te9); 111 | hasher.finalize(&mut output); 112 | assert_eq!(expected as &[u8], &output as &[u8]); 113 | } 114 | --------------------------------------------------------------------------------