Documentation
¶
Overview ¶
Package hash provides algebraic hash function defined over implemented curves
This package is kept for backwards compatibility for initializing hash functions directly. The recommended way to initialize hash function is to directly use the constructors in the corresponding packages (e.g. ecc/bn254/fr/mimc). Using the direct constructors allows to apply options for altering the hash function behavior (endianness, input splicing etc.) and returns more specific types with additional methods.
See [Importing hash functions] below for more information.
This package also provides a construction for a generic hash function from the compression primitive. See the interface Compressor and the corresponding initialization function NewMerkleDamgardHasher.
Importing hash functions ¶
The package follows registration pattern for importing hash functions. To import all known hash functions in gnark-crypto, import the github.com/consensys/gnark-crypto/hash/all package in your code. To import only a specific hash, then import the corresponding package directly, e.g. github.com/consensys/gnark-crypto/ecc/bn254/fr/mimc. The import format should be:
import _ "github.com/consensys/gnark-crypto/ecc/bn254/fr/mimc"
Length extension attack ¶
The MiMC hash function is vulnerable to a length extension attack. For example when we have a hash
h = MiMC(k || m)
and we want to hash a new message
m' = m || m2,
we can compute
h' = MiMC(k || m || m2)
without knowing k by computing
h' = MiMC(h || m2).
This is because the MiMC hash function is a simple iterated cipher, and the hash value is the state of the cipher after encrypting the message.
There are several ways to mitigate this attack:
- use a random key for each hash
- use a domain separation tag for different use cases: h = MiMC(k || tag || m)
- use the secret input as last input: h = MiMC(m || k)
In general, inside a circuit the length-extension attack is not a concern as due to the circuit definition the attacker can not append messages to existing hash. But the user has to consider the cases when using a secret key and MiMC in different contexts.
Hash input format ¶
The MiMC hash function is defined over a field. The input to the hash function is a byte slice. The byte slice is interpreted as a sequence of field elements. Due to this interpretation, the input byte slice length must be multiple of the field modulus size. And every sequence of byte slice for a single field element must be strictly less than the field modulus.
See open issues:
Index ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func NewHash ¶ added in v0.18.0
NewHash returns a new hash.Hash object for the given hash function name. It can be a standard hash function (e.g. "MIMC_BN254"), or a custom hash function defined by the user through RegisterCustomHash.
func RegisterCustomHash ¶ added in v0.18.0
RegisterCustomHash registers a new hash function constructor, retrievable by name using NewHash. It does not allow overwriting standard hash functions.
func RegisterHash ¶ added in v0.15.0
RegisterHash registers a new hash function constructor. Should be called in the init function of the hash package.
To register all known hash functions in gnark-crypto, import the github.com/consensys/gnark-crypto/hash/all package in your code.
Types ¶
type Compressor ¶ added in v0.17.0
type Compressor interface {
// Compress compresses the two inputs into one output. All the inputs and
// outputs are of the same size, which is the block size. See [BlockSize].
Compress(left []byte, right []byte) (compressed []byte, err error)
// BlockSize returns the blocks size.
BlockSize() int
}
Compressor is a 2-1 one-way function. It takes two inputs and compresses them into one output. The inputs and outputs are all of the same size, which is the block size. See [BlockSize].
NB! This is lossy compression, meaning that the output is not guaranteed to be unique for different inputs. The function must be stateless, meaning that the output is guaranteed to be the same for the same inputs. It must furthermore not modify its input, even temporarily.
The Compressor is used in the Merkle-Damgard construction to build a hash function.
type Hash ¶
type Hash uint
Hash defines a unique identifier for a hash function.
const ( // MIMC_BN254 is the MiMC hash function for the BN254 curve. MIMC_BN254 Hash = iota // MIMC_BLS12_381 is the MiMC hash function for the BLS12-381 curve. MIMC_BLS12_381 // MIMC_BLS12_377 is the MiMC hash function for the BLS12-377 curve. MIMC_BLS12_377 // MIMC_BW6_761 is the MiMC hash function for the BW6-761 curve. MIMC_BW6_761 // MIMC_BLS24_315 is the MiMC hash function for the BLS24-315 curve. MIMC_BLS24_315 // MIMC_BLS24_317 is the MiMC hash function for the BLS24-317 curve. MIMC_BLS24_317 // MIMC_BW6_633 is the MiMC hash function for the BW6-633 curve. MIMC_BW6_633 // MIMC_GRUMPKIN is the MiMC hash function for the Grumpkin curve. MIMC_GRUMPKIN // POSEIDON2_BLS12_377 is the Poseidon2 hash function for the BLS12-377 curve. POSEIDON2_BLS12_377 // POSEIDON2_BLS12_381 is the Poseidon2 hash function for the BLS12-381 curve. POSEIDON2_BLS12_381 // POSEIDON2_BN254 is the Poseidon2 hash function for the BN254 curve. POSEIDON2_BN254 // POSEIDON2_GRUMPKIN is the Poseidon2 hash function for the Grumpkin curve. POSEIDON2_GRUMPKIN // POSEIDON2_BW6_761 is the Poseidon2 hash function for the BW6-761 curve. POSEIDON2_BW6_761 // POSEIDON2_BW6_633 is the Poseidon2 hash function for the BW6-633 curve. POSEIDON2_BW6_633 // POSEIDON2_BLS24_315 is the Poseidon2 hash function for the BLS21-315 curve. POSEIDON2_BLS24_315 // POSEIDON2_BLS24_317 is the Poseidon2 hash function for the BLS21-317 curve. POSEIDON2_BLS24_317 // POSEIDON2_KOALABEAR is the Poseidon2 hash function for the KoalaBear field. POSEIDON2_KOALABEAR // POSEIDON2_BABYBEAR is the Poseidon2 hash function for the BabyBear field. POSEIDON2_BABYBEAR // POSEIDON2_GOLDILOCKS is the Poseidon2 hash function for the Goldilocks field. POSEIDON2_GOLDILOCKS // POSEIDON2_MAMABEAR is the Poseidon2 hash function for the MamaBear field. POSEIDON2_MAMABEAR )
func (Hash) New ¶
New initializes the hash function. This is a convenience function which does not allow setting hash-specific options.
type StateStorer ¶ added in v0.15.0
type StateStorer interface {
hash.Hash
// State retrieves the current state of the hash function. Calling this
// method should not destroy the current state and allow continue the use of
// the current hasher.
State() []byte
// SetState sets the state of the hash function from a previously stored
// state retrieved using [StateStorer.State] method.
SetState(state []byte) error
}
StateStorer allows to store and retrieve the state of a hash function.
func NewMerkleDamgardHasher ¶ added in v0.17.0
func NewMerkleDamgardHasher(f Compressor, initialState []byte) StateStorer
NewMerkleDamgardHasher transforms a 2-1 one-way compression function into a hash function using a Merkle-Damgard construction. The resulting hash function has a block size equal to the block size of compression function.
NB! The construction does not perform explicit padding on the input data. The last block of input data is zero-padded to full block size. This means that the construction is not collision resistant for generic data as the digest of input and input concatenated with zeros (up to the same number of total blocks) is same. For collision resistance the caller should perform explicit padding on the input data.
- initialState is provided as initial input to the compression function. Its preimage should not be known and thus it should be generated using a deterministic method. If the given initialState is shorter than the hash block size, it will be zero-padded on the left. An oversized initialState will cause a panic.