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.

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