github.com/ethw3/go-ethereuma@v0.0.0-20221013053120-c14602a4c23c/crypto/bn256/cloudflare/gfp6.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 // gfP6 implements the field of size p⁶ as a cubic extension of gfP2 where τ³=ξ 8 // and ξ=i+9. 9 type gfP6 struct { 10 x, y, z gfP2 // value is xτ² + yτ + z 11 } 12 13 func (e *gfP6) String() string { 14 return "(" + e.x.String() + ", " + e.y.String() + ", " + e.z.String() + ")" 15 } 16 17 func (e *gfP6) Set(a *gfP6) *gfP6 { 18 e.x.Set(&a.x) 19 e.y.Set(&a.y) 20 e.z.Set(&a.z) 21 return e 22 } 23 24 func (e *gfP6) SetZero() *gfP6 { 25 e.x.SetZero() 26 e.y.SetZero() 27 e.z.SetZero() 28 return e 29 } 30 31 func (e *gfP6) SetOne() *gfP6 { 32 e.x.SetZero() 33 e.y.SetZero() 34 e.z.SetOne() 35 return e 36 } 37 38 func (e *gfP6) IsZero() bool { 39 return e.x.IsZero() && e.y.IsZero() && e.z.IsZero() 40 } 41 42 func (e *gfP6) IsOne() bool { 43 return e.x.IsZero() && e.y.IsZero() && e.z.IsOne() 44 } 45 46 func (e *gfP6) Neg(a *gfP6) *gfP6 { 47 e.x.Neg(&a.x) 48 e.y.Neg(&a.y) 49 e.z.Neg(&a.z) 50 return e 51 } 52 53 func (e *gfP6) Frobenius(a *gfP6) *gfP6 { 54 e.x.Conjugate(&a.x) 55 e.y.Conjugate(&a.y) 56 e.z.Conjugate(&a.z) 57 58 e.x.Mul(&e.x, xiTo2PMinus2Over3) 59 e.y.Mul(&e.y, xiToPMinus1Over3) 60 return e 61 } 62 63 // FrobeniusP2 computes (xτ²+yτ+z)^(p²) = xτ^(2p²) + yτ^(p²) + z 64 func (e *gfP6) FrobeniusP2(a *gfP6) *gfP6 { 65 // τ^(2p²) = τ²τ^(2p²-2) = τ²ξ^((2p²-2)/3) 66 e.x.MulScalar(&a.x, xiTo2PSquaredMinus2Over3) 67 // τ^(p²) = ττ^(p²-1) = τξ^((p²-1)/3) 68 e.y.MulScalar(&a.y, xiToPSquaredMinus1Over3) 69 e.z.Set(&a.z) 70 return e 71 } 72 73 func (e *gfP6) FrobeniusP4(a *gfP6) *gfP6 { 74 e.x.MulScalar(&a.x, xiToPSquaredMinus1Over3) 75 e.y.MulScalar(&a.y, xiTo2PSquaredMinus2Over3) 76 e.z.Set(&a.z) 77 return e 78 } 79 80 func (e *gfP6) Add(a, b *gfP6) *gfP6 { 81 e.x.Add(&a.x, &b.x) 82 e.y.Add(&a.y, &b.y) 83 e.z.Add(&a.z, &b.z) 84 return e 85 } 86 87 func (e *gfP6) Sub(a, b *gfP6) *gfP6 { 88 e.x.Sub(&a.x, &b.x) 89 e.y.Sub(&a.y, &b.y) 90 e.z.Sub(&a.z, &b.z) 91 return e 92 } 93 94 func (e *gfP6) Mul(a, b *gfP6) *gfP6 { 95 // "Multiplication and Squaring on Pairing-Friendly Fields" 96 // Section 4, Karatsuba method. 97 // http://eprint.iacr.org/2006/471.pdf 98 v0 := (&gfP2{}).Mul(&a.z, &b.z) 99 v1 := (&gfP2{}).Mul(&a.y, &b.y) 100 v2 := (&gfP2{}).Mul(&a.x, &b.x) 101 102 t0 := (&gfP2{}).Add(&a.x, &a.y) 103 t1 := (&gfP2{}).Add(&b.x, &b.y) 104 tz := (&gfP2{}).Mul(t0, t1) 105 tz.Sub(tz, v1).Sub(tz, v2).MulXi(tz).Add(tz, v0) 106 107 t0.Add(&a.y, &a.z) 108 t1.Add(&b.y, &b.z) 109 ty := (&gfP2{}).Mul(t0, t1) 110 t0.MulXi(v2) 111 ty.Sub(ty, v0).Sub(ty, v1).Add(ty, t0) 112 113 t0.Add(&a.x, &a.z) 114 t1.Add(&b.x, &b.z) 115 tx := (&gfP2{}).Mul(t0, t1) 116 tx.Sub(tx, v0).Add(tx, v1).Sub(tx, v2) 117 118 e.x.Set(tx) 119 e.y.Set(ty) 120 e.z.Set(tz) 121 return e 122 } 123 124 func (e *gfP6) MulScalar(a *gfP6, b *gfP2) *gfP6 { 125 e.x.Mul(&a.x, b) 126 e.y.Mul(&a.y, b) 127 e.z.Mul(&a.z, b) 128 return e 129 } 130 131 func (e *gfP6) MulGFP(a *gfP6, b *gfP) *gfP6 { 132 e.x.MulScalar(&a.x, b) 133 e.y.MulScalar(&a.y, b) 134 e.z.MulScalar(&a.z, b) 135 return e 136 } 137 138 // MulTau computes τ·(aτ²+bτ+c) = bτ²+cτ+aξ 139 func (e *gfP6) MulTau(a *gfP6) *gfP6 { 140 tz := (&gfP2{}).MulXi(&a.x) 141 ty := (&gfP2{}).Set(&a.y) 142 143 e.y.Set(&a.z) 144 e.x.Set(ty) 145 e.z.Set(tz) 146 return e 147 } 148 149 func (e *gfP6) Square(a *gfP6) *gfP6 { 150 v0 := (&gfP2{}).Square(&a.z) 151 v1 := (&gfP2{}).Square(&a.y) 152 v2 := (&gfP2{}).Square(&a.x) 153 154 c0 := (&gfP2{}).Add(&a.x, &a.y) 155 c0.Square(c0).Sub(c0, v1).Sub(c0, v2).MulXi(c0).Add(c0, v0) 156 157 c1 := (&gfP2{}).Add(&a.y, &a.z) 158 c1.Square(c1).Sub(c1, v0).Sub(c1, v1) 159 xiV2 := (&gfP2{}).MulXi(v2) 160 c1.Add(c1, xiV2) 161 162 c2 := (&gfP2{}).Add(&a.x, &a.z) 163 c2.Square(c2).Sub(c2, v0).Add(c2, v1).Sub(c2, v2) 164 165 e.x.Set(c2) 166 e.y.Set(c1) 167 e.z.Set(c0) 168 return e 169 } 170 171 func (e *gfP6) Invert(a *gfP6) *gfP6 { 172 // See "Implementing cryptographic pairings", M. Scott, section 3.2. 173 // ftp://136.206.11.249/pub/crypto/pairings.pdf 174 175 // Here we can give a short explanation of how it works: let j be a cubic root of 176 // unity in GF(p²) so that 1+j+j²=0. 177 // Then (xτ² + yτ + z)(xj²τ² + yjτ + z)(xjτ² + yj²τ + z) 178 // = (xτ² + yτ + z)(Cτ²+Bτ+A) 179 // = (x³ξ²+y³ξ+z³-3ξxyz) = F is an element of the base field (the norm). 180 // 181 // On the other hand (xj²τ² + yjτ + z)(xjτ² + yj²τ + z) 182 // = τ²(y²-ξxz) + τ(ξx²-yz) + (z²-ξxy) 183 // 184 // So that's why A = (z²-ξxy), B = (ξx²-yz), C = (y²-ξxz) 185 t1 := (&gfP2{}).Mul(&a.x, &a.y) 186 t1.MulXi(t1) 187 188 A := (&gfP2{}).Square(&a.z) 189 A.Sub(A, t1) 190 191 B := (&gfP2{}).Square(&a.x) 192 B.MulXi(B) 193 t1.Mul(&a.y, &a.z) 194 B.Sub(B, t1) 195 196 C := (&gfP2{}).Square(&a.y) 197 t1.Mul(&a.x, &a.z) 198 C.Sub(C, t1) 199 200 F := (&gfP2{}).Mul(C, &a.y) 201 F.MulXi(F) 202 t1.Mul(A, &a.z) 203 F.Add(F, t1) 204 t1.Mul(B, &a.x).MulXi(t1) 205 F.Add(F, t1) 206 207 F.Invert(F) 208 209 e.x.Mul(C, F) 210 e.y.Mul(B, F) 211 e.z.Mul(A, F) 212 return e 213 }