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.

152 lines
3.3 KiB

  1. // code originally taken from https://github.com/arnaucube/go-snark (https://github.com/arnaucube/go-snark/blob/master/fields/fq.go), pasted here to ensure compatibility among future changes
  2. package field
  3. import (
  4. "bytes"
  5. "crypto/rand"
  6. "math/big"
  7. )
  8. // Fq is the Z field over modulus Q
  9. type Fq struct {
  10. Q *big.Int // Q
  11. }
  12. // NewFq generates a new Fq
  13. func NewFq(q *big.Int) Fq {
  14. return Fq{
  15. q,
  16. }
  17. }
  18. // Zero returns a Zero value on the Fq
  19. func (fq Fq) Zero() *big.Int {
  20. return big.NewInt(int64(0))
  21. }
  22. // One returns a One value on the Fq
  23. func (fq Fq) One() *big.Int {
  24. return big.NewInt(int64(1))
  25. }
  26. // Add performs an addition on the Fq
  27. func (fq Fq) Add(a, b *big.Int) *big.Int {
  28. r := new(big.Int).Add(a, b)
  29. return new(big.Int).Mod(r, fq.Q)
  30. }
  31. // Double performs a doubling on the Fq
  32. func (fq Fq) Double(a *big.Int) *big.Int {
  33. r := new(big.Int).Add(a, a)
  34. return new(big.Int).Mod(r, fq.Q)
  35. }
  36. // Sub performs a subtraction on the Fq
  37. func (fq Fq) Sub(a, b *big.Int) *big.Int {
  38. r := new(big.Int).Sub(a, b)
  39. return new(big.Int).Mod(r, fq.Q)
  40. }
  41. // Neg performs a negation on the Fq
  42. func (fq Fq) Neg(a *big.Int) *big.Int {
  43. m := new(big.Int).Neg(a)
  44. return new(big.Int).Mod(m, fq.Q)
  45. }
  46. // Mul performs a multiplication on the Fq
  47. func (fq Fq) Mul(a, b *big.Int) *big.Int {
  48. m := new(big.Int).Mul(a, b)
  49. return new(big.Int).Mod(m, fq.Q)
  50. }
  51. func (fq Fq) MulScalar(base, e *big.Int) *big.Int {
  52. return fq.Mul(base, e)
  53. }
  54. // Inverse returns the inverse on the Fq
  55. func (fq Fq) Inverse(a *big.Int) *big.Int {
  56. return new(big.Int).ModInverse(a, fq.Q)
  57. }
  58. // Div performs the division over the finite field
  59. func (fq Fq) Div(a, b *big.Int) *big.Int {
  60. d := fq.Mul(a, fq.Inverse(b))
  61. return new(big.Int).Mod(d, fq.Q)
  62. }
  63. // Square performs a square operation on the Fq
  64. func (fq Fq) Square(a *big.Int) *big.Int {
  65. m := new(big.Int).Mul(a, a)
  66. return new(big.Int).Mod(m, fq.Q)
  67. }
  68. // Exp performs the exponential over Fq
  69. func (fq Fq) Exp(base *big.Int, e *big.Int) *big.Int {
  70. res := fq.One()
  71. rem := fq.Copy(e)
  72. exp := base
  73. for !bytes.Equal(rem.Bytes(), big.NewInt(int64(0)).Bytes()) {
  74. if BigIsOdd(rem) {
  75. res = fq.Mul(res, exp)
  76. }
  77. exp = fq.Square(exp)
  78. rem = new(big.Int).Rsh(rem, 1)
  79. }
  80. return res
  81. }
  82. func (fq Fq) Rand() (*big.Int, error) {
  83. maxbits := fq.Q.BitLen()
  84. b := make([]byte, (maxbits/8)-1)
  85. _, err := rand.Read(b)
  86. if err != nil {
  87. return nil, err
  88. }
  89. r := new(big.Int).SetBytes(b)
  90. rq := new(big.Int).Mod(r, fq.Q)
  91. // r over q, nil
  92. return rq, nil
  93. }
  94. func (fq Fq) IsZero(a *big.Int) bool {
  95. return bytes.Equal(a.Bytes(), fq.Zero().Bytes())
  96. }
  97. func (fq Fq) Copy(a *big.Int) *big.Int {
  98. return new(big.Int).SetBytes(a.Bytes())
  99. }
  100. func (fq Fq) Affine(a *big.Int) *big.Int {
  101. nq := fq.Neg(fq.Q)
  102. aux := a
  103. if aux.Cmp(big.NewInt(int64(0))) == -1 { // negative value
  104. if aux.Cmp(nq) != 1 { // aux less or equal nq
  105. aux = new(big.Int).Mod(aux, fq.Q)
  106. }
  107. if aux.Cmp(big.NewInt(int64(0))) == -1 { // negative value
  108. aux = new(big.Int).Add(aux, fq.Q)
  109. }
  110. } else {
  111. if aux.Cmp(fq.Q) != -1 { // aux greater or equal nq
  112. aux = new(big.Int).Mod(aux, fq.Q)
  113. }
  114. }
  115. return aux
  116. }
  117. func (fq Fq) Equal(a, b *big.Int) bool {
  118. aAff := fq.Affine(a)
  119. bAff := fq.Affine(b)
  120. return bytes.Equal(aAff.Bytes(), bAff.Bytes())
  121. }
  122. func BigIsOdd(n *big.Int) bool {
  123. one := big.NewInt(int64(1))
  124. and := new(big.Int).And(n, one)
  125. return bytes.Equal(and.Bytes(), big.NewInt(int64(1)).Bytes())
  126. }