github.com/snowblossomcoin/go-ethereum@v1.9.25/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 102 func (e *fp12) double(c, a *fe12) { 103 fp6 := e.fp6 104 fp6.double(&c[0], &a[0]) 105 fp6.double(&c[1], &a[1]) 106 } 107 108 func (e *fp12) sub(c, a, b *fe12) { 109 fp6 := e.fp6 110 fp6.sub(&c[0], &a[0], &b[0]) 111 fp6.sub(&c[1], &a[1], &b[1]) 112 113 } 114 115 func (e *fp12) neg(c, a *fe12) { 116 fp6 := e.fp6 117 fp6.neg(&c[0], &a[0]) 118 fp6.neg(&c[1], &a[1]) 119 } 120 121 func (e *fp12) conjugate(c, a *fe12) { 122 fp6 := e.fp6 123 c[0].set(&a[0]) 124 fp6.neg(&c[1], &a[1]) 125 } 126 127 func (e *fp12) square(c, a *fe12) { 128 fp6, t := e.fp6, e.t6 129 fp6.add(t[0], &a[0], &a[1]) 130 fp6.mul(t[2], &a[0], &a[1]) 131 fp6.mulByNonResidue(t[1], &a[1]) 132 fp6.addAssign(t[1], &a[0]) 133 fp6.mulByNonResidue(t[3], t[2]) 134 fp6.mulAssign(t[0], t[1]) 135 fp6.subAssign(t[0], t[2]) 136 fp6.sub(&c[0], t[0], t[3]) 137 fp6.double(&c[1], t[2]) 138 } 139 140 func (e *fp12) cyclotomicSquare(c, a *fe12) { 141 t, fp2 := e.t2, e.fp2() 142 e.fp4Square(t[3], t[4], &a[0][0], &a[1][1]) 143 fp2.sub(t[2], t[3], &a[0][0]) 144 fp2.doubleAssign(t[2]) 145 fp2.add(&c[0][0], t[2], t[3]) 146 fp2.add(t[2], t[4], &a[1][1]) 147 fp2.doubleAssign(t[2]) 148 fp2.add(&c[1][1], t[2], t[4]) 149 e.fp4Square(t[3], t[4], &a[1][0], &a[0][2]) 150 e.fp4Square(t[5], t[6], &a[0][1], &a[1][2]) 151 fp2.sub(t[2], t[3], &a[0][1]) 152 fp2.doubleAssign(t[2]) 153 fp2.add(&c[0][1], t[2], t[3]) 154 fp2.add(t[2], t[4], &a[1][2]) 155 fp2.doubleAssign(t[2]) 156 fp2.add(&c[1][2], t[2], t[4]) 157 fp2.mulByNonResidue(t[3], t[6]) 158 fp2.add(t[2], t[3], &a[1][0]) 159 fp2.doubleAssign(t[2]) 160 fp2.add(&c[1][0], t[2], t[3]) 161 fp2.sub(t[2], t[5], &a[0][2]) 162 fp2.doubleAssign(t[2]) 163 fp2.add(&c[0][2], t[2], t[5]) 164 } 165 166 func (e *fp12) mul(c, a, b *fe12) { 167 t, fp6 := e.t6, e.fp6 168 fp6.mul(t[1], &a[0], &b[0]) 169 fp6.mul(t[2], &a[1], &b[1]) 170 fp6.add(t[0], t[1], t[2]) 171 fp6.mulByNonResidue(t[2], t[2]) 172 fp6.add(t[3], t[1], t[2]) 173 fp6.add(t[1], &a[0], &a[1]) 174 fp6.add(t[2], &b[0], &b[1]) 175 fp6.mulAssign(t[1], t[2]) 176 c[0].set(t[3]) 177 fp6.sub(&c[1], t[1], t[0]) 178 } 179 180 func (e *fp12) mulAssign(a, b *fe12) { 181 t, fp6 := e.t6, e.fp6 182 fp6.mul(t[1], &a[0], &b[0]) 183 fp6.mul(t[2], &a[1], &b[1]) 184 fp6.add(t[0], t[1], t[2]) 185 fp6.mulByNonResidue(t[2], t[2]) 186 fp6.add(t[3], t[1], t[2]) 187 fp6.add(t[1], &a[0], &a[1]) 188 fp6.add(t[2], &b[0], &b[1]) 189 fp6.mulAssign(t[1], t[2]) 190 a[0].set(t[3]) 191 fp6.sub(&a[1], t[1], t[0]) 192 } 193 194 func (e *fp12) fp4Square(c0, c1, a0, a1 *fe2) { 195 t, fp2 := e.t2, e.fp2() 196 fp2.square(t[0], a0) 197 fp2.square(t[1], a1) 198 fp2.mulByNonResidue(t[2], t[1]) 199 fp2.add(c0, t[2], t[0]) 200 fp2.add(t[2], a0, a1) 201 fp2.squareAssign(t[2]) 202 fp2.subAssign(t[2], t[0]) 203 fp2.sub(c1, t[2], t[1]) 204 } 205 206 func (e *fp12) inverse(c, a *fe12) { 207 fp6, t := e.fp6, e.t6 208 fp6.square(t[0], &a[0]) 209 fp6.square(t[1], &a[1]) 210 fp6.mulByNonResidue(t[1], t[1]) 211 fp6.sub(t[1], t[0], t[1]) 212 fp6.inverse(t[0], t[1]) 213 fp6.mul(&c[0], &a[0], t[0]) 214 fp6.mulAssign(t[0], &a[1]) 215 fp6.neg(&c[1], t[0]) 216 } 217 218 func (e *fp12) mulBy014Assign(a *fe12, c0, c1, c4 *fe2) { 219 fp2, fp6, t, t2 := e.fp2(), e.fp6, e.t6, e.t2[0] 220 fp6.mulBy01(t[0], &a[0], c0, c1) 221 fp6.mulBy1(t[1], &a[1], c4) 222 fp2.add(t2, c1, c4) 223 fp6.add(t[2], &a[1], &a[0]) 224 fp6.mulBy01Assign(t[2], c0, t2) 225 fp6.subAssign(t[2], t[0]) 226 fp6.sub(&a[1], t[2], t[1]) 227 fp6.mulByNonResidue(t[1], t[1]) 228 fp6.add(&a[0], t[1], t[0]) 229 } 230 231 func (e *fp12) exp(c, a *fe12, s *big.Int) { 232 z := e.one() 233 for i := s.BitLen() - 1; i >= 0; i-- { 234 e.square(z, z) 235 if s.Bit(i) == 1 { 236 e.mul(z, z, a) 237 } 238 } 239 c.set(z) 240 } 241 242 func (e *fp12) cyclotomicExp(c, a *fe12, s *big.Int) { 243 z := e.one() 244 for i := s.BitLen() - 1; i >= 0; i-- { 245 e.cyclotomicSquare(z, z) 246 if s.Bit(i) == 1 { 247 e.mul(z, z, a) 248 } 249 } 250 c.set(z) 251 } 252 253 func (e *fp12) frobeniusMap(c, a *fe12, power uint) { 254 fp6 := e.fp6 255 fp6.frobeniusMap(&c[0], &a[0], power) 256 fp6.frobeniusMap(&c[1], &a[1], power) 257 switch power { 258 case 0: 259 return 260 case 6: 261 fp6.neg(&c[1], &c[1]) 262 default: 263 fp6.mulByBaseField(&c[1], &c[1], &frobeniusCoeffs12[power]) 264 } 265 } 266 267 func (e *fp12) frobeniusMapAssign(a *fe12, power uint) { 268 fp6 := e.fp6 269 fp6.frobeniusMapAssign(&a[0], power) 270 fp6.frobeniusMapAssign(&a[1], power) 271 switch power { 272 case 0: 273 return 274 case 6: 275 fp6.neg(&a[1], &a[1]) 276 default: 277 fp6.mulByBaseField(&a[1], &a[1], &frobeniusCoeffs12[power]) 278 } 279 }