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.

107 lines
2.2 KiB

  1. package poseidon
  2. import (
  3. "math/big"
  4. "github.com/iden3/go-iden3-crypto/ffg"
  5. )
  6. func zero() *ffg.Element {
  7. return ffg.NewElement()
  8. }
  9. var big7 = big.NewInt(7)
  10. // exp7 performs x^7 mod p
  11. func exp7(a *ffg.Element) {
  12. a.Exp(*a, big7)
  13. }
  14. // exp7state perform exp7 for whole state
  15. func exp7state(state []*ffg.Element) {
  16. for i := 0; i < len(state); i++ {
  17. exp7(state[i])
  18. }
  19. }
  20. // ark computes Add-Round Key, from the paper https://eprint.iacr.org/2019/458.pdf
  21. func ark(state []*ffg.Element, it int) {
  22. for i := 0; i < len(state); i++ {
  23. state[i].Add(state[i], C[it+i])
  24. }
  25. }
  26. // mix returns [[matrix]] * [vector]
  27. func mix(state []*ffg.Element, opt bool) []*ffg.Element {
  28. mul := zero()
  29. newState := make([]*ffg.Element, mLen)
  30. for i := 0; i < mLen; i++ {
  31. newState[i] = zero()
  32. }
  33. for i := 0; i < mLen; i++ {
  34. newState[i].SetUint64(0)
  35. for j := 0; j < mLen; j++ {
  36. if opt {
  37. mul.Mul(P[j][i], state[j])
  38. } else {
  39. mul.Mul(M[j][i], state[j])
  40. }
  41. newState[i].Add(newState[i], mul)
  42. }
  43. }
  44. return newState
  45. }
  46. // Hash computes the hash for the given inputs
  47. func Hash(inpBI [NROUNDSF]uint64, capBI [CAPLEN]uint64) ([CAPLEN]uint64, error) {
  48. state := make([]*ffg.Element, mLen)
  49. for i := 0; i < NROUNDSF; i++ {
  50. state[i] = ffg.NewElement().SetUint64(inpBI[i])
  51. }
  52. for i := 0; i < CAPLEN; i++ {
  53. state[i+NROUNDSF] = ffg.NewElement().SetUint64(capBI[i])
  54. }
  55. for i := 0; i < mLen; i++ {
  56. state[i].Add(state[i], C[i])
  57. }
  58. for r := 0; r < NROUNDSF/2; r++ {
  59. exp7state(state)
  60. ark(state, (r+1)*mLen)
  61. state = mix(state, r == NROUNDSF/2-1)
  62. }
  63. for r := 0; r < NROUNDSP; r++ {
  64. exp7(state[0])
  65. state[0].Add(state[0], C[(NROUNDSF/2+1)*mLen+r])
  66. s0 := zero()
  67. mul := zero()
  68. mul.Mul(S[(mLen*2-1)*r], state[0])
  69. s0.Add(s0, mul)
  70. for i := 1; i < mLen; i++ {
  71. mul.Mul(S[(mLen*2-1)*r+i], state[i])
  72. s0.Add(s0, mul)
  73. mul.Mul(S[(mLen*2-1)*r+mLen+i-1], state[0])
  74. state[i].Add(state[i], mul)
  75. }
  76. state[0] = s0
  77. }
  78. for r := 0; r < NROUNDSF/2; r++ {
  79. exp7state(state)
  80. if r < NROUNDSF/2-1 {
  81. ark(state, (NROUNDSF/2+1+r)*mLen+NROUNDSP)
  82. }
  83. state = mix(state, false)
  84. }
  85. return [CAPLEN]uint64{
  86. state[0].ToUint64Regular(),
  87. state[1].ToUint64Regular(),
  88. state[2].ToUint64Regular(),
  89. state[3].ToUint64Regular(),
  90. }, nil
  91. }