From 069e517f788b78f7b4a48d29f471aadf6f4df1d6 Mon Sep 17 00:00:00 2001
From: Robin Salen <30937548+Nashtare@users.noreply.github.com>
Date: Thu, 29 Feb 2024 14:33:03 +0900
Subject: [PATCH] Remove griffin hash due to security concerns (#254)
---
crypto/README.md | 34 +-
crypto/benches/hash.rs | 26 +-
.../hash/griffin/griffin64_256_jive/digest.rs | 111 ---
.../hash/griffin/griffin64_256_jive/mod.rs | 679 ------------------
.../hash/griffin/griffin64_256_jive/tests.rs | 214 ------
crypto/src/hash/griffin/mod.rs | 9 -
crypto/src/hash/mod.rs | 3 -
crypto/src/hash/rescue/rp64_256_jive/mod.rs | 4 +-
crypto/src/lib.rs | 1 -
examples/src/fibonacci/fib_small/mod.rs | 4 -
examples/src/lib.rs | 10 +-
11 files changed, 13 insertions(+), 1082 deletions(-)
delete mode 100644 crypto/src/hash/griffin/griffin64_256_jive/digest.rs
delete mode 100644 crypto/src/hash/griffin/griffin64_256_jive/mod.rs
delete mode 100644 crypto/src/hash/griffin/griffin64_256_jive/tests.rs
delete mode 100644 crypto/src/hash/griffin/mod.rs
diff --git a/crypto/README.md b/crypto/README.md
index bdcf6d82f..70e2f4a5b 100644
--- a/crypto/README.md
+++ b/crypto/README.md
@@ -8,7 +8,6 @@ This crate contains modules with cryptographic operations needed in STARK proof
* BLAKE3 with either 256-bit or 192-bit output. The smaller output version can be used to reduce STARK proof size, however, it also limits proof security level to at most 96 bits.
* Rescue Prime over a 64-bit field with 256-bit output and over a 62-bit field with 248-bit output. Rescue is an arithmetization-friendly hash function and can be used in the STARK protocol when recursive proof composition is desired. However, using this function is not yet supported by the Winterfell STARK prover and verifier.
* Rescue Prime over the same 64-bit field as above, with 256-bit output, but using the novel [Jive compression mode](https://eprint.iacr.org/2022/840.pdf) to obtain a smaller state and faster 2-to-1 compression.
-* Griffin over the same 64-bit field as above, with 256-bit output, also using the novel [Jive compression mode](https://eprint.iacr.org/2022/840.pdf) to obtain a smaller state and faster 2-to-1 compression.
### Rescue hash function implementation
Rescue hash function is implemented according to the Rescue Prime [specifications](https://eprint.iacr.org/2020/1143.pdf) with the following exception:
@@ -45,36 +44,19 @@ The parameters used to instantiate the functions are:
- S-Box degree: 3.
- Target security level: 124-bits.
-### Griffin hash function implementation
-Griffin hash function is implemented according to the Griffin [specifications](https://eprint.iacr.org/2022/403.pdf) with the following differences:
-* We set the number of rounds to 7, which implies a 15% security margin instead of the 20% margin used in the specifications (a 20% margin rounds up to 8 rounds), similarly to the motivation on Rescue above.
-* When hashing a sequence of elements, we follow the [Hirose padding](https://www.researchgate.net/publication/325706626_Sequential_Hashing_with_Minimum_Padding) specification, similarly to RPJive64_256 instantiation. However, this means that our instantiation of Griffin cannot be used in a stream mode as the number of elements to be hashed must be known upfront.
-* For instantiation `GriffinJive64_256`, we also make the following modifications:
- - Instead of using the matrix suggested by the Griffin specification paper, we use a methodology developed by Polygon Zero to find an MDS matrix with coefficients which are small powers of two in frequency domain. This allows us to dramatically reduce MDS matrix multiplication time. We claim without proof that using a different MDS matrix does not affect security of the hash function.
- - We use Jive as compression mode for 2-to-1 hashing. Similarly to `RpJive64_256` above, the output of the hash function is not the same when we hash 8 field elements as a sequence of elements using `hash_elements()` function and when we compress 8 field elements into 4 (e.g., for building a Merkle tree) using the 2-to-1 Jive compression mode.
-
-The parameters used to instantiate the function are:
-* For `GriffinJive64_256`:
- - Field: 64-bit prime field with modulus 264 - 232 + 1.
- - State width: 8 field elements.
- - Capacity size: 4 field elements.
- - Digest size: 4 field elements (can be serialized into 32 bytes).
- - Number of founds: 7.
- - S-Box degree: 7.
- - Target security level: 128-bits.
### Hash function performance
One of the core operations performed during STARK proof generation is construction of Merkle trees. We care greatly about building these trees as quickly as possible, and thus, for the purposes of STARK protocol, 2-to-1 hash operation (e.g., computing a hash of two 32-byte values) is especially important. The table below contains rough benchmarks for computing a 2-to-1 hash for all currently implemented hash functions.
-| CPU | BLAKE3_256 | SHA3_256 | RP64_256 | RPJ64_256 | RP62_248 | GriffinJ64_256 |
-| --------------------------- | :--------: | :------: | :------: | :-------: | :------: | :------------: |
-| Apple M1 Pro | 76 ns | 227 ns | 5.1 us | 3.8 us | 7.1 us | 2.2 us |
-| AMD Ryzen 9 5950X @ 3.4 GHz | 62 ns | 310 ns | 5.2 us | 3.9 us | 6.9 us | 1.5 us |
-| Core i9-9980KH @ 2.4 GHz | 66 ns | 400 ns | - | - | 6.6 us | - |
-| Core i5-7300U @ 2.6 GHz | 81 ns | 540 ns | - | - | 9.5 us | - |
-| Core i5-4300U @ 1.9 GHz | 106 ns | 675 ns | - | - | 13.9 us | - |
+| CPU | BLAKE3_256 | SHA3_256 | RP64_256 | RPJ64_256 | RP62_248 |
+| --------------------------- | :--------: | :------: | :------: | :-------: | :------: |
+| Apple M1 Pro | 76 ns | 227 ns | 5.1 us | 3.8 us | 7.1 us |
+| AMD Ryzen 9 5950X @ 3.4 GHz | 62 ns | 310 ns | 5.2 us | 3.9 us | 6.9 us |
+| Core i9-9980KH @ 2.4 GHz | 66 ns | 400 ns | - | - | 6.6 us |
+| Core i5-7300U @ 2.6 GHz | 81 ns | 540 ns | - | - | 9.5 us |
+| Core i5-4300U @ 1.9 GHz | 106 ns | 675 ns | - | - | 13.9 us |
-As can be seen from the table, BLAKE3 is by far the fastest hash function, while our implementations of algebraic hashes are between 30x (Griffin) and 70x (Rescue-Prime) slower than BLAKE3 and between 10x (Griffin) and 20x (Rescue-Prime) slower than SHA3.
+As can be seen from the table, BLAKE3 is by far the fastest hash function, while our implementations of algebraic hashes are 70x slower than BLAKE3 and 20x slower than SHA3.
## Merkle
[Merkle](src/merkle) module contains an implementation of a Merkle tree which supports batch proof generation and verification. Batch proofs are based on the Octopus algorithm described [here](https://eprint.iacr.org/2017/933).
diff --git a/crypto/benches/hash.rs b/crypto/benches/hash.rs
index 291ce5aa8..62569706b 100644
--- a/crypto/benches/hash.rs
+++ b/crypto/benches/hash.rs
@@ -7,7 +7,7 @@ use criterion::{black_box, criterion_group, criterion_main, BatchSize, Criterion
use math::fields::f128;
use rand_utils::rand_value;
use winter_crypto::{
- hashers::{Blake3_256, GriffinJive64_256, Rp62_248, Rp64_256, RpJive64_256, Sha3_256},
+ hashers::{Blake3_256, Rp62_248, Rp64_256, RpJive64_256, Sha3_256},
Hasher,
};
@@ -20,7 +20,6 @@ type Sha3Digest = ::Digest;
type Rp62_248Digest = ::Digest;
type Rp64_256Digest = ::Digest;
type RpJive64_256Digest = ::Digest;
-type GriffinJive64_256Digest = ::Digest;
fn blake3(c: &mut Criterion) {
let v: [Blake3Digest; 2] = [Blake3::hash(&[1u8]), Blake3::hash(&[2u8])];
@@ -118,26 +117,5 @@ fn rescue_jive256(c: &mut Criterion) {
});
}
-fn griffin_jive256(c: &mut Criterion) {
- let v: [GriffinJive64_256Digest; 2] =
- [GriffinJive64_256::hash(&[1u8]), GriffinJive64_256::hash(&[2u8])];
- c.bench_function("hash_griffin_jive64_256 (cached)", |bench| {
- bench.iter(|| GriffinJive64_256::merge(black_box(&v)))
- });
-
- c.bench_function("hash_griffin_jive64_256 (random)", |b| {
- b.iter_batched(
- || {
- [
- GriffinJive64_256::hash(&rand_value::().to_le_bytes()),
- GriffinJive64_256::hash(&rand_value::().to_le_bytes()),
- ]
- },
- |state| GriffinJive64_256::merge(&state),
- BatchSize::SmallInput,
- )
- });
-}
-
-criterion_group!(hash_group, blake3, sha3, rescue248, rescue256, rescue_jive256, griffin_jive256,);
+criterion_group!(hash_group, blake3, sha3, rescue248, rescue256, rescue_jive256);
criterion_main!(hash_group);
diff --git a/crypto/src/hash/griffin/griffin64_256_jive/digest.rs b/crypto/src/hash/griffin/griffin64_256_jive/digest.rs
deleted file mode 100644
index 3a599a0ef..000000000
--- a/crypto/src/hash/griffin/griffin64_256_jive/digest.rs
+++ /dev/null
@@ -1,111 +0,0 @@
-// Copyright (c) Facebook, Inc. and its affiliates.
-//
-// This source code is licensed under the MIT license found in the
-// LICENSE file in the root directory of this source tree.
-
-use super::{Digest, DIGEST_SIZE};
-use core::slice;
-use math::fields::f64::BaseElement;
-use utils::{ByteReader, ByteWriter, Deserializable, DeserializationError, Serializable};
-
-// DIGEST TRAIT IMPLEMENTATIONS
-// ================================================================================================
-
-#[derive(Debug, Copy, Clone, Eq, PartialEq)]
-pub struct ElementDigest([BaseElement; DIGEST_SIZE]);
-
-impl ElementDigest {
- pub fn new(value: [BaseElement; DIGEST_SIZE]) -> Self {
- Self(value)
- }
-
- pub fn as_elements(&self) -> &[BaseElement] {
- &self.0
- }
-
- pub fn digests_as_elements(digests: &[Self]) -> &[BaseElement] {
- let p = digests.as_ptr();
- let len = digests.len() * DIGEST_SIZE;
- unsafe { slice::from_raw_parts(p as *const BaseElement, len) }
- }
-}
-
-impl Digest for ElementDigest {
- fn as_bytes(&self) -> [u8; 32] {
- let mut result = [0; 32];
-
- result[..8].copy_from_slice(&self.0[0].as_int().to_le_bytes());
- result[8..16].copy_from_slice(&self.0[1].as_int().to_le_bytes());
- result[16..24].copy_from_slice(&self.0[2].as_int().to_le_bytes());
- result[24..].copy_from_slice(&self.0[3].as_int().to_le_bytes());
-
- result
- }
-}
-
-impl Default for ElementDigest {
- fn default() -> Self {
- ElementDigest([BaseElement::default(); DIGEST_SIZE])
- }
-}
-
-impl Serializable for ElementDigest {
- fn write_into(&self, target: &mut W) {
- target.write_bytes(&self.as_bytes());
- }
-}
-
-impl Deserializable for ElementDigest {
- fn read_from(source: &mut R) -> Result {
- // TODO: check if the field elements are valid?
- let e1 = BaseElement::new(source.read_u64()?);
- let e2 = BaseElement::new(source.read_u64()?);
- let e3 = BaseElement::new(source.read_u64()?);
- let e4 = BaseElement::new(source.read_u64()?);
-
- Ok(Self([e1, e2, e3, e4]))
- }
-}
-
-impl From<[BaseElement; DIGEST_SIZE]> for ElementDigest {
- fn from(value: [BaseElement; DIGEST_SIZE]) -> Self {
- Self(value)
- }
-}
-
-impl From for [BaseElement; DIGEST_SIZE] {
- fn from(value: ElementDigest) -> Self {
- value.0
- }
-}
-
-impl From for [u8; 32] {
- fn from(value: ElementDigest) -> Self {
- value.as_bytes()
- }
-}
-
-// TESTS
-// ================================================================================================
-
-#[cfg(test)]
-mod tests {
-
- use super::ElementDigest;
- use rand_utils::rand_array;
- use utils::{Deserializable, Serializable, SliceReader};
-
- #[test]
- fn digest_serialization() {
- let d1 = ElementDigest(rand_array());
-
- let mut bytes = vec![];
- d1.write_into(&mut bytes);
- assert_eq!(32, bytes.len());
-
- let mut reader = SliceReader::new(&bytes);
- let d2 = ElementDigest::read_from(&mut reader).unwrap();
-
- assert_eq!(d1, d2);
- }
-}
diff --git a/crypto/src/hash/griffin/griffin64_256_jive/mod.rs b/crypto/src/hash/griffin/griffin64_256_jive/mod.rs
deleted file mode 100644
index f8237c8f0..000000000
--- a/crypto/src/hash/griffin/griffin64_256_jive/mod.rs
+++ /dev/null
@@ -1,679 +0,0 @@
-// Copyright (c) Facebook, Inc. and its affiliates.
-//
-// This source code is licensed under the MIT license found in the
-// LICENSE file in the root directory of this source tree.
-
-use super::super::mds::mds_f64_8x8::mds_multiply;
-use super::{Digest, ElementHasher, Hasher};
-use core::ops::Range;
-use math::{fields::f64::BaseElement, FieldElement, StarkField};
-
-mod digest;
-pub use digest::ElementDigest;
-
-#[cfg(test)]
-mod tests;
-
-// CONSTANTS
-// ================================================================================================
-
-/// Sponge state is set to 8 field elements or 64 bytes; 4 elements are reserved for rate and
-/// the remaining 4 elements are reserved for capacity.
-const STATE_WIDTH: usize = 8;
-
-/// The rate portion of the state is located in elements 0 through 4.
-const RATE_RANGE: Range = 0..4;
-const RATE_WIDTH: usize = RATE_RANGE.end - RATE_RANGE.start;
-
-// The compression makes use of the Jive mode, hence ignoring the notion of sponge capacity.
-const INPUT1_RANGE: Range = 0..4;
-const INPUT2_RANGE: Range = 4..8;
-
-/// The capacity portion of the state is located in elements 4, 5, 6 and 7.
-const CAPACITY_RANGE: Range = 4..8;
-
-/// The output of the hash function is a digest which consists of 4 field elements or 32 bytes.
-///
-/// The digest is returned from state elements 0, 1, 2, 3 (the four elements of the rate).
-const DIGEST_RANGE: Range = 0..4;
-const DIGEST_SIZE: usize = DIGEST_RANGE.end - DIGEST_RANGE.start;
-
-/// The number of rounds is set to 7 to target 128-bit security level with 15% security margin
-const NUM_ROUNDS: usize = 7;
-
-// HASHER IMPLEMENTATION
-// ================================================================================================
-
-/// Implementation of [Hasher] trait for Griffin hash function with 256-bit output.
-///
-/// The hash function is implemented according to the Griffin
-/// [specifications](https://eprint.iacr.org/2020/1143.pdf) with the following caveats:
-/// * We set the number of rounds to 7, which implies a 15% security margin instead of the 20%
-/// margin used in the specifications (a 20% margin rounds up to 8 rounds). The primary
-/// motivation for this is that having the number of rounds be one less than a power of two
-/// simplifies AIR design for computations involving the hash function.
-/// * When hashing a sequence of elements, implement the Hirose padding rule. However, it also
-/// means that our instantiation of Griffin cannot be used in a stream mode as the number
-/// of elements to be hashed must be known upfront.
-/// * Instead of using the suggested matrix as described in Griffin paper, we use a methodology
-/// developed by Polygon Zero to find an MDS matrix with coefficients which are small powers
-/// of two in frequency domain. This allows us to dramatically reduce matrix multiplication
-/// time. We claim without proof that using a different (MDS) matrix does not affect security of
-/// as the branching number is actually increased (9 instead of 6).
-///
-/// The parameters used to instantiate the function are:
-/// * Field: 64-bit prime field with modulus 2^64 - 2^32 + 1.
-/// * State width: 8 field elements.
-/// * Capacity size: 4 field elements.
-/// * Number of founds: 7.
-/// * S-Box degree: 7.
-///
-/// The above parameters target 128-bit security level. The digest consists of four field elements
-/// and it can be serialized into 32 bytes (256 bits).
-///
-/// ## Hash output consistency
-/// Functions [hash_elements()](GriffinJive64_256::hash_elements), [merge()](GriffinJive64_256::merge), and
-/// [merge_with_int()](GriffinJive64_256::merge_with_int) are not consistent. This is because the former
-/// is instantiated with a sponge construction, while the latter use the Jive compression mode and
-/// hence do not rely on the sponge construction.
-///
-/// In addition, [hash()](GriffinJive64_256::hash) function is not consistent with the functions mentioned
-/// above. For example, if we take two field elements, serialize them to bytes and hash them using
-/// [hash()](GriffinJive64_256::hash), the result will differ from the result obtained by hashing these
-/// elements directly using [hash_elements()](GriffinJive64_256::hash_elements) function. The reason for
-/// this difference is that [hash()](GriffinJive64_256::hash) function needs to be able to handle
-/// arbitrary binary strings, which may or may not encode valid field elements - and thus,
-/// deserialization procedure used by this function is different from the procedure used to
-/// deserialize valid field elements.
-///
-/// Thus, if the underlying data consists of valid field elements, it might make more sense
-/// to deserialize them into field elements and then hash them using
-/// [hash_elements()](GriffinJive64_256::hash_elements) function rather then hashing the serialized bytes
-/// using [hash()](GriffinJive64_256::hash) function.
-pub struct GriffinJive64_256();
-
-impl Hasher for GriffinJive64_256 {
- type Digest = ElementDigest;
-
- const COLLISION_RESISTANCE: u32 = 128;
-
- fn hash(bytes: &[u8]) -> Self::Digest {
- // compute the number of elements required to represent the string; we will be processing
- // the string in 7-byte chunks, thus the number of elements will be equal to the number
- // of such chunks (including a potential partial chunk at the end).
- let num_elements = if bytes.len() % 7 == 0 {
- bytes.len() / 7
- } else {
- bytes.len() / 7 + 1
- };
-
- // initialize state to all zeros, except for the first element of the capacity part, which
- // is set to 1 if the number of elements is not a multiple of RATE_WIDTH.
- let mut state = [BaseElement::ZERO; STATE_WIDTH];
- if num_elements % RATE_WIDTH != 0 {
- state[CAPACITY_RANGE.start] = BaseElement::ONE;
- }
-
- // break the string into 7-byte chunks, convert each chunk into a field element, and
- // absorb the element into the rate portion of the state. we use 7-byte chunks because
- // every 7-byte chunk is guaranteed to map to some field element.
- let mut i = 0;
- let mut buf = [0_u8; 8];
- for (index, chunk) in bytes.chunks(7).enumerate() {
- if index < num_elements - 1 {
- buf[..7].copy_from_slice(chunk);
- } else {
- // if we are dealing with the last chunk, it may be smaller than 7 bytes long, so
- // we need to handle it slightly differently. we also append a byte with value 1
- // to the end of the string; this pads the string in such a way that adding
- // trailing zeros results in different hash
- let chunk_len = chunk.len();
- buf = [0_u8; 8];
- buf[..chunk_len].copy_from_slice(chunk);
- buf[chunk_len] = 1;
- }
-
- // convert the bytes into a field element and absorb it into the rate portion of the
- // state; if the rate is filled up, apply the Griffin permutation and start absorbing
- // again from zero index.
- state[RATE_RANGE.start + i] += BaseElement::new(u64::from_le_bytes(buf));
- i += 1;
- if i % RATE_WIDTH == 0 {
- Self::apply_permutation(&mut state);
- i = 0;
- }
- }
-
- // if we absorbed some elements but didn't apply a permutation to them (would happen when
- // the number of elements is not a multiple of RATE_WIDTH), apply a final permutation after
- // padding by appending a 1 followed by as many 0 as necessary to make the input length a
- // multiple of the RATE_WIDTH.
- if i > 0 {
- state[RATE_RANGE.start + i] = BaseElement::ONE;
- i += 1;
- while i != RATE_WIDTH {
- state[RATE_RANGE.start + i] = BaseElement::ZERO;
- i += 1;
- }
- Self::apply_permutation(&mut state);
- }
-
- // return the first 4 elements of the state as hash result
- ElementDigest::new(state[DIGEST_RANGE].try_into().unwrap())
- }
-
- // We do not rely on the sponge construction to build our compression function. Instead, we use
- // the Jive compression mode designed in https://eprint.iacr.org/2022/840.pdf.
- fn merge(values: &[Self::Digest; 2]) -> Self::Digest {
- // initialize the state by copying the digest elements into the state
- let initial_state: [BaseElement; STATE_WIDTH] =
- Self::Digest::digests_as_elements(values).try_into().unwrap();
- let mut state = initial_state;
-
- // apply the Griffin permutation and apply the final Jive summation
- Self::apply_permutation(&mut state);
-
- Self::apply_jive_summation(&initial_state, &state)
- }
-
- // We do not rely on the sponge construction to build our compression function. Instead, we use
- // the Jive compression mode designed in https://eprint.iacr.org/2022/840.pdf.
- fn merge_with_int(seed: Self::Digest, value: u64) -> Self::Digest {
- // initialize the state as follows:
- // - seed is copied into the first 4 elements of the state.
- // - if the value fits into a single field element, copy it into the fifth rate element
- // and set the last state element to 5 (the number of elements to be hashed).
- // - if the value doesn't fit into a single field element, split it into two field
- // elements, copy them into state elements 5 and 6, and set the last state element
- // to 6.
- let mut state = [BaseElement::ZERO; STATE_WIDTH];
- state[INPUT1_RANGE].copy_from_slice(seed.as_elements());
- state[INPUT2_RANGE.start] = BaseElement::new(value);
- if value < BaseElement::MODULUS {
- state[INPUT2_RANGE.end - 1] = BaseElement::new(DIGEST_SIZE as u64 + 1);
- } else {
- state[INPUT2_RANGE.start + 1] = BaseElement::new(value / BaseElement::MODULUS);
- state[INPUT2_RANGE.end - 1] = BaseElement::new(DIGEST_SIZE as u64 + 2);
- }
-
- let initial_state = state;
- // apply the Griffin permutation and apply the final Jive summation
- Self::apply_permutation(&mut state);
-
- Self::apply_jive_summation(&initial_state, &state)
- }
-}
-
-impl ElementHasher for GriffinJive64_256 {
- type BaseField = BaseElement;
-
- fn hash_elements>(elements: &[E]) -> Self::Digest {
- // convert the elements into a list of base field elements
- let elements = E::slice_as_base_elements(elements);
-
- // initialize state to all zeros, except for the first element of the capacity part, which
- // is set to 1 if the number of elements is not a multiple of RATE_WIDTH.
- let mut state = [BaseElement::ZERO; STATE_WIDTH];
- if elements.len() % RATE_WIDTH != 0 {
- state[CAPACITY_RANGE.start] = BaseElement::ONE;
- }
-
- // absorb elements into the state one by one until the rate portion of the state is filled
- // up; then apply the Griffin permutation and start absorbing again; repeat until all
- // elements have been absorbed
- let mut i = 0;
- for &element in elements.iter() {
- state[RATE_RANGE.start + i] += element;
- i += 1;
- if i % RATE_WIDTH == 0 {
- Self::apply_permutation(&mut state);
- i = 0;
- }
- }
-
- // if we absorbed some elements but didn't apply a permutation to them (would happen when
- // the number of elements is not a multiple of RATE_WIDTH), apply a final permutation after
- // padding by appending a 1 followed by as many 0 as necessary to make the input length a
- // multiple of the RATE_WIDTH.
- if i > 0 {
- state[RATE_RANGE.start + i] = BaseElement::ONE;
- i += 1;
- while i != RATE_WIDTH {
- state[RATE_RANGE.start + i] = BaseElement::ZERO;
- i += 1;
- }
- Self::apply_permutation(&mut state);
- }
-
- // return the first 4 elements of the state as hash result
- ElementDigest::new(state[DIGEST_RANGE].try_into().unwrap())
- }
-}
-
-// HASH FUNCTION IMPLEMENTATION
-// ================================================================================================
-
-impl GriffinJive64_256 {
- // CONSTANTS
- // --------------------------------------------------------------------------------------------
-
- /// The number of rounds is set to 7 to target 128-bit security level with 40% security margin.
- pub const NUM_ROUNDS: usize = NUM_ROUNDS;
-
- /// Sponge state is set to 8 field elements or 64 bytes; 4 elements are reserved for rate and
- /// the remaining 4 elements are reserved for capacity.
- pub const STATE_WIDTH: usize = STATE_WIDTH;
-
- /// The rate portion of the state is located in elements 4 through 7 (inclusive).
- pub const RATE_RANGE: Range = RATE_RANGE;
-
- /// The capacity portion of the state is located in elements 0, 1, 2, and 3.
- pub const CAPACITY_RANGE: Range = CAPACITY_RANGE;
-
- /// The output of the hash function can be read from state elements 4, 5, 6, and 7.
- pub const DIGEST_RANGE: Range = DIGEST_RANGE;
-
- /// MDS matrix used for computing the linear layer in a Griffin round.
- pub const MDS: [[BaseElement; STATE_WIDTH]; STATE_WIDTH] = MDS;
-
- /// Round constants added to the hasher state in the first half of the Griffin round.
- pub const ARK: [[BaseElement; STATE_WIDTH]; NUM_ROUNDS - 1] = ARK;
-
- /// Constants alpha_i for Griffin non-linear layer.
- pub(crate) const ALPHA: [BaseElement; STATE_WIDTH - 2] = [
- BaseElement::new(6303398607380181568),
- BaseElement::new(12606797214760363136),
- BaseElement::new(463451752725960383),
- BaseElement::new(6766850360106141951),
- BaseElement::new(13070248967486323519),
- BaseElement::new(926903505451920766),
- ];
-
- /// Constants beta_i for Griffin non-linear layer.
- pub(crate) const BETA: [BaseElement; STATE_WIDTH - 2] = [
- BaseElement::new(5698628486727258041),
- BaseElement::new(4347769877494447843),
- BaseElement::new(14394168241716153727),
- BaseElement::new(17391079509977791372),
- BaseElement::new(13338503682279360778),
- BaseElement::new(2236440758620861945),
- ];
-
- // GRIFFIN PERMUTATION
- // --------------------------------------------------------------------------------------------
-
- /// Applies Griffin permutation to the provided state.
- pub fn apply_permutation(state: &mut [BaseElement; STATE_WIDTH]) {
- for i in 0..NUM_ROUNDS - 1 {
- Self::apply_round(state, i);
- }
- Self::apply_non_linear(state);
- Self::apply_linear(state);
- }
-
- /// Griffin round function.
- #[inline(always)]
- pub fn apply_round(state: &mut [BaseElement; STATE_WIDTH], round: usize) {
- Self::apply_non_linear(state);
- Self::apply_linear(state);
- Self::add_constants(state, &ARK[round]);
- }
-
- #[inline(always)]
- pub fn apply_jive_summation(
- initial_state: &[BaseElement; STATE_WIDTH],
- final_state: &[BaseElement; STATE_WIDTH],
- ) -> ElementDigest {
- let mut result = [BaseElement::ZERO; DIGEST_SIZE];
- for (i, r) in result.iter_mut().enumerate() {
- *r = initial_state[i]
- + initial_state[DIGEST_SIZE + i]
- + final_state[i]
- + final_state[DIGEST_SIZE + i];
- }
-
- ElementDigest::new(result)
- }
-
- // HELPER FUNCTIONS
- // --------------------------------------------------------------------------------------------
-
- #[inline(always)]
- /// Applies the Griffin non-linear layer
- /// to the current hash state.
- fn apply_non_linear(state: &mut [BaseElement; STATE_WIDTH]) {
- pow_inv_d(&mut state[0]);
- pow_d(&mut state[1]);
-
- let l2 = Self::linear_function(2, state[0], state[1], BaseElement::ZERO);
- state[2] *= l2.square() + Self::ALPHA[0] * l2 + Self::BETA[0];
-
- let l3 = Self::linear_function(3, state[0], state[1], state[2]);
- state[3] *= l3.square() + Self::ALPHA[1] * l3 + Self::BETA[1];
-
- let l4 = Self::linear_function(4, state[0], state[1], state[3]);
- state[4] *= l4.square() + Self::ALPHA[2] * l4 + Self::BETA[2];
-
- let l5 = Self::linear_function(5, state[0], state[1], state[4]);
- state[5] *= l5.square() + Self::ALPHA[3] * l5 + Self::BETA[3];
-
- let l6 = Self::linear_function(6, state[0], state[1], state[5]);
- state[6] *= l6.square() + Self::ALPHA[4] * l6 + Self::BETA[4];
-
- let l7 = Self::linear_function(7, state[0], state[1], state[6]);
- state[7] *= l7.square() + Self::ALPHA[5] * l7 + Self::BETA[5];
- }
-
- #[inline(always)]
- fn apply_linear(state: &mut [BaseElement; STATE_WIDTH]) {
- mds_multiply(state)
- }
-
- #[inline(always)]
- fn add_constants(state: &mut [BaseElement; STATE_WIDTH], ark: &[BaseElement; STATE_WIDTH]) {
- state.iter_mut().zip(ark).for_each(|(s, &k)| *s += k);
- }
-
- #[inline(always)]
- fn linear_function(
- round: u64,
- z0: BaseElement,
- z1: BaseElement,
- z2: BaseElement,
- ) -> BaseElement {
- let (r0, r1, r2) = (z0.inner() as u128, z1.inner() as u128, z2.inner() as u128);
- let r = (round - 1) as u128 * r0 + r1 + r2;
- let s_hi = (r >> 64) as u64;
- let s_lo = r as u64;
- let z = (s_hi << 32) - s_hi;
- let (res, over) = s_lo.overflowing_add(z);
-
- BaseElement::from_mont(res.wrapping_add(0u32.wrapping_sub(over as u32) as u64))
- }
-}
-
-#[inline(always)]
-fn pow_d(x: &mut BaseElement) {
- *x = x.exp7();
-}
-
-#[inline(always)]
-fn pow_inv_d(x: &mut BaseElement) {
- // compute base^10540996611094048183 using 72 multiplications
- // 10540996611094048183 = b1001001001001001001001001001000110110110110110110110110110110111
-
- // compute base^10
- let t1 = x.square();
-
- // compute base^100
- let t2 = t1.square();
-
- // compute base^100100
- let t3 = square_assign_and_multiply::<3>(t2, t2);
-
- // compute base^100100100100
- let t4 = square_assign_and_multiply::<6>(t3, t3);
-
- // compute base^100100100100100100100100
- let t5 = square_assign_and_multiply::<12>(t4, t4);
-
- // compute base^100100100100100100100100100100
- let t6 = square_assign_and_multiply::<6>(t5, t3);
-
- // compute base^1001001001001001001001001001000100100100100100100100100100100
- let t7 = square_assign_and_multiply::<31>(t6, t6);
-
- // compute base^1001001001001001001001001001000110110110110110110110110110110111
- let a = (t7.square() * t6).square().square();
- let b = t1 * t2 * *x;
- *x = a * b;
-}
-
-#[inline(always)]
-/// Squares an element M times, then multiplies it with tail.
-fn square_assign_and_multiply(base: BaseElement, tail: BaseElement) -> BaseElement {
- let mut result = base;
- for _ in 0..M {
- result = result.square();
- }
-
- result * tail
-}
-
-// MDS
-// ================================================================================================
-/// Griffin MDS matrix
-const MDS: [[BaseElement; STATE_WIDTH]; STATE_WIDTH] = [
- [
- BaseElement::new(23),
- BaseElement::new(8),
- BaseElement::new(13),
- BaseElement::new(10),
- BaseElement::new(7),
- BaseElement::new(6),
- BaseElement::new(21),
- BaseElement::new(8),
- ],
- [
- BaseElement::new(8),
- BaseElement::new(23),
- BaseElement::new(8),
- BaseElement::new(13),
- BaseElement::new(10),
- BaseElement::new(7),
- BaseElement::new(6),
- BaseElement::new(21),
- ],
- [
- BaseElement::new(21),
- BaseElement::new(8),
- BaseElement::new(23),
- BaseElement::new(8),
- BaseElement::new(13),
- BaseElement::new(10),
- BaseElement::new(7),
- BaseElement::new(6),
- ],
- [
- BaseElement::new(6),
- BaseElement::new(21),
- BaseElement::new(8),
- BaseElement::new(23),
- BaseElement::new(8),
- BaseElement::new(13),
- BaseElement::new(10),
- BaseElement::new(7),
- ],
- [
- BaseElement::new(7),
- BaseElement::new(6),
- BaseElement::new(21),
- BaseElement::new(8),
- BaseElement::new(23),
- BaseElement::new(8),
- BaseElement::new(13),
- BaseElement::new(10),
- ],
- [
- BaseElement::new(10),
- BaseElement::new(7),
- BaseElement::new(6),
- BaseElement::new(21),
- BaseElement::new(8),
- BaseElement::new(23),
- BaseElement::new(8),
- BaseElement::new(13),
- ],
- [
- BaseElement::new(13),
- BaseElement::new(10),
- BaseElement::new(7),
- BaseElement::new(6),
- BaseElement::new(21),
- BaseElement::new(8),
- BaseElement::new(23),
- BaseElement::new(8),
- ],
- [
- BaseElement::new(8),
- BaseElement::new(13),
- BaseElement::new(10),
- BaseElement::new(7),
- BaseElement::new(6),
- BaseElement::new(21),
- BaseElement::new(8),
- BaseElement::new(23),
- ],
-];
-
-/// Griffin Inverse MDS matrix
-#[cfg(test)]
-const INV_MDS: [[BaseElement; STATE_WIDTH]; STATE_WIDTH] = [
- [
- BaseElement::new(10671399028204489528),
- BaseElement::new(15436289366139187412),
- BaseElement::new(4624329233769728317),
- BaseElement::new(18200084821960740316),
- BaseElement::new(8736112961492104393),
- BaseElement::new(1953609990965186349),
- BaseElement::new(12477339747250042564),
- BaseElement::new(1495657543820456485),
- ],
- [
- BaseElement::new(1495657543820456485),
- BaseElement::new(10671399028204489528),
- BaseElement::new(15436289366139187412),
- BaseElement::new(4624329233769728317),
- BaseElement::new(18200084821960740316),
- BaseElement::new(8736112961492104393),
- BaseElement::new(1953609990965186349),
- BaseElement::new(12477339747250042564),
- ],
- [
- BaseElement::new(12477339747250042564),
- BaseElement::new(1495657543820456485),
- BaseElement::new(10671399028204489528),
- BaseElement::new(15436289366139187412),
- BaseElement::new(4624329233769728317),
- BaseElement::new(18200084821960740316),
- BaseElement::new(8736112961492104393),
- BaseElement::new(1953609990965186349),
- ],
- [
- BaseElement::new(1953609990965186349),
- BaseElement::new(12477339747250042564),
- BaseElement::new(1495657543820456485),
- BaseElement::new(10671399028204489528),
- BaseElement::new(15436289366139187412),
- BaseElement::new(4624329233769728317),
- BaseElement::new(18200084821960740316),
- BaseElement::new(8736112961492104393),
- ],
- [
- BaseElement::new(8736112961492104393),
- BaseElement::new(1953609990965186349),
- BaseElement::new(12477339747250042564),
- BaseElement::new(1495657543820456485),
- BaseElement::new(10671399028204489528),
- BaseElement::new(15436289366139187412),
- BaseElement::new(4624329233769728317),
- BaseElement::new(18200084821960740316),
- ],
- [
- BaseElement::new(18200084821960740316),
- BaseElement::new(8736112961492104393),
- BaseElement::new(1953609990965186349),
- BaseElement::new(12477339747250042564),
- BaseElement::new(1495657543820456485),
- BaseElement::new(10671399028204489528),
- BaseElement::new(15436289366139187412),
- BaseElement::new(4624329233769728317),
- ],
- [
- BaseElement::new(4624329233769728317),
- BaseElement::new(18200084821960740316),
- BaseElement::new(8736112961492104393),
- BaseElement::new(1953609990965186349),
- BaseElement::new(12477339747250042564),
- BaseElement::new(1495657543820456485),
- BaseElement::new(10671399028204489528),
- BaseElement::new(15436289366139187412),
- ],
- [
- BaseElement::new(15436289366139187412),
- BaseElement::new(4624329233769728317),
- BaseElement::new(18200084821960740316),
- BaseElement::new(8736112961492104393),
- BaseElement::new(1953609990965186349),
- BaseElement::new(12477339747250042564),
- BaseElement::new(1495657543820456485),
- BaseElement::new(10671399028204489528),
- ],
-];
-
-// ROUND CONSTANTS
-// ================================================================================================
-
-/// Griffin round constants;
-const ARK: [[BaseElement; STATE_WIDTH]; NUM_ROUNDS - 1] = [
- [
- BaseElement::new(9692712401870945221),
- BaseElement::new(7618007584389424767),
- BaseElement::new(5248032629877155397),
- BaseElement::new(3331263627507477698),
- BaseElement::new(860199187432911550),
- BaseElement::new(10360526140302824670),
- BaseElement::new(5014858186237911359),
- BaseElement::new(4161019260461204222),
- ],
- [
- BaseElement::new(2649891723669882704),
- BaseElement::new(15035697086627576083),
- BaseElement::new(14140087988207356741),
- BaseElement::new(357780579603925138),
- BaseElement::new(273712483418536090),
- BaseElement::new(348552596175072640),
- BaseElement::new(11116926243792475367),
- BaseElement::new(2475357435469270767),
- ],
- [
- BaseElement::new(9513699262061178678),
- BaseElement::new(11735848814479196467),
- BaseElement::new(12888397717055708631),
- BaseElement::new(15194236579723079985),
- BaseElement::new(14734897209064082180),
- BaseElement::new(9352307275330595094),
- BaseElement::new(2536293522055086772),
- BaseElement::new(1551701365424645656),
- ],
- [
- BaseElement::new(17180574791560887028),
- BaseElement::new(10973179380721509279),
- BaseElement::new(15451549433162538377),
- BaseElement::new(11230437049044589131),
- BaseElement::new(14416448585168854586),
- BaseElement::new(13520950449774622599),
- BaseElement::new(14110026253178816443),
- BaseElement::new(7562226163074683487),
- ],
- [
- BaseElement::new(15625584526294513461),
- BaseElement::new(12868717640985007163),
- BaseElement::new(5045176603305276542),
- BaseElement::new(6821445918259551845),
- BaseElement::new(15049718154108882541),
- BaseElement::new(676731535772312475),
- BaseElement::new(14779363889066167393),
- BaseElement::new(17108914943169063073),
- ],
- [
- BaseElement::new(17529530613938644968),
- BaseElement::new(13801329800663243071),
- BaseElement::new(12666329335088484031),
- BaseElement::new(10289051774796875319),
- BaseElement::new(46795987162557096),
- BaseElement::new(8590445841426612555),
- BaseElement::new(7174111149249058757),
- BaseElement::new(5820086182616968416),
- ],
-];
diff --git a/crypto/src/hash/griffin/griffin64_256_jive/tests.rs b/crypto/src/hash/griffin/griffin64_256_jive/tests.rs
deleted file mode 100644
index 346f58fbe..000000000
--- a/crypto/src/hash/griffin/griffin64_256_jive/tests.rs
+++ /dev/null
@@ -1,214 +0,0 @@
-// Copyright (c) Facebook, Inc. and its affiliates.
-//
-// This source code is licensed under the MIT license found in the
-// LICENSE file in the root directory of this source tree.
-
-use super::{
- BaseElement, ElementDigest, ElementHasher, FieldElement, GriffinJive64_256, Hasher, StarkField,
- INV_MDS, MDS, STATE_WIDTH,
-};
-use proptest::prelude::*;
-
-use rand_utils::{rand_array, rand_value};
-
-#[allow(clippy::needless_range_loop)]
-#[test]
-fn mds_inv_test() {
- let mut mul_result = [[BaseElement::new(0); STATE_WIDTH]; STATE_WIDTH];
- for i in 0..STATE_WIDTH {
- for j in 0..STATE_WIDTH {
- let result = {
- let mut result = BaseElement::new(0);
- for k in 0..STATE_WIDTH {
- result += MDS[i][k] * INV_MDS[k][j]
- }
- result
- };
- mul_result[i][j] = result;
- if i == j {
- assert_eq!(result, BaseElement::new(1));
- } else {
- assert_eq!(result, BaseElement::new(0));
- }
- }
- }
-}
-
-#[test]
-fn test_pow_d() {
- let mut e: BaseElement = rand_value();
- let e_copy = e;
- let e_exp = e.exp(7);
- super::pow_d(&mut e);
- assert_eq!(e, e_exp);
- super::pow_inv_d(&mut e);
- assert_eq!(e, e_copy);
-}
-
-#[test]
-fn apply_permutation() {
- let mut state: [BaseElement; STATE_WIDTH] = [
- BaseElement::new(0),
- BaseElement::new(1),
- BaseElement::new(2),
- BaseElement::new(3),
- BaseElement::new(4),
- BaseElement::new(5),
- BaseElement::new(6),
- BaseElement::new(7),
- ];
-
- GriffinJive64_256::apply_permutation(&mut state);
-
- // expected values are obtained by executing sage implementation code
- // available at https://github.com/Nashtare/griffin-hash
- let expected = vec![
- BaseElement::new(5100889723013202324),
- BaseElement::new(6905683344086677437),
- BaseElement::new(8236358786066512460),
- BaseElement::new(1729367862961866374),
- BaseElement::new(11501420603552582981),
- BaseElement::new(15040992847148175954),
- BaseElement::new(10400407304634768298),
- BaseElement::new(1197713229800045418),
- ];
-
- assert_eq!(expected, state);
-}
-
-#[test]
-fn hash() {
- let state: [BaseElement; STATE_WIDTH] = [
- BaseElement::new(0),
- BaseElement::new(1),
- BaseElement::new(2),
- BaseElement::new(3),
- BaseElement::new(4),
- BaseElement::new(5),
- BaseElement::new(6),
- BaseElement::new(7),
- ];
-
- let result = GriffinJive64_256::hash_elements(&state);
-
- // expected values are obtained by executing sage implementation code
- // available at https://github.com/Nashtare/griffin-hash
- let expected = vec![
- BaseElement::new(16887612651479285699),
- BaseElement::new(16469590207124000227),
- BaseElement::new(11134472952466778260),
- BaseElement::new(15455301814830509354),
- ];
-
- assert_eq!(expected, result.as_elements());
-}
-
-#[test]
-fn hash_elements_vs_merge() {
- let elements: [BaseElement; 8] = rand_array();
-
- let digests: [ElementDigest; 2] = [
- ElementDigest::new(elements[..4].try_into().unwrap()),
- ElementDigest::new(elements[4..].try_into().unwrap()),
- ];
-
- let m_result = GriffinJive64_256::merge(&digests);
- let h_result = GriffinJive64_256::hash_elements(&elements);
-
- // Because we use the Jive compression mode, `merge` and
- // `hash_elements` methods are incompatible.
- assert_ne!(m_result, h_result);
-}
-
-#[test]
-fn hash_elements_vs_merge_with_int() {
- let seed = ElementDigest::new(rand_array());
-
- // ----- value fits into a field element ------------------------------------------------------
- let val: BaseElement = rand_value();
- let m_result = GriffinJive64_256::merge_with_int(seed, val.as_int());
-
- let mut elements = seed.as_elements().to_vec();
- elements.push(val);
- let h_result = GriffinJive64_256::hash_elements(&elements);
-
- // Because we use the Jive compression mode, `merge` and
- // `hash_elements` methods are incompatible.
- assert_ne!(m_result, h_result);
-
- // ----- value does not fit into a field element ----------------------------------------------
- let val = BaseElement::MODULUS + 2;
- let m_result = GriffinJive64_256::merge_with_int(seed, val);
-
- let mut elements = seed.as_elements().to_vec();
- elements.push(BaseElement::new(val));
- elements.push(BaseElement::new(1));
- let h_result = GriffinJive64_256::hash_elements(&elements);
-
- // Because we use the Jive compression mode, `merge` and
- // `hash_elements` methods are incompatible.
- assert_ne!(m_result, h_result);
-}
-
-#[test]
-fn hash_padding() {
- // adding a zero bytes at the end of a byte string should result in a different hash
- let r1 = GriffinJive64_256::hash(&[1_u8, 2, 3]);
- let r2 = GriffinJive64_256::hash(&[1_u8, 2, 3, 0]);
- assert_ne!(r1, r2);
-
- // same as above but with bigger inputs
- let r1 = GriffinJive64_256::hash(&[1_u8, 2, 3, 4, 5, 6]);
- let r2 = GriffinJive64_256::hash(&[1_u8, 2, 3, 4, 5, 6, 0]);
- assert_ne!(r1, r2);
-
- // same as above but with input splitting over two elements
- let r1 = GriffinJive64_256::hash(&[1_u8, 2, 3, 4, 5, 6, 7]);
- let r2 = GriffinJive64_256::hash(&[1_u8, 2, 3, 4, 5, 6, 7, 0]);
- assert_ne!(r1, r2);
-
- // same as above but with multiple zeros
- let r1 = GriffinJive64_256::hash(&[1_u8, 2, 3, 4, 5, 6, 7, 0, 0]);
- let r2 = GriffinJive64_256::hash(&[1_u8, 2, 3, 4, 5, 6, 7, 0, 0, 0, 0]);
- assert_ne!(r1, r2);
-}
-
-#[test]
-fn hash_elements_padding() {
- let e1: [BaseElement; 2] = rand_array();
- let e2 = [e1[0], e1[1], BaseElement::ZERO];
-
- let r1 = GriffinJive64_256::hash_elements(&e1);
- let r2 = GriffinJive64_256::hash_elements(&e2);
- assert_ne!(r1, r2);
-}
-
-#[inline(always)]
-fn apply_mds_naive(state: &mut [BaseElement; STATE_WIDTH]) {
- let mut result = [BaseElement::ZERO; STATE_WIDTH];
- result.iter_mut().zip(MDS).for_each(|(r, mds_row)| {
- state.iter().zip(mds_row).for_each(|(&s, m)| {
- *r += m * s;
- });
- });
- *state = result;
-}
-
-proptest! {
- #[test]
- fn mds_freq_proptest(a in any::<[u64; STATE_WIDTH]>()) {
-
- let mut v1 = [BaseElement::ZERO; STATE_WIDTH];
- let mut v2;
-
- for i in 0..STATE_WIDTH {
- v1[i] = BaseElement::new(a[i]);
- }
- v2 = v1;
-
- apply_mds_naive(&mut v1);
- GriffinJive64_256::apply_linear(&mut v2);
-
- prop_assert_eq!(v1, v2);
- }
-}
diff --git a/crypto/src/hash/griffin/mod.rs b/crypto/src/hash/griffin/mod.rs
deleted file mode 100644
index 190526fea..000000000
--- a/crypto/src/hash/griffin/mod.rs
+++ /dev/null
@@ -1,9 +0,0 @@
-// Copyright (c) Facebook, Inc. and its affiliates.
-//
-// This source code is licensed under the MIT license found in the
-// LICENSE file in the root directory of this source tree.
-
-use super::{Digest, ElementHasher, Hasher};
-
-mod griffin64_256_jive;
-pub use griffin64_256_jive::GriffinJive64_256;
diff --git a/crypto/src/hash/mod.rs b/crypto/src/hash/mod.rs
index 99ff71105..5b8e1fe92 100644
--- a/crypto/src/hash/mod.rs
+++ b/crypto/src/hash/mod.rs
@@ -18,9 +18,6 @@ mod mds;
mod rescue;
pub use rescue::{Rp62_248, Rp64_256, RpJive64_256};
-mod griffin;
-pub use griffin::GriffinJive64_256;
-
// HASHER TRAITS
// ================================================================================================
diff --git a/crypto/src/hash/rescue/rp64_256_jive/mod.rs b/crypto/src/hash/rescue/rp64_256_jive/mod.rs
index 66178baab..b28964684 100644
--- a/crypto/src/hash/rescue/rp64_256_jive/mod.rs
+++ b/crypto/src/hash/rescue/rp64_256_jive/mod.rs
@@ -152,7 +152,7 @@ impl Hasher for RpJive64_256 {
}
// convert the bytes into a field element and absorb it into the rate portion of the
- // state; if the rate is filled up, apply the Griffin permutation and start absorbing
+ // state; if the rate is filled up, apply the Rescue-Prime permutation and start absorbing
// again from zero index.
state[RATE_RANGE.start + i] += BaseElement::new(u64::from_le_bytes(buf));
i += 1;
@@ -237,7 +237,7 @@ impl ElementHasher for RpJive64_256 {
}
// absorb elements into the state one by one until the rate portion of the state is filled
- // up; then apply the Griffin permutation and start absorbing again; repeat until all
+ // up; then apply the Rescue-Prime permutation and start absorbing again; repeat until all
// elements have been absorbed
let mut i = 0;
for &element in elements.iter() {
diff --git a/crypto/src/lib.rs b/crypto/src/lib.rs
index 0f2d9de1b..cc4877c89 100644
--- a/crypto/src/lib.rs
+++ b/crypto/src/lib.rs
@@ -29,7 +29,6 @@ pub mod hashers {
pub use super::hash::Blake3_192;
pub use super::hash::Blake3_256;
- pub use super::hash::GriffinJive64_256;
pub use super::hash::Rp62_248;
pub use super::hash::Rp64_256;
pub use super::hash::RpJive64_256;
diff --git a/examples/src/fibonacci/fib_small/mod.rs b/examples/src/fibonacci/fib_small/mod.rs
index 5b149a42f..85bb89c42 100644
--- a/examples/src/fibonacci/fib_small/mod.rs
+++ b/examples/src/fibonacci/fib_small/mod.rs
@@ -33,7 +33,6 @@ type Blake3_256 = winterfell::crypto::hashers::Blake3_256;
type Sha3_256 = winterfell::crypto::hashers::Sha3_256;
type Rp64_256 = winterfell::crypto::hashers::Rp64_256;
type RpJive64_256 = winterfell::crypto::hashers::RpJive64_256;
-type GriffinJive64_256 = winterfell::crypto::hashers::GriffinJive64_256;
// FIBONACCI EXAMPLE
// ================================================================================================
@@ -60,9 +59,6 @@ pub fn get_example(
HashFunction::RpJive64_256 => {
Ok(Box::new(FibExample::::new(sequence_length, options)))
}
- HashFunction::GriffinJive64_256 => {
- Ok(Box::new(FibExample::::new(sequence_length, options)))
- }
}
}
diff --git a/examples/src/lib.rs b/examples/src/lib.rs
index 14f27a584..3801a260d 100644
--- a/examples/src/lib.rs
+++ b/examples/src/lib.rs
@@ -5,7 +5,7 @@
use structopt::StructOpt;
use winterfell::{
- crypto::hashers::{GriffinJive64_256, Rp64_256, RpJive64_256},
+ crypto::hashers::{Rp64_256, RpJive64_256},
math::fields::f128::BaseElement,
FieldExtension, ProofOptions, StarkProof, VerifierError,
};
@@ -88,7 +88,6 @@ impl ExampleOptions {
"sha3_256" => HashFunction::Sha3_256,
"rp64_256" => HashFunction::Rp64_256,
"rp_jive64_256" => HashFunction::RpJive64_256,
- "griffin_jive64_256" => HashFunction::GriffinJive64_256,
val => panic!("'{val}' is not a valid hash function option"),
};
@@ -113,7 +112,6 @@ impl ExampleOptions {
"sha3_256" => proof.security_level::(conjectured),
"rp64_256" => proof.security_level::(conjectured),
"rp_jive64_256" => proof.security_level::(conjectured),
- "griffin_jive64_256" => proof.security_level::(conjectured),
val => panic!("'{val}' is not a valid hash function option"),
};
@@ -236,10 +234,4 @@ pub enum HashFunction {
///
/// When this function is used in the STARK protocol, proof security cannot exceed 128 bits.
RpJive64_256,
-
- /// Griffin hash function with 256 bit output. It only works in `f64` field.
- /// This instance uses the Jive compression mode in Merkle trees.
- ///
- /// When this function is used in the STARK protocol, proof security cannot exceed 128 bits.
- GriffinJive64_256,
}