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.

120 lines
2.7 KiB

5 years ago
5 years ago
5 years ago
4 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 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, 60, 66, 60, 65, 70, 60, 64, 68} //nolint:golint
  11. func zero() *ff.Element {
  12. return ff.NewElement()
  13. }
  14. // exp5 performs x^5 mod p
  15. // https://eprint.iacr.org/2019/458.pdf page 8
  16. func exp5(a *ff.Element) {
  17. a.Exp(*a, 5) //nolint:gomnd
  18. }
  19. // exp5state perform exp5 for whole state
  20. func exp5state(state []*ff.Element) {
  21. for i := 0; i < len(state); i++ {
  22. exp5(state[i])
  23. }
  24. }
  25. // ark computes Add-Round Key, from the paper https://eprint.iacr.org/2019/458.pdf
  26. func ark(state []*ff.Element, c []*ff.Element, it int) {
  27. for i := 0; i < len(state); i++ {
  28. state[i].Add(state[i], c[it+i])
  29. }
  30. }
  31. // mix returns [[matrix]] * [vector]
  32. func mix(state []*ff.Element, t int, m [][]*ff.Element) []*ff.Element {
  33. mul := zero()
  34. newState := make([]*ff.Element, t)
  35. for i := 0; i < t; i++ {
  36. newState[i] = zero()
  37. }
  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[j][i], state[j])
  42. newState[i].Add(newState[i], mul)
  43. }
  44. }
  45. return newState
  46. }
  47. // Hash computes the Poseidon hash for the given inputs
  48. func Hash(inpBI []*big.Int) (*big.Int, error) {
  49. t := len(inpBI) + 1
  50. if len(inpBI) == 0 || len(inpBI) > len(NROUNDSP) {
  51. return nil, fmt.Errorf("invalid inputs length %d, max %d", len(inpBI), len(NROUNDSP)) //nolint:gomnd,lll
  52. }
  53. if !utils.CheckBigIntArrayInField(inpBI[:]) {
  54. return nil, errors.New("inputs values not inside Finite Field")
  55. }
  56. inp := utils.BigIntArrayToElementArray(inpBI[:])
  57. nRoundsF := NROUNDSF
  58. nRoundsP := NROUNDSP[t-2]
  59. C := c.c[t-2]
  60. S := c.s[t-2]
  61. M := c.m[t-2]
  62. P := c.p[t-2]
  63. state := make([]*ff.Element, t)
  64. state[0] = zero()
  65. copy(state[1:], inp[:])
  66. ark(state, C, 0)
  67. for i := 0; i < nRoundsF/2-1; i++ {
  68. exp5state(state)
  69. ark(state, C, (i+1)*t)
  70. state = mix(state, t, M)
  71. }
  72. exp5state(state)
  73. ark(state, C, (nRoundsF/2)*t)
  74. state = mix(state, t, P)
  75. for i := 0; i < nRoundsP; i++ {
  76. exp5(state[0])
  77. state[0].Add(state[0], C[(nRoundsF/2+1)*t+i])
  78. mul := zero()
  79. newState0 := zero()
  80. for j := 0; j < len(state); j++ {
  81. mul.Mul(S[(t*2-1)*i+j], state[j])
  82. newState0.Add(newState0, mul)
  83. }
  84. for k := 1; k < t; k++ {
  85. mul = zero()
  86. state[k] = state[k].Add(state[k], mul.Mul(state[0], S[(t*2-1)*i+t+k-1]))
  87. }
  88. state[0] = newState0
  89. }
  90. for i := 0; i < nRoundsF/2-1; i++ {
  91. exp5state(state)
  92. ark(state, C, (nRoundsF/2+1)*t+nRoundsP+i*t)
  93. state = mix(state, t, M)
  94. }
  95. exp5state(state)
  96. state = mix(state, t, M)
  97. rE := state[0]
  98. r := big.NewInt(0)
  99. rE.ToBigIntRegular(r)
  100. return r, nil
  101. }