github.com/ConsenSys/Quorum@v20.10.0+incompatible/crypto/bn256/cloudflare/gfp12.go (about) 1 package bn256 2 3 // For details of the algorithms used, see "Multiplication and Squaring on 4 // Pairing-Friendly Fields, Devegili et al. 5 // http://eprint.iacr.org/2006/471.pdf. 6 7 import ( 8 "math/big" 9 ) 10 11 // gfP12 implements the field of size p¹² as a quadratic extension of gfP6 12 // where ω²=τ. 13 type gfP12 struct { 14 x, y gfP6 // value is xω + y 15 } 16 17 func (e *gfP12) String() string { 18 return "(" + e.x.String() + "," + e.y.String() + ")" 19 } 20 21 func (e *gfP12) Set(a *gfP12) *gfP12 { 22 e.x.Set(&a.x) 23 e.y.Set(&a.y) 24 return e 25 } 26 27 func (e *gfP12) SetZero() *gfP12 { 28 e.x.SetZero() 29 e.y.SetZero() 30 return e 31 } 32 33 func (e *gfP12) SetOne() *gfP12 { 34 e.x.SetZero() 35 e.y.SetOne() 36 return e 37 } 38 39 func (e *gfP12) IsZero() bool { 40 return e.x.IsZero() && e.y.IsZero() 41 } 42 43 func (e *gfP12) IsOne() bool { 44 return e.x.IsZero() && e.y.IsOne() 45 } 46 47 func (e *gfP12) Conjugate(a *gfP12) *gfP12 { 48 e.x.Neg(&a.x) 49 e.y.Set(&a.y) 50 return e 51 } 52 53 func (e *gfP12) Neg(a *gfP12) *gfP12 { 54 e.x.Neg(&a.x) 55 e.y.Neg(&a.y) 56 return e 57 } 58 59 // Frobenius computes (xω+y)^p = x^p ω·ξ^((p-1)/6) + y^p 60 func (e *gfP12) Frobenius(a *gfP12) *gfP12 { 61 e.x.Frobenius(&a.x) 62 e.y.Frobenius(&a.y) 63 e.x.MulScalar(&e.x, xiToPMinus1Over6) 64 return e 65 } 66 67 // FrobeniusP2 computes (xω+y)^p² = x^p² ω·ξ^((p²-1)/6) + y^p² 68 func (e *gfP12) FrobeniusP2(a *gfP12) *gfP12 { 69 e.x.FrobeniusP2(&a.x) 70 e.x.MulGFP(&e.x, xiToPSquaredMinus1Over6) 71 e.y.FrobeniusP2(&a.y) 72 return e 73 } 74 75 func (e *gfP12) FrobeniusP4(a *gfP12) *gfP12 { 76 e.x.FrobeniusP4(&a.x) 77 e.x.MulGFP(&e.x, xiToPSquaredMinus1Over3) 78 e.y.FrobeniusP4(&a.y) 79 return e 80 } 81 82 func (e *gfP12) Add(a, b *gfP12) *gfP12 { 83 e.x.Add(&a.x, &b.x) 84 e.y.Add(&a.y, &b.y) 85 return e 86 } 87 88 func (e *gfP12) Sub(a, b *gfP12) *gfP12 { 89 e.x.Sub(&a.x, &b.x) 90 e.y.Sub(&a.y, &b.y) 91 return e 92 } 93 94 func (e *gfP12) Mul(a, b *gfP12) *gfP12 { 95 tx := (&gfP6{}).Mul(&a.x, &b.y) 96 t := (&gfP6{}).Mul(&b.x, &a.y) 97 tx.Add(tx, t) 98 99 ty := (&gfP6{}).Mul(&a.y, &b.y) 100 t.Mul(&a.x, &b.x).MulTau(t) 101 102 e.x.Set(tx) 103 e.y.Add(ty, t) 104 return e 105 } 106 107 func (e *gfP12) MulScalar(a *gfP12, b *gfP6) *gfP12 { 108 e.x.Mul(&e.x, b) 109 e.y.Mul(&e.y, b) 110 return e 111 } 112 113 func (c *gfP12) Exp(a *gfP12, power *big.Int) *gfP12 { 114 sum := (&gfP12{}).SetOne() 115 t := &gfP12{} 116 117 for i := power.BitLen() - 1; i >= 0; i-- { 118 t.Square(sum) 119 if power.Bit(i) != 0 { 120 sum.Mul(t, a) 121 } else { 122 sum.Set(t) 123 } 124 } 125 126 c.Set(sum) 127 return c 128 } 129 130 func (e *gfP12) Square(a *gfP12) *gfP12 { 131 // Complex squaring algorithm 132 v0 := (&gfP6{}).Mul(&a.x, &a.y) 133 134 t := (&gfP6{}).MulTau(&a.x) 135 t.Add(&a.y, t) 136 ty := (&gfP6{}).Add(&a.x, &a.y) 137 ty.Mul(ty, t).Sub(ty, v0) 138 t.MulTau(v0) 139 ty.Sub(ty, t) 140 141 e.x.Add(v0, v0) 142 e.y.Set(ty) 143 return e 144 } 145 146 func (e *gfP12) Invert(a *gfP12) *gfP12 { 147 // See "Implementing cryptographic pairings", M. Scott, section 3.2. 148 // ftp://136.206.11.249/pub/crypto/pairings.pdf 149 t1, t2 := &gfP6{}, &gfP6{} 150 151 t1.Square(&a.x) 152 t2.Square(&a.y) 153 t1.MulTau(t1).Sub(t2, t1) 154 t2.Invert(t1) 155 156 e.x.Neg(&a.x) 157 e.y.Set(&a.y) 158 e.MulScalar(e, t2) 159 return e 160 }