7 from Crypto.Hash
import keccak \
9 from abc
import abstractmethod
10 from typing
import List
30 Base class of MiMC implementations.
37 self.
seed = _keccak_256(_str_to_bytes(seed_str))
45 result = message % self.
prime
47 round_constant: int = self.
seed
53 round_constant = _update_round_constant(round_constant)
54 result = self.
mimc_round(result, key, round_constant)
57 return (result + key) % self.
prime
59 def hash(self, left: bytes, right: bytes) -> bytes:
61 Apply Miyaguchi-Preneel to the output of the encrypt function.
63 x = int.from_bytes(left, byteorder=
'big') % self.
prime
64 y = int.from_bytes(right, byteorder=
'big') % self.
prime
65 return self.
hash_int(x, y).to_bytes(32, byteorder=
'big')
69 Similar to hash, but use field elements directly.
76 def mimc_round(self, message: int, key: int, rc: int) -> int:
82 Implementation of MiMCBase with exponent 17
84 def mimc_round(self, message: int, key: int, rc: int) -> int:
93 return ((message + key + rc) ** 17) % self.
prime
98 MiMC specialized for Fr in ALT-BN128, using exponent 17 and 65 rounds. See
99 zeth specifications (Section 3.2) for details.
104 21888242871839275222246405745257275088548364400416034343698204186575808495617,
111 MiMC specialized for Fr in BLS12-377, using exponent 17 and 62 rounds. See
112 zeth specifications (Section 3.2) for details.
117 8444461749428370424248824938781546531375899335154063827935233455917409239041,
123 Return the first `num_rounds` round constants. Not called directly here,
124 but used to precompute (in particular for the mimc_permutation gadget).
126 seed = _keccak_256(_str_to_bytes(seed_str))
130 for _
in range(1, num_rounds):
131 rc = _update_round_constant(rc)
134 assert len(rcs) == num_rounds
140 Select an appropriate hash for a given pairing. Note that these must match
141 the selection logic in `libzeth/circuits/circuit_types.hpp`.
143 if pairing_name ==
"alt-bn128":
145 if pairing_name ==
"bls12-377":
147 raise Exception(f
"no tree hash for pairing: {pairing_name}")
150 def _str_to_bytes(value: str) -> bytes:
151 return value.encode(
'ascii')
154 def _int_to_bytes32(value: int) -> bytes:
155 return value.to_bytes(32,
'big')
158 def _keccak_256(data_bytes: bytes) -> int:
159 h = keccak.new(digest_bits=256)
162 return int.from_bytes(hashed,
'big')
165 def _update_round_constant(rc: int) -> int:
166 return _keccak_256(_int_to_bytes32(rc))