|
| 1 | +// Copyright 2020 ConsenSys Software Inc. |
| 2 | +// |
| 3 | +// Licensed under the Apache License, Version 2.0 (the "License"); |
| 4 | +// you may not use this file except in compliance with the License. |
| 5 | +// You may obtain a copy of the License at |
| 6 | +// |
| 7 | +// http://www.apache.org/licenses/LICENSE-2.0 |
| 8 | +// |
| 9 | +// Unless required by applicable law or agreed to in writing, software |
| 10 | +// distributed under the License is distributed on an "AS IS" BASIS, |
| 11 | +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 12 | +// See the License for the specific language governing permissions and |
| 13 | +// limitations under the License. |
| 14 | + |
| 15 | +package fptower |
| 16 | + |
| 17 | +import ( |
| 18 | + "math/big" |
| 19 | +) |
| 20 | + |
| 21 | +// E12 is a degree three finite field extension of fp4 |
| 22 | +type E12 struct { |
| 23 | + C0, C1, C2 E4 |
| 24 | +} |
| 25 | + |
| 26 | +// Equal returns true if z equals x, fasle otherwise |
| 27 | +func (z *E12) Equal(x *E12) bool { |
| 28 | + return z.C0.Equal(&x.C0) && z.C1.Equal(&x.C1) && z.C2.Equal(&x.C2) |
| 29 | +} |
| 30 | + |
| 31 | +// String puts E12 elmt in string form |
| 32 | +func (z *E12) String() string { |
| 33 | + return (z.C0.String() + "+(" + z.C1.String() + ")*w+(" + z.C2.String() + ")*w**2") |
| 34 | +} |
| 35 | + |
| 36 | +// SetString sets a E12 elmt from stringf |
| 37 | +func (z *E12) SetString(s0, s1, s2, s3, s4, s5, s6, s7, s8, s9, s10, s11 string) *E12 { |
| 38 | + z.C0.SetString(s0, s1, s2, s3) |
| 39 | + z.C1.SetString(s4, s5, s6, s7) |
| 40 | + z.C2.SetString(s8, s9, s10, s11) |
| 41 | + return z |
| 42 | +} |
| 43 | + |
| 44 | +// Set Sets a E12 elmt form another E12 elmt |
| 45 | +func (z *E12) Set(x *E12) *E12 { |
| 46 | + z.C0 = x.C0 |
| 47 | + z.C1 = x.C1 |
| 48 | + z.C2 = x.C2 |
| 49 | + return z |
| 50 | +} |
| 51 | + |
| 52 | +// SetOne sets z to 1 in Montgomery form and returns z |
| 53 | +func (z *E12) SetOne() *E12 { |
| 54 | + *z = E12{} |
| 55 | + z.C0.B0.A0.SetOne() |
| 56 | + return z |
| 57 | +} |
| 58 | + |
| 59 | +// SetRandom set z to a random elmt |
| 60 | +func (z *E12) SetRandom() (*E12, error) { |
| 61 | + if _, err := z.C0.SetRandom(); err != nil { |
| 62 | + return nil, err |
| 63 | + } |
| 64 | + if _, err := z.C1.SetRandom(); err != nil { |
| 65 | + return nil, err |
| 66 | + } |
| 67 | + if _, err := z.C2.SetRandom(); err != nil { |
| 68 | + return nil, err |
| 69 | + } |
| 70 | + return z, nil |
| 71 | +} |
| 72 | + |
| 73 | +// ToMont converts to Mont form |
| 74 | +func (z *E12) ToMont() *E12 { |
| 75 | + z.C0.ToMont() |
| 76 | + z.C1.ToMont() |
| 77 | + z.C2.ToMont() |
| 78 | + return z |
| 79 | +} |
| 80 | + |
| 81 | +// FromMont converts from Mont form |
| 82 | +func (z *E12) FromMont() *E12 { |
| 83 | + z.C0.FromMont() |
| 84 | + z.C1.FromMont() |
| 85 | + z.C2.FromMont() |
| 86 | + return z |
| 87 | +} |
| 88 | + |
| 89 | +// Add adds two elements of E12 |
| 90 | +func (z *E12) Add(x, y *E12) *E12 { |
| 91 | + z.C0.Add(&x.C0, &y.C0) |
| 92 | + z.C1.Add(&x.C1, &y.C1) |
| 93 | + z.C2.Add(&x.C2, &y.C2) |
| 94 | + return z |
| 95 | +} |
| 96 | + |
| 97 | +// Neg negates the E12 number |
| 98 | +func (z *E12) Neg(x *E12) *E12 { |
| 99 | + z.C0.Neg(&x.C0) |
| 100 | + z.C1.Neg(&x.C1) |
| 101 | + z.C2.Neg(&x.C2) |
| 102 | + return z |
| 103 | +} |
| 104 | + |
| 105 | +// Sub two elements of E12 |
| 106 | +func (z *E12) Sub(x, y *E12) *E12 { |
| 107 | + z.C0.Sub(&x.C0, &y.C0) |
| 108 | + z.C1.Sub(&x.C1, &y.C1) |
| 109 | + z.C2.Sub(&x.C2, &y.C2) |
| 110 | + return z |
| 111 | +} |
| 112 | + |
| 113 | +// Double doubles an element in E12 |
| 114 | +func (z *E12) Double(x *E12) *E12 { |
| 115 | + z.C0.Double(&x.C0) |
| 116 | + z.C1.Double(&x.C1) |
| 117 | + z.C2.Double(&x.C2) |
| 118 | + return z |
| 119 | +} |
| 120 | + |
| 121 | +// MulByNonResidue mul x by (0,1,0) |
| 122 | +func (z *E12) MulByNonResidue(x *E12) *E12 { |
| 123 | + z.C2, z.C1, z.C0 = x.C1, x.C0, x.C2 |
| 124 | + z.C0.MulByNonResidue(&z.C0) |
| 125 | + return z |
| 126 | +} |
| 127 | + |
| 128 | +// Mul sets z to the E12 product of x,y, returns z |
| 129 | +func (z *E12) Mul(x, y *E12) *E12 { |
| 130 | + // Algorithm 13 from https://eprint.iacr.org/2010/354.pdf |
| 131 | + var t0, t1, t2, c0, c1, c2, tmp E4 |
| 132 | + t0.Mul(&x.C0, &y.C0) |
| 133 | + t1.Mul(&x.C1, &y.C1) |
| 134 | + t2.Mul(&x.C2, &y.C2) |
| 135 | + |
| 136 | + c0.Add(&x.C1, &x.C2) |
| 137 | + tmp.Add(&y.C1, &y.C2) |
| 138 | + c0.Mul(&c0, &tmp).Sub(&c0, &t1).Sub(&c0, &t2).MulByNonResidue(&c0).Add(&c0, &t0) |
| 139 | + |
| 140 | + c1.Add(&x.C0, &x.C1) |
| 141 | + tmp.Add(&y.C0, &y.C1) |
| 142 | + c1.Mul(&c1, &tmp).Sub(&c1, &t0).Sub(&c1, &t1) |
| 143 | + tmp.MulByNonResidue(&t2) |
| 144 | + c1.Add(&c1, &tmp) |
| 145 | + |
| 146 | + tmp.Add(&x.C0, &x.C2) |
| 147 | + c2.Add(&y.C0, &y.C2).Mul(&c2, &tmp).Sub(&c2, &t0).Sub(&c2, &t2).Add(&c2, &t1) |
| 148 | + |
| 149 | + z.C0.Set(&c0) |
| 150 | + z.C1.Set(&c1) |
| 151 | + z.C2.Set(&c2) |
| 152 | + |
| 153 | + return z |
| 154 | +} |
| 155 | + |
| 156 | +// Square sets z to the E12 product of x,x, returns z |
| 157 | +func (z *E12) Square(x *E12) *E12 { |
| 158 | + |
| 159 | + // Algorithm 16 from https://eprint.iacr.org/2010/354.pdf |
| 160 | + var c4, c5, c1, c2, c3, c0 E4 |
| 161 | + c4.Mul(&x.C0, &x.C1).Double(&c4) |
| 162 | + c5.Square(&x.C2) |
| 163 | + c1.MulByNonResidue(&c5).Add(&c1, &c4) |
| 164 | + c2.Sub(&c4, &c5) |
| 165 | + c3.Square(&x.C0) |
| 166 | + c4.Sub(&x.C0, &x.C1).Add(&c4, &x.C2) |
| 167 | + c5.Mul(&x.C1, &x.C2).Double(&c5) |
| 168 | + c4.Square(&c4) |
| 169 | + c0.MulByNonResidue(&c5).Add(&c0, &c3) |
| 170 | + z.C2.Add(&c2, &c4).Add(&z.C2, &c5).Sub(&z.C2, &c3) |
| 171 | + z.C0.Set(&c0) |
| 172 | + z.C1.Set(&c1) |
| 173 | + |
| 174 | + return z |
| 175 | +} |
| 176 | + |
| 177 | +// Inverse an element in E12 |
| 178 | +func (z *E12) Inverse(x *E12) *E12 { |
| 179 | + // Algorithm 17 from https://eprint.iacr.org/2010/354.pdf |
| 180 | + // step 9 is wrong in the paper it's t1-t4 |
| 181 | + var t0, t1, t2, t3, t4, t5, t6, c0, c1, c2, d1, d2 E4 |
| 182 | + t0.Square(&x.C0) |
| 183 | + t1.Square(&x.C1) |
| 184 | + t2.Square(&x.C2) |
| 185 | + t3.Mul(&x.C0, &x.C1) |
| 186 | + t4.Mul(&x.C0, &x.C2) |
| 187 | + t5.Mul(&x.C1, &x.C2) |
| 188 | + c0.MulByNonResidue(&t5).Sub(&t0, &c0) |
| 189 | + c1.MulByNonResidue(&t2).Sub(&c1, &t3) |
| 190 | + c2.Sub(&t1, &t4) |
| 191 | + t6.Mul(&x.C0, &c0) |
| 192 | + d1.Mul(&x.C2, &c1) |
| 193 | + d2.Mul(&x.C1, &c2) |
| 194 | + d1.Add(&d1, &d2).MulByNonResidue(&d1) |
| 195 | + t6.Add(&t6, &d1) |
| 196 | + t6.Inverse(&t6) |
| 197 | + z.C0.Mul(&c0, &t6) |
| 198 | + z.C1.Mul(&c1, &t6) |
| 199 | + z.C2.Mul(&c2, &t6) |
| 200 | + |
| 201 | + return z |
| 202 | +} |
| 203 | + |
| 204 | +// Exp sets z=x**e and returns it |
| 205 | +func (z *E12) Exp(x *E12, e big.Int) *E12 { |
| 206 | + var res E12 |
| 207 | + res.SetOne() |
| 208 | + b := e.Bytes() |
| 209 | + for i := range b { |
| 210 | + w := b[i] |
| 211 | + mask := byte(0x80) |
| 212 | + for j := 7; j >= 0; j-- { |
| 213 | + res.Square(&res) |
| 214 | + if (w&mask)>>j != 0 { |
| 215 | + res.Mul(&res, x) |
| 216 | + } |
| 217 | + mask = mask >> 1 |
| 218 | + } |
| 219 | + } |
| 220 | + z.Set(&res) |
| 221 | + return z |
| 222 | +} |
| 223 | + |
| 224 | +// InverseUnitary inverse a unitary element |
| 225 | +func (z *E12) InverseUnitary(x *E12) *E12 { |
| 226 | + return z.Conjugate(x) |
| 227 | +} |
| 228 | + |
| 229 | +// Conjugate set z to x conjugated and return z |
| 230 | +func (z *E12) Conjugate(x *E12) *E12 { |
| 231 | + z.C0.Conjugate(&x.C0) |
| 232 | + z.C1.Conjugate(&x.C1).Neg(&z.C1) |
| 233 | + z.C2.Conjugate(&x.C2) |
| 234 | + return z |
| 235 | +} |
| 236 | + |
| 237 | +// MulBy01 multiplication by sparse element (c0,c1,0) |
| 238 | +func (z *E12) MulBy01(c0, c1 *E4) *E12 { |
| 239 | + |
| 240 | + var a, b, tmp, t0, t1, t2 E4 |
| 241 | + |
| 242 | + a.Mul(&z.C0, c0) |
| 243 | + b.Mul(&z.C1, c1) |
| 244 | + |
| 245 | + tmp.Add(&z.C1, &z.C2) |
| 246 | + t0.Mul(c1, &tmp) |
| 247 | + t0.Sub(&t0, &b) |
| 248 | + t0.MulByNonResidue(&t0) |
| 249 | + t0.Add(&t0, &a) |
| 250 | + |
| 251 | + tmp.Add(&z.C0, &z.C2) |
| 252 | + t2.Mul(c0, &tmp) |
| 253 | + t2.Sub(&t2, &a) |
| 254 | + t2.Add(&t2, &b) |
| 255 | + |
| 256 | + t1.Add(c0, c1) |
| 257 | + tmp.Add(&z.C0, &z.C1) |
| 258 | + t1.Mul(&t1, &tmp) |
| 259 | + t1.Sub(&t1, &a) |
| 260 | + t1.Sub(&t1, &b) |
| 261 | + |
| 262 | + z.C0.Set(&t0) |
| 263 | + z.C1.Set(&t1) |
| 264 | + z.C2.Set(&t2) |
| 265 | + |
| 266 | + return z |
| 267 | +} |
| 268 | + |
| 269 | +// MulByE2 multiplies an element in E12 by an element in E2 |
| 270 | +func (z *E12) MulByE2(x *E12, y *E4) *E12 { |
| 271 | + var yCopy E4 |
| 272 | + yCopy.Set(y) |
| 273 | + z.C0.Mul(&x.C0, &yCopy) |
| 274 | + z.C1.Mul(&x.C1, &yCopy) |
| 275 | + z.C2.Mul(&x.C2, &yCopy) |
| 276 | + return z |
| 277 | +} |
0 commit comments