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.

171 lines
3.9 KiB

5 years ago
5 years ago
5 years ago
  1. package fields
  2. import (
  3. "bytes"
  4. "math/big"
  5. )
  6. // Fq12 uses the same algorithms than Fq2, but with [2][3][2]*big.Int data structure
  7. // Fq12 is Field 12
  8. type Fq12 struct {
  9. F Fq6
  10. Fq2 Fq2
  11. NonResidue [2]*big.Int
  12. }
  13. // NewFq12 generates a new Fq12
  14. func NewFq12(f Fq6, fq2 Fq2, nonResidue [2]*big.Int) Fq12 {
  15. fq12 := Fq12{
  16. f,
  17. fq2,
  18. nonResidue,
  19. }
  20. return fq12
  21. }
  22. // Zero returns a Zero value on the Fq12
  23. func (fq12 Fq12) Zero() [2][3][2]*big.Int {
  24. return [2][3][2]*big.Int{fq12.F.Zero(), fq12.F.Zero()}
  25. }
  26. // One returns a One value on the Fq12
  27. func (fq12 Fq12) One() [2][3][2]*big.Int {
  28. return [2][3][2]*big.Int{fq12.F.One(), fq12.F.Zero()}
  29. }
  30. func (fq12 Fq12) mulByNonResidue(a [3][2]*big.Int) [3][2]*big.Int {
  31. return [3][2]*big.Int{
  32. fq12.Fq2.Mul(fq12.NonResidue, a[2]),
  33. a[0],
  34. a[1],
  35. }
  36. }
  37. // Add performs an addition on the Fq12
  38. func (fq12 Fq12) Add(a, b [2][3][2]*big.Int) [2][3][2]*big.Int {
  39. return [2][3][2]*big.Int{
  40. fq12.F.Add(a[0], b[0]),
  41. fq12.F.Add(a[1], b[1]),
  42. }
  43. }
  44. // Double performs a doubling on the Fq12
  45. func (fq12 Fq12) Double(a [2][3][2]*big.Int) [2][3][2]*big.Int {
  46. return fq12.Add(a, a)
  47. }
  48. // Sub performs a subtraction on the Fq12
  49. func (fq12 Fq12) Sub(a, b [2][3][2]*big.Int) [2][3][2]*big.Int {
  50. return [2][3][2]*big.Int{
  51. fq12.F.Sub(a[0], b[0]),
  52. fq12.F.Sub(a[1], b[1]),
  53. }
  54. }
  55. // Neg performs a negation on the Fq12
  56. func (fq12 Fq12) Neg(a [2][3][2]*big.Int) [2][3][2]*big.Int {
  57. return fq12.Sub(fq12.Zero(), a)
  58. }
  59. // Mul performs a multiplication on the Fq12
  60. func (fq12 Fq12) Mul(a, b [2][3][2]*big.Int) [2][3][2]*big.Int {
  61. // Multiplication and Squaring on Pairing-Friendly .pdf; Section 3 (Karatsuba)
  62. v0 := fq12.F.Mul(a[0], b[0])
  63. v1 := fq12.F.Mul(a[1], b[1])
  64. return [2][3][2]*big.Int{
  65. fq12.F.Add(v0, fq12.mulByNonResidue(v1)),
  66. fq12.F.Sub(
  67. fq12.F.Mul(
  68. fq12.F.Add(a[0], a[1]),
  69. fq12.F.Add(b[0], b[1])),
  70. fq12.F.Add(v0, v1)),
  71. }
  72. }
  73. // MulScalar is ...
  74. func (fq12 Fq12) MulScalar(base [2][3][2]*big.Int, e *big.Int) [2][3][2]*big.Int {
  75. // for more possible implementations see g2.go file, at the function g2.MulScalar()
  76. res := fq12.Zero()
  77. rem := e
  78. exp := base
  79. for !bytes.Equal(rem.Bytes(), big.NewInt(int64(0)).Bytes()) {
  80. // if rem % 2 == 1
  81. if bytes.Equal(new(big.Int).Rem(rem, big.NewInt(int64(2))).Bytes(), big.NewInt(int64(1)).Bytes()) {
  82. res = fq12.Add(res, exp)
  83. }
  84. exp = fq12.Double(exp)
  85. rem = rem.Rsh(rem, 1) // rem = rem >> 1
  86. }
  87. return res
  88. }
  89. // Inverse returns the inverse on the Fq12
  90. func (fq12 Fq12) Inverse(a [2][3][2]*big.Int) [2][3][2]*big.Int {
  91. t0 := fq12.F.Square(a[0])
  92. t1 := fq12.F.Square(a[1])
  93. t2 := fq12.F.Sub(t0, fq12.mulByNonResidue(t1))
  94. t3 := fq12.F.Inverse(t2)
  95. return [2][3][2]*big.Int{
  96. fq12.F.Mul(a[0], t3),
  97. fq12.F.Neg(fq12.F.Mul(a[1], t3)),
  98. }
  99. }
  100. // Div performs a division on the Fq12
  101. func (fq12 Fq12) Div(a, b [2][3][2]*big.Int) [2][3][2]*big.Int {
  102. return fq12.Mul(a, fq12.Inverse(b))
  103. }
  104. // Square performs a square operation on the Fq12
  105. func (fq12 Fq12) Square(a [2][3][2]*big.Int) [2][3][2]*big.Int {
  106. ab := fq12.F.Mul(a[0], a[1])
  107. return [2][3][2]*big.Int{
  108. fq12.F.Sub(
  109. fq12.F.Mul(
  110. fq12.F.Add(a[0], a[1]),
  111. fq12.F.Add(
  112. a[0],
  113. fq12.mulByNonResidue(a[1]))),
  114. fq12.F.Add(
  115. ab,
  116. fq12.mulByNonResidue(ab))),
  117. fq12.F.Add(ab, ab),
  118. }
  119. }
  120. // Exp is ...
  121. func (fq12 Fq12) Exp(base [2][3][2]*big.Int, e *big.Int) [2][3][2]*big.Int {
  122. // TODO fix bottleneck
  123. res := fq12.One()
  124. rem := fq12.Fq2.F.Copy(e)
  125. exp := base
  126. // before := time.Now()
  127. for !bytes.Equal(rem.Bytes(), big.NewInt(int64(0)).Bytes()) {
  128. if BigIsOdd(rem) {
  129. res = fq12.Mul(res, exp)
  130. }
  131. exp = fq12.Square(exp)
  132. rem = new(big.Int).Rsh(rem, 1)
  133. }
  134. // fmt.Println("time elapsed:", time.Since(before))
  135. return res
  136. }
  137. // Affine is ...
  138. func (fq12 Fq12) Affine(a [2][3][2]*big.Int) [2][3][2]*big.Int {
  139. return [2][3][2]*big.Int{
  140. fq12.F.Affine(a[0]),
  141. fq12.F.Affine(a[1]),
  142. }
  143. }
  144. // Equal is ...
  145. func (fq12 Fq12) Equal(a, b [2][3][2]*big.Int) bool {
  146. return fq12.F.Equal(a[0], b[0]) && fq12.F.Equal(a[1], b[1])
  147. }