github.com/nova-foundation/go-ethereum@v1.0.1/crypto/bls12381/fp12.go (about) 1 // Copyright 2020 The go-ethereum Authors 2 // This file is part of the go-ethereum library. 3 // 4 // The go-ethereum library is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU Lesser General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // The go-ethereum library is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU Lesser General Public License for more details. 13 // 14 // You should have received a copy of the GNU Lesser General Public License 15 // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>. 16 17 package bls12381 18 19 import ( 20 "errors" 21 "math/big" 22 ) 23 24 type fp12 struct { 25 fp12temp 26 fp6 *fp6 27 } 28 29 type fp12temp struct { 30 t2 [9]*fe2 31 t6 [5]*fe6 32 t12 *fe12 33 } 34 35 func newFp12Temp() fp12temp { 36 t2 := [9]*fe2{} 37 t6 := [5]*fe6{} 38 for i := 0; i < len(t2); i++ { 39 t2[i] = &fe2{} 40 } 41 for i := 0; i < len(t6); i++ { 42 t6[i] = &fe6{} 43 } 44 return fp12temp{t2, t6, &fe12{}} 45 } 46 47 func newFp12(fp6 *fp6) *fp12 { 48 t := newFp12Temp() 49 if fp6 == nil { 50 return &fp12{t, newFp6(nil)} 51 } 52 return &fp12{t, fp6} 53 } 54 55 func (e *fp12) fp2() *fp2 { 56 return e.fp6.fp2 57 } 58 59 func (e *fp12) fromBytes(in []byte) (*fe12, error) { 60 if len(in) != 576 { 61 return nil, errors.New("input string should be larger than 96 bytes") 62 } 63 fp6 := e.fp6 64 c1, err := fp6.fromBytes(in[:288]) 65 if err != nil { 66 return nil, err 67 } 68 c0, err := fp6.fromBytes(in[288:]) 69 if err != nil { 70 return nil, err 71 } 72 return &fe12{*c0, *c1}, nil 73 } 74 75 func (e *fp12) toBytes(a *fe12) []byte { 76 fp6 := e.fp6 77 out := make([]byte, 576) 78 copy(out[:288], fp6.toBytes(&a[1])) 79 copy(out[288:], fp6.toBytes(&a[0])) 80 return out 81 } 82 83 func (e *fp12) new() *fe12 { 84 return new(fe12) 85 } 86 87 func (e *fp12) zero() *fe12 { 88 return new(fe12) 89 } 90 91 func (e *fp12) one() *fe12 { 92 return new(fe12).one() 93 } 94 95 func (e *fp12) add(c, a, b *fe12) { 96 fp6 := e.fp6 97 fp6.add(&c[0], &a[0], &b[0]) 98 fp6.add(&c[1], &a[1], &b[1]) 99 } 100 101 func (e *fp12) double(c, a *fe12) { 102 fp6 := e.fp6 103 fp6.double(&c[0], &a[0]) 104 fp6.double(&c[1], &a[1]) 105 } 106 107 func (e *fp12) sub(c, a, b *fe12) { 108 fp6 := e.fp6 109 fp6.sub(&c[0], &a[0], &b[0]) 110 fp6.sub(&c[1], &a[1], &b[1]) 111 } 112 113 func (e *fp12) neg(c, a *fe12) { 114 fp6 := e.fp6 115 fp6.neg(&c[0], &a[0]) 116 fp6.neg(&c[1], &a[1]) 117 } 118 119 func (e *fp12) conjugate(c, a *fe12) { 120 fp6 := e.fp6 121 c[0].set(&a[0]) 122 fp6.neg(&c[1], &a[1]) 123 } 124 125 func (e *fp12) square(c, a *fe12) { 126 fp6, t := e.fp6, e.t6 127 fp6.add(t[0], &a[0], &a[1]) 128 fp6.mul(t[2], &a[0], &a[1]) 129 fp6.mulByNonResidue(t[1], &a[1]) 130 fp6.addAssign(t[1], &a[0]) 131 fp6.mulByNonResidue(t[3], t[2]) 132 fp6.mulAssign(t[0], t[1]) 133 fp6.subAssign(t[0], t[2]) 134 fp6.sub(&c[0], t[0], t[3]) 135 fp6.double(&c[1], t[2]) 136 } 137 138 func (e *fp12) cyclotomicSquare(c, a *fe12) { 139 t, fp2 := e.t2, e.fp2() 140 e.fp4Square(t[3], t[4], &a[0][0], &a[1][1]) 141 fp2.sub(t[2], t[3], &a[0][0]) 142 fp2.doubleAssign(t[2]) 143 fp2.add(&c[0][0], t[2], t[3]) 144 fp2.add(t[2], t[4], &a[1][1]) 145 fp2.doubleAssign(t[2]) 146 fp2.add(&c[1][1], t[2], t[4]) 147 e.fp4Square(t[3], t[4], &a[1][0], &a[0][2]) 148 e.fp4Square(t[5], t[6], &a[0][1], &a[1][2]) 149 fp2.sub(t[2], t[3], &a[0][1]) 150 fp2.doubleAssign(t[2]) 151 fp2.add(&c[0][1], t[2], t[3]) 152 fp2.add(t[2], t[4], &a[1][2]) 153 fp2.doubleAssign(t[2]) 154 fp2.add(&c[1][2], t[2], t[4]) 155 fp2.mulByNonResidue(t[3], t[6]) 156 fp2.add(t[2], t[3], &a[1][0]) 157 fp2.doubleAssign(t[2]) 158 fp2.add(&c[1][0], t[2], t[3]) 159 fp2.sub(t[2], t[5], &a[0][2]) 160 fp2.doubleAssign(t[2]) 161 fp2.add(&c[0][2], t[2], t[5]) 162 } 163 164 func (e *fp12) mul(c, a, b *fe12) { 165 t, fp6 := e.t6, e.fp6 166 fp6.mul(t[1], &a[0], &b[0]) 167 fp6.mul(t[2], &a[1], &b[1]) 168 fp6.add(t[0], t[1], t[2]) 169 fp6.mulByNonResidue(t[2], t[2]) 170 fp6.add(t[3], t[1], t[2]) 171 fp6.add(t[1], &a[0], &a[1]) 172 fp6.add(t[2], &b[0], &b[1]) 173 fp6.mulAssign(t[1], t[2]) 174 c[0].set(t[3]) 175 fp6.sub(&c[1], t[1], t[0]) 176 } 177 178 func (e *fp12) mulAssign(a, b *fe12) { 179 t, fp6 := e.t6, e.fp6 180 fp6.mul(t[1], &a[0], &b[0]) 181 fp6.mul(t[2], &a[1], &b[1]) 182 fp6.add(t[0], t[1], t[2]) 183 fp6.mulByNonResidue(t[2], t[2]) 184 fp6.add(t[3], t[1], t[2]) 185 fp6.add(t[1], &a[0], &a[1]) 186 fp6.add(t[2], &b[0], &b[1]) 187 fp6.mulAssign(t[1], t[2]) 188 a[0].set(t[3]) 189 fp6.sub(&a[1], t[1], t[0]) 190 } 191 192 func (e *fp12) fp4Square(c0, c1, a0, a1 *fe2) { 193 t, fp2 := e.t2, e.fp2() 194 fp2.square(t[0], a0) 195 fp2.square(t[1], a1) 196 fp2.mulByNonResidue(t[2], t[1]) 197 fp2.add(c0, t[2], t[0]) 198 fp2.add(t[2], a0, a1) 199 fp2.squareAssign(t[2]) 200 fp2.subAssign(t[2], t[0]) 201 fp2.sub(c1, t[2], t[1]) 202 } 203 204 func (e *fp12) inverse(c, a *fe12) { 205 fp6, t := e.fp6, e.t6 206 fp6.square(t[0], &a[0]) 207 fp6.square(t[1], &a[1]) 208 fp6.mulByNonResidue(t[1], t[1]) 209 fp6.sub(t[1], t[0], t[1]) 210 fp6.inverse(t[0], t[1]) 211 fp6.mul(&c[0], &a[0], t[0]) 212 fp6.mulAssign(t[0], &a[1]) 213 fp6.neg(&c[1], t[0]) 214 } 215 216 func (e *fp12) mulBy014Assign(a *fe12, c0, c1, c4 *fe2) { 217 fp2, fp6, t, t2 := e.fp2(), e.fp6, e.t6, e.t2[0] 218 fp6.mulBy01(t[0], &a[0], c0, c1) 219 fp6.mulBy1(t[1], &a[1], c4) 220 fp2.add(t2, c1, c4) 221 fp6.add(t[2], &a[1], &a[0]) 222 fp6.mulBy01Assign(t[2], c0, t2) 223 fp6.subAssign(t[2], t[0]) 224 fp6.sub(&a[1], t[2], t[1]) 225 fp6.mulByNonResidue(t[1], t[1]) 226 fp6.add(&a[0], t[1], t[0]) 227 } 228 229 func (e *fp12) exp(c, a *fe12, s *big.Int) { 230 z := e.one() 231 for i := s.BitLen() - 1; i >= 0; i-- { 232 e.square(z, z) 233 if s.Bit(i) == 1 { 234 e.mul(z, z, a) 235 } 236 } 237 c.set(z) 238 } 239 240 func (e *fp12) cyclotomicExp(c, a *fe12, s *big.Int) { 241 z := e.one() 242 for i := s.BitLen() - 1; i >= 0; i-- { 243 e.cyclotomicSquare(z, z) 244 if s.Bit(i) == 1 { 245 e.mul(z, z, a) 246 } 247 } 248 c.set(z) 249 } 250 251 func (e *fp12) frobeniusMap(c, a *fe12, power uint) { 252 fp6 := e.fp6 253 fp6.frobeniusMap(&c[0], &a[0], power) 254 fp6.frobeniusMap(&c[1], &a[1], power) 255 switch power { 256 case 0: 257 return 258 case 6: 259 fp6.neg(&c[1], &c[1]) 260 default: 261 fp6.mulByBaseField(&c[1], &c[1], &frobeniusCoeffs12[power]) 262 } 263 } 264 265 func (e *fp12) frobeniusMapAssign(a *fe12, power uint) { 266 fp6 := e.fp6 267 fp6.frobeniusMapAssign(&a[0], power) 268 fp6.frobeniusMapAssign(&a[1], power) 269 switch power { 270 case 0: 271 return 272 case 6: 273 fp6.neg(&a[1], &a[1]) 274 default: 275 fp6.mulByBaseField(&a[1], &a[1], &frobeniusCoeffs12[power]) 276 } 277 }