Skip to content

Commit

Permalink
docs: describe potential length extension attack when using MiMC in-c…
Browse files Browse the repository at this point in the history
…ircuit (#1198)

* docs: describe length extension attack in MiMC

* docs: describe potential length extension attack for shorthash
  • Loading branch information
ivokub authored Jul 12, 2024
1 parent 378dd33 commit 8c1cd75
Show file tree
Hide file tree
Showing 3 changed files with 63 additions and 9 deletions.
41 changes: 41 additions & 0 deletions std/hash/mimc/doc.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
// Package mimc provides a ZKP-circuit function to compute a MiMC hash.
//
// For the reference implementation of the MiMC hash function, see the
// corresponding package in [gnark-crypto].
//
// # 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.
//
// [gnark-crypto]: https://pkg.go.dev/github.com/consensys/gnark-crypto/hash
package mimc
20 changes: 13 additions & 7 deletions std/hash/mimc/mimc.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ See the License for the specific language governing permissions and
limitations under the License.
*/

// Package mimc provides a ZKP-circuit function to compute a MiMC hash.
package mimc

import (
Expand All @@ -26,7 +25,9 @@ import (
"github.com/consensys/gnark/internal/utils"
)

// MiMC contains the params of the Mimc hash func and the curves on which it is implemented
// MiMC contains the params of the MiMC hash func and the curves on which it is implemented.
//
// NB! See the package documentation for length extension attack consideration.
type MiMC struct {
params []big.Int // slice containing constants for the encryption rounds
id ecc.ID // id needed to know which encryption function to use
Expand All @@ -35,7 +36,12 @@ type MiMC struct {
api frontend.API // underlying constraint system
}

// NewMiMC returns a MiMC instance, that can be used in a gnark circuit
// NewMiMC returns a MiMC instance that can be used in a gnark circuit. The
// out-circuit counterpart of this function is provided in [gnark-crypto].
//
// NB! See the package documentation for length extension attack consideration.
//
// [gnark-crypto]: https://pkg.go.dev/github.com/consensys/gnark-crypto/hash
func NewMiMC(api frontend.API) (MiMC, error) {
// TODO @gbotrel use field
if constructor, ok := newMimc[utils.FieldToCurve(api.Compiler().Field())]; ok {
Expand All @@ -55,10 +61,10 @@ func (h *MiMC) Reset() {
h.h = 0
}

// Sum hash (in r1cs form) using Miyaguchi–Preneel:
// https://en.wikipedia.org/wiki/One-way_compression_function
// The XOR operation is replaced by field addition.
// See github.com/consensys/gnark-crypto for reference implementation.
// Sum hash using [Miyaguchi–Preneel] where the XOR operation is replaced by
// field addition.
//
// [Miyaguchi–Preneel]: https://en.wikipedia.org/wiki/One-way_compression_function
func (h *MiMC) Sum() frontend.Variable {

//h.Write(data...)s
Expand Down
11 changes: 9 additions & 2 deletions std/recursion/wrapped_hash.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,9 @@ type shortNativeHash struct {
// field and outputs element in the target field (usually the scalar field of
// the circuit being recursed). The hash function is based on MiMC and
// partitions the excess bits to not overflow the target field.
//
// NB! See the considerations in the package documentation of [mimc] for length
// extension attack.
func NewShort(current, target *big.Int) (hash.Hash, error) {
var h cryptomimc.Hash
var bitBlockSize int
Expand Down Expand Up @@ -155,8 +158,12 @@ func newHashFromParameter(api frontend.API, hf stdhash.FieldHasher, bitLength in

// NewHash returns a circuit hash function which reads elements in the current
// native field and outputs element in the target field (usually the scalar
// field of the circuit being recursed). The hash function is based on MiMC and
// partitions the excess bits to not overflow the target field.
// field of the circuit being recursed). The hash function is based on MiMC
// (from [mimc] package) and partitions the excess bits to not overflow the
// target field.
//
// NB! See the considerations in the package documentation of [mimc] for length
// extension attack.
func NewHash(api frontend.API, target *big.Int, bitmode bool) (stdhash.FieldHasher, error) {
h, err := mimc.NewMiMC(api)
if err != nil {
Expand Down

0 comments on commit 8c1cd75

Please sign in to comment.