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.

75 lines
1.7 KiB

  1. package poseidon
  2. import (
  3. "math/big"
  4. "github.com/iden3/go-iden3-crypto/ffg"
  5. )
  6. const spongeChunkSize = 31
  7. const spongeInputs = 16
  8. func zero() *ffg.Element {
  9. return ffg.NewElement()
  10. }
  11. // exp7 performs x^7 mod p
  12. func exp7(a *ffg.Element) {
  13. a.Exp(*a, big.NewInt(7)) //nolint:gomnd
  14. }
  15. // exp7state perform exp7 for whole state
  16. func exp7state(state []*ffg.Element) {
  17. for i := 0; i < len(state); i++ {
  18. exp7(state[i])
  19. }
  20. }
  21. // ark computes Add-Round Key, from the paper https://eprint.iacr.org/2019/458.pdf
  22. func ark(state []*ffg.Element, it int) {
  23. for i := 0; i < len(state); i++ {
  24. state[i].Add(state[i], C[it+i])
  25. }
  26. }
  27. // mix returns [[matrix]] * [vector]
  28. func mix(state []*ffg.Element) []*ffg.Element {
  29. mul := zero()
  30. newState := make([]*ffg.Element, mLen)
  31. for i := 0; i < mLen; i++ {
  32. newState[i] = zero()
  33. }
  34. for i := 0; i < mLen; i++ {
  35. newState[i].SetUint64(0)
  36. for j := 0; j < mLen; j++ {
  37. mul.Mul(M[i][j], state[j])
  38. newState[i].Add(newState[i], mul)
  39. }
  40. }
  41. return newState
  42. }
  43. // Hash computes the Poseidon hash for the given inputs
  44. func Hash(inpBI [NROUNDSF]uint64, capBI [CAPLEN]uint64) ([CAPLEN]uint64, error) {
  45. state := make([]*ffg.Element, mLen)
  46. for i := 0; i < NROUNDSF; i++ {
  47. state[i] = ffg.NewElement().SetUint64(inpBI[i])
  48. }
  49. for i := 0; i < CAPLEN; i++ {
  50. state[i+NROUNDSF] = ffg.NewElement().SetUint64(capBI[i])
  51. }
  52. for r := 0; r < NROUNDSF+NROUNDSP; r++ {
  53. ark(state, r*mLen)
  54. if r < NROUNDSF/2 || r >= NROUNDSF/2+NROUNDSP {
  55. exp7state(state)
  56. } else {
  57. exp7(state[0])
  58. }
  59. state = mix(state)
  60. }
  61. return [CAPLEN]uint64{state[0].ToUint64Regular(), state[1].ToUint64Regular(), state[2].ToUint64Regular(), state[3].ToUint64Regular()}, nil
  62. }