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.

151 lines
3.2 KiB

  1. package fields
  2. import (
  3. "bytes"
  4. "math/big"
  5. )
  6. // Fq is the Z field over modulus Q
  7. type Fq struct {
  8. Q *big.Int // Q
  9. }
  10. // NewFq generates a new Fq
  11. func NewFq(q *big.Int) Fq {
  12. return Fq{
  13. q,
  14. }
  15. }
  16. // Zero returns a Zero value on the Fq
  17. func (fq Fq) Zero() *big.Int {
  18. return big.NewInt(int64(0))
  19. }
  20. // One returns a One value on the Fq
  21. func (fq Fq) One() *big.Int {
  22. return big.NewInt(int64(1))
  23. }
  24. // Add performs an addition on the Fq
  25. func (fq Fq) Add(a, b *big.Int) *big.Int {
  26. r := new(big.Int).Add(a, b)
  27. return new(big.Int).Mod(r, fq.Q)
  28. // return r
  29. }
  30. // Double performs a doubling on the Fq
  31. func (fq Fq) Double(a *big.Int) *big.Int {
  32. r := new(big.Int).Add(a, a)
  33. return new(big.Int).Mod(r, fq.Q)
  34. // return r
  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. // return r
  41. }
  42. // Neg performs a negation on the Fq
  43. func (fq Fq) Neg(a *big.Int) *big.Int {
  44. m := new(big.Int).Neg(a)
  45. return new(big.Int).Mod(m, fq.Q)
  46. // return m
  47. }
  48. // Mul performs a multiplication on the Fq
  49. func (fq Fq) Mul(a, b *big.Int) *big.Int {
  50. m := new(big.Int).Mul(a, b)
  51. return new(big.Int).Mod(m, fq.Q)
  52. // return m
  53. }
  54. func (fq Fq) MulScalar(base, e *big.Int) *big.Int {
  55. return fq.Mul(base, e)
  56. }
  57. // Inverse returns the inverse on the Fq
  58. func (fq Fq) Inverse(a *big.Int) *big.Int {
  59. return new(big.Int).ModInverse(a, fq.Q)
  60. // q := bigCopy(fq.Q)
  61. // t := big.NewInt(int64(0))
  62. // r := fq.Q
  63. // newt := big.NewInt(int64(0))
  64. // newr := fq.Affine(a)
  65. // for !bytes.Equal(newr.Bytes(), big.NewInt(int64(0)).Bytes()) {
  66. // q := new(big.Int).Div(bigCopy(r), bigCopy(newr))
  67. //
  68. // t = bigCopy(newt)
  69. // newt = fq.Sub(t, fq.Mul(q, newt))
  70. //
  71. // r = bigCopy(newr)
  72. // newr = fq.Sub(r, fq.Mul(q, newr))
  73. // }
  74. // if t.Cmp(big.NewInt(0)) == -1 { // t< 0
  75. // t = fq.Add(t, q)
  76. // }
  77. // return t
  78. }
  79. // Div performs the division over the finite field
  80. func (fq Fq) Div(a, b *big.Int) *big.Int {
  81. d := fq.Mul(a, fq.Inverse(b))
  82. return new(big.Int).Mod(d, fq.Q)
  83. }
  84. // Square performs a square operation on the Fq
  85. func (fq Fq) Square(a *big.Int) *big.Int {
  86. m := new(big.Int).Mul(a, a)
  87. return new(big.Int).Mod(m, fq.Q)
  88. }
  89. // Exp performs the exponential over Fq
  90. func (fq Fq) Exp(base *big.Int, e *big.Int) *big.Int {
  91. res := fq.One()
  92. rem := fq.Copy(e)
  93. exp := base
  94. for !bytes.Equal(rem.Bytes(), big.NewInt(int64(0)).Bytes()) {
  95. if BigIsOdd(rem) {
  96. res = fq.Mul(res, exp)
  97. }
  98. exp = fq.Square(exp)
  99. rem = new(big.Int).Rsh(rem, 1)
  100. }
  101. return res
  102. }
  103. func (fq Fq) IsZero(a *big.Int) bool {
  104. return bytes.Equal(a.Bytes(), fq.Zero().Bytes())
  105. }
  106. func (fq Fq) Copy(a *big.Int) *big.Int {
  107. return new(big.Int).SetBytes(a.Bytes())
  108. }
  109. func (fq Fq) Affine(a *big.Int) *big.Int {
  110. nq := fq.Neg(fq.Q)
  111. aux := a
  112. if aux.Cmp(big.NewInt(int64(0))) == -1 { // negative value
  113. if aux.Cmp(nq) != 1 { // aux less or equal nq
  114. aux = new(big.Int).Mod(aux, fq.Q)
  115. }
  116. if aux.Cmp(big.NewInt(int64(0))) == -1 { // negative value
  117. aux = new(big.Int).Add(aux, fq.Q)
  118. }
  119. } else {
  120. if aux.Cmp(fq.Q) != -1 { // aux greater or equal nq
  121. aux = new(big.Int).Mod(aux, fq.Q)
  122. }
  123. }
  124. return aux
  125. }
  126. func (fq Fq) Equal(a, b *big.Int) bool {
  127. aAff := fq.Affine(a)
  128. bAff := fq.Affine(b)
  129. return bytes.Equal(aAff.Bytes(), bAff.Bytes())
  130. }