// Hash performs the Poseidon hash over a *big.Int array
// in chunks of 5 elements
func Hash(arr []*big.Int) (*big.Int, error) {
if !utils.CheckBigIntArrayInField(arr, constants.fqR.Q) {
return nil, errors.New("inputs values not inside Finite Field")
}
r := constants.fqR.Zero()
for i := 0; i < len(arr); i = i + 5 {
var fiveElems [5]*big.Int
for j := 0; j < 5; j++ {
if i+j < len(arr) {
fiveElems[j] = arr[i+j]
} else {
fiveElems[j] = _constants.Zero
}
}
ph, err := PoseidonHash(fiveElems[:])
if err != nil {
return nil, err
}
r = constants.fqR.Add(
r,
ph)
}
return r, nil
}
// PoseidonHash computes the Poseidon hash for the given inputs
func PoseidonHash(inp []*big.Int) (*big.Int, error) {
if len(inp) == 0 || len(inp) > T {
return nil, errors.New("wrong inputs length")
}
if !utils.CheckBigIntArrayInField(inp, constants.fqR.Q) {
return nil, errors.New("inputs values not inside Finite Field")
}
state := inp
for i := len(inp); i < T; i++ {
state = append(state, constants.fqR.Zero())
}
// ARK --> SBox --> M, https://eprint.iacr.org/2019/458.pdf pag.5
for i := 0; i < NROUNDSF+NROUNDSP; i++ {
state = ark(state, constants.c[i])
state = sbox(state, i)
state = mix(state, constants.m)
}
return state[0], nil
}