You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

89 lines
2.1 KiB

4 years ago
4 years ago
4 years ago
3 years ago
4 years ago
3 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
  1. package poseidon
  2. import (
  3. "errors"
  4. "fmt"
  5. "math/big"
  6. "github.com/iden3/go-iden3-crypto/ff"
  7. "github.com/iden3/go-iden3-crypto/utils"
  8. )
  9. const NROUNDSF = 8 //nolint:golint
  10. var NROUNDSP = []int{56, 57, 56, 60, 60, 63, 64, 63} //nolint:golint
  11. func zero() *ff.Element {
  12. return ff.NewElement()
  13. }
  14. // ark computes Add-Round Key, from the paper https://eprint.iacr.org/2019/458.pdf
  15. func ark(state []*ff.Element, c []*ff.Element, it int) {
  16. for i := 0; i < len(state); i++ {
  17. state[i].Add(state[i], c[it+i])
  18. }
  19. }
  20. // exp5 performs x^5 mod p
  21. // https://eprint.iacr.org/2019/458.pdf page 8
  22. func exp5(a *ff.Element) {
  23. a.Exp(*a, 5)
  24. }
  25. // sbox https://eprint.iacr.org/2019/458.pdf page 6
  26. func sbox(nRoundsF, nRoundsP int, state []*ff.Element, i int) {
  27. if (i < nRoundsF/2) || (i >= nRoundsF/2+nRoundsP) {
  28. for j := 0; j < len(state); j++ {
  29. exp5(state[j])
  30. }
  31. } else {
  32. exp5(state[0])
  33. }
  34. }
  35. // mix returns [[matrix]] * [vector]
  36. func mix(state []*ff.Element, newState []*ff.Element, m [][]*ff.Element) {
  37. mul := zero()
  38. for i := 0; i < len(state); i++ {
  39. newState[i].SetUint64(0)
  40. for j := 0; j < len(state); j++ {
  41. mul.Mul(m[i][j], state[j])
  42. newState[i].Add(newState[i], mul)
  43. }
  44. }
  45. }
  46. // Hash computes the Poseidon hash for the given inputs
  47. func Hash(inpBI []*big.Int) (*big.Int, error) {
  48. t := len(inpBI) + 1
  49. if len(inpBI) == 0 || len(inpBI) >= len(NROUNDSP)-1 {
  50. return nil, fmt.Errorf("invalid inputs length %d, max %d", len(inpBI), len(NROUNDSP)-1)
  51. }
  52. if !utils.CheckBigIntArrayInField(inpBI[:]) {
  53. return nil, errors.New("inputs values not inside Finite Field")
  54. }
  55. inp := utils.BigIntArrayToElementArray(inpBI[:])
  56. state := make([]*ff.Element, t)
  57. state[0] = zero()
  58. copy(state[1:], inp[:])
  59. nRoundsF := NROUNDSF
  60. nRoundsP := NROUNDSP[t-2]
  61. newState := make([]*ff.Element, t)
  62. for i := 0; i < t; i++ {
  63. newState[i] = zero()
  64. }
  65. // ARK --> SBox --> M, https://eprint.iacr.org/2019/458.pdf pag.5
  66. for i := 0; i < nRoundsF+nRoundsP; i++ {
  67. ark(state, c.c[t-2], i*t)
  68. sbox(nRoundsF, nRoundsP, state, i)
  69. mix(state, newState, c.m[t-2])
  70. state, newState = newState, state
  71. }
  72. rE := state[0]
  73. r := big.NewInt(0)
  74. rE.ToBigIntRegular(r)
  75. return r, nil
  76. }