github.com/aigarnetwork/aigar@v0.0.0-20191115204914-d59a6eb70f8e/crypto/bn256/google/gfp12.go (about) 1 // Copyright 2018 The go-ethereum Authors 2 // Copyright 2019 The go-aigar Authors 3 // This file is part of the go-aigar library. 4 // 5 // The go-aigar library is free software: you can redistribute it and/or modify 6 // it under the terms of the GNU Lesser General Public License as published by 7 // the Free Software Foundation, either version 3 of the License, or 8 // (at your option) any later version. 9 // 10 // The go-aigar library is distributed in the hope that it will be useful, 11 // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 // GNU Lesser General Public License for more details. 14 // 15 // You should have received a copy of the GNU Lesser General Public License 16 // along with the go-aigar library. If not, see <http://www.gnu.org/licenses/>. 17 18 package bn256 19 20 // For details of the algorithms used, see "Multiplication and Squaring on 21 // Pairing-Friendly Fields, Devegili et al. 22 // http://eprint.iacr.org/2006/471.pdf. 23 24 import ( 25 "math/big" 26 ) 27 28 // gfP12 implements the field of size p¹² as a quadratic extension of gfP6 29 // where ω²=τ. 30 type gfP12 struct { 31 x, y *gfP6 // value is xω + y 32 } 33 34 func newGFp12(pool *bnPool) *gfP12 { 35 return &gfP12{newGFp6(pool), newGFp6(pool)} 36 } 37 38 func (e *gfP12) String() string { 39 return "(" + e.x.String() + "," + e.y.String() + ")" 40 } 41 42 func (e *gfP12) Put(pool *bnPool) { 43 e.x.Put(pool) 44 e.y.Put(pool) 45 } 46 47 func (e *gfP12) Set(a *gfP12) *gfP12 { 48 e.x.Set(a.x) 49 e.y.Set(a.y) 50 return e 51 } 52 53 func (e *gfP12) SetZero() *gfP12 { 54 e.x.SetZero() 55 e.y.SetZero() 56 return e 57 } 58 59 func (e *gfP12) SetOne() *gfP12 { 60 e.x.SetZero() 61 e.y.SetOne() 62 return e 63 } 64 65 func (e *gfP12) Minimal() { 66 e.x.Minimal() 67 e.y.Minimal() 68 } 69 70 func (e *gfP12) IsZero() bool { 71 e.Minimal() 72 return e.x.IsZero() && e.y.IsZero() 73 } 74 75 func (e *gfP12) IsOne() bool { 76 e.Minimal() 77 return e.x.IsZero() && e.y.IsOne() 78 } 79 80 func (e *gfP12) Conjugate(a *gfP12) *gfP12 { 81 e.x.Negative(a.x) 82 e.y.Set(a.y) 83 return a 84 } 85 86 func (e *gfP12) Negative(a *gfP12) *gfP12 { 87 e.x.Negative(a.x) 88 e.y.Negative(a.y) 89 return e 90 } 91 92 // Frobenius computes (xω+y)^p = x^p ω·ξ^((p-1)/6) + y^p 93 func (e *gfP12) Frobenius(a *gfP12, pool *bnPool) *gfP12 { 94 e.x.Frobenius(a.x, pool) 95 e.y.Frobenius(a.y, pool) 96 e.x.MulScalar(e.x, xiToPMinus1Over6, pool) 97 return e 98 } 99 100 // FrobeniusP2 computes (xω+y)^p² = x^p² ω·ξ^((p²-1)/6) + y^p² 101 func (e *gfP12) FrobeniusP2(a *gfP12, pool *bnPool) *gfP12 { 102 e.x.FrobeniusP2(a.x) 103 e.x.MulGFP(e.x, xiToPSquaredMinus1Over6) 104 e.y.FrobeniusP2(a.y) 105 return e 106 } 107 108 func (e *gfP12) Add(a, b *gfP12) *gfP12 { 109 e.x.Add(a.x, b.x) 110 e.y.Add(a.y, b.y) 111 return e 112 } 113 114 func (e *gfP12) Sub(a, b *gfP12) *gfP12 { 115 e.x.Sub(a.x, b.x) 116 e.y.Sub(a.y, b.y) 117 return e 118 } 119 120 func (e *gfP12) Mul(a, b *gfP12, pool *bnPool) *gfP12 { 121 tx := newGFp6(pool) 122 tx.Mul(a.x, b.y, pool) 123 t := newGFp6(pool) 124 t.Mul(b.x, a.y, pool) 125 tx.Add(tx, t) 126 127 ty := newGFp6(pool) 128 ty.Mul(a.y, b.y, pool) 129 t.Mul(a.x, b.x, pool) 130 t.MulTau(t, pool) 131 e.y.Add(ty, t) 132 e.x.Set(tx) 133 134 tx.Put(pool) 135 ty.Put(pool) 136 t.Put(pool) 137 return e 138 } 139 140 func (e *gfP12) MulScalar(a *gfP12, b *gfP6, pool *bnPool) *gfP12 { 141 e.x.Mul(e.x, b, pool) 142 e.y.Mul(e.y, b, pool) 143 return e 144 } 145 146 func (c *gfP12) Exp(a *gfP12, power *big.Int, pool *bnPool) *gfP12 { 147 sum := newGFp12(pool) 148 sum.SetOne() 149 t := newGFp12(pool) 150 151 for i := power.BitLen() - 1; i >= 0; i-- { 152 t.Square(sum, pool) 153 if power.Bit(i) != 0 { 154 sum.Mul(t, a, pool) 155 } else { 156 sum.Set(t) 157 } 158 } 159 160 c.Set(sum) 161 162 sum.Put(pool) 163 t.Put(pool) 164 165 return c 166 } 167 168 func (e *gfP12) Square(a *gfP12, pool *bnPool) *gfP12 { 169 // Complex squaring algorithm 170 v0 := newGFp6(pool) 171 v0.Mul(a.x, a.y, pool) 172 173 t := newGFp6(pool) 174 t.MulTau(a.x, pool) 175 t.Add(a.y, t) 176 ty := newGFp6(pool) 177 ty.Add(a.x, a.y) 178 ty.Mul(ty, t, pool) 179 ty.Sub(ty, v0) 180 t.MulTau(v0, pool) 181 ty.Sub(ty, t) 182 183 e.y.Set(ty) 184 e.x.Double(v0) 185 186 v0.Put(pool) 187 t.Put(pool) 188 ty.Put(pool) 189 190 return e 191 } 192 193 func (e *gfP12) Invert(a *gfP12, pool *bnPool) *gfP12 { 194 // See "Implementing cryptographic pairings", M. Scott, section 3.2. 195 // ftp://136.206.11.249/pub/crypto/pairings.pdf 196 t1 := newGFp6(pool) 197 t2 := newGFp6(pool) 198 199 t1.Square(a.x, pool) 200 t2.Square(a.y, pool) 201 t1.MulTau(t1, pool) 202 t1.Sub(t2, t1) 203 t2.Invert(t1, pool) 204 205 e.x.Negative(a.x) 206 e.y.Set(a.y) 207 e.MulScalar(e, t2, pool) 208 209 t1.Put(pool) 210 t2.Put(pool) 211 212 return e 213 }