github.com/aigarnetwork/aigar@v0.0.0-20191115204914-d59a6eb70f8e/crypto/bn256/google/gfp2.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 // gfP2 implements a field of size p² as a quadratic extension of the base 29 // field where i²=-1. 30 type gfP2 struct { 31 x, y *big.Int // value is xi+y. 32 } 33 34 func newGFp2(pool *bnPool) *gfP2 { 35 return &gfP2{pool.Get(), pool.Get()} 36 } 37 38 func (e *gfP2) String() string { 39 x := new(big.Int).Mod(e.x, P) 40 y := new(big.Int).Mod(e.y, P) 41 return "(" + x.String() + "," + y.String() + ")" 42 } 43 44 func (e *gfP2) Put(pool *bnPool) { 45 pool.Put(e.x) 46 pool.Put(e.y) 47 } 48 49 func (e *gfP2) Set(a *gfP2) *gfP2 { 50 e.x.Set(a.x) 51 e.y.Set(a.y) 52 return e 53 } 54 55 func (e *gfP2) SetZero() *gfP2 { 56 e.x.SetInt64(0) 57 e.y.SetInt64(0) 58 return e 59 } 60 61 func (e *gfP2) SetOne() *gfP2 { 62 e.x.SetInt64(0) 63 e.y.SetInt64(1) 64 return e 65 } 66 67 func (e *gfP2) Minimal() { 68 if e.x.Sign() < 0 || e.x.Cmp(P) >= 0 { 69 e.x.Mod(e.x, P) 70 } 71 if e.y.Sign() < 0 || e.y.Cmp(P) >= 0 { 72 e.y.Mod(e.y, P) 73 } 74 } 75 76 func (e *gfP2) IsZero() bool { 77 return e.x.Sign() == 0 && e.y.Sign() == 0 78 } 79 80 func (e *gfP2) IsOne() bool { 81 if e.x.Sign() != 0 { 82 return false 83 } 84 words := e.y.Bits() 85 return len(words) == 1 && words[0] == 1 86 } 87 88 func (e *gfP2) Conjugate(a *gfP2) *gfP2 { 89 e.y.Set(a.y) 90 e.x.Neg(a.x) 91 return e 92 } 93 94 func (e *gfP2) Negative(a *gfP2) *gfP2 { 95 e.x.Neg(a.x) 96 e.y.Neg(a.y) 97 return e 98 } 99 100 func (e *gfP2) Add(a, b *gfP2) *gfP2 { 101 e.x.Add(a.x, b.x) 102 e.y.Add(a.y, b.y) 103 return e 104 } 105 106 func (e *gfP2) Sub(a, b *gfP2) *gfP2 { 107 e.x.Sub(a.x, b.x) 108 e.y.Sub(a.y, b.y) 109 return e 110 } 111 112 func (e *gfP2) Double(a *gfP2) *gfP2 { 113 e.x.Lsh(a.x, 1) 114 e.y.Lsh(a.y, 1) 115 return e 116 } 117 118 func (c *gfP2) Exp(a *gfP2, power *big.Int, pool *bnPool) *gfP2 { 119 sum := newGFp2(pool) 120 sum.SetOne() 121 t := newGFp2(pool) 122 123 for i := power.BitLen() - 1; i >= 0; i-- { 124 t.Square(sum, pool) 125 if power.Bit(i) != 0 { 126 sum.Mul(t, a, pool) 127 } else { 128 sum.Set(t) 129 } 130 } 131 132 c.Set(sum) 133 134 sum.Put(pool) 135 t.Put(pool) 136 137 return c 138 } 139 140 // See "Multiplication and Squaring in Pairing-Friendly Fields", 141 // http://eprint.iacr.org/2006/471.pdf 142 func (e *gfP2) Mul(a, b *gfP2, pool *bnPool) *gfP2 { 143 tx := pool.Get().Mul(a.x, b.y) 144 t := pool.Get().Mul(b.x, a.y) 145 tx.Add(tx, t) 146 tx.Mod(tx, P) 147 148 ty := pool.Get().Mul(a.y, b.y) 149 t.Mul(a.x, b.x) 150 ty.Sub(ty, t) 151 e.y.Mod(ty, P) 152 e.x.Set(tx) 153 154 pool.Put(tx) 155 pool.Put(ty) 156 pool.Put(t) 157 158 return e 159 } 160 161 func (e *gfP2) MulScalar(a *gfP2, b *big.Int) *gfP2 { 162 e.x.Mul(a.x, b) 163 e.y.Mul(a.y, b) 164 return e 165 } 166 167 // MulXi sets e=ξa where ξ=i+9 and then returns e. 168 func (e *gfP2) MulXi(a *gfP2, pool *bnPool) *gfP2 { 169 // (xi+y)(i+3) = (9x+y)i+(9y-x) 170 tx := pool.Get().Lsh(a.x, 3) 171 tx.Add(tx, a.x) 172 tx.Add(tx, a.y) 173 174 ty := pool.Get().Lsh(a.y, 3) 175 ty.Add(ty, a.y) 176 ty.Sub(ty, a.x) 177 178 e.x.Set(tx) 179 e.y.Set(ty) 180 181 pool.Put(tx) 182 pool.Put(ty) 183 184 return e 185 } 186 187 func (e *gfP2) Square(a *gfP2, pool *bnPool) *gfP2 { 188 // Complex squaring algorithm: 189 // (xi+b)² = (x+y)(y-x) + 2*i*x*y 190 t1 := pool.Get().Sub(a.y, a.x) 191 t2 := pool.Get().Add(a.x, a.y) 192 ty := pool.Get().Mul(t1, t2) 193 ty.Mod(ty, P) 194 195 t1.Mul(a.x, a.y) 196 t1.Lsh(t1, 1) 197 198 e.x.Mod(t1, P) 199 e.y.Set(ty) 200 201 pool.Put(t1) 202 pool.Put(t2) 203 pool.Put(ty) 204 205 return e 206 } 207 208 func (e *gfP2) Invert(a *gfP2, pool *bnPool) *gfP2 { 209 // See "Implementing cryptographic pairings", M. Scott, section 3.2. 210 // ftp://136.206.11.249/pub/crypto/pairings.pdf 211 t := pool.Get() 212 t.Mul(a.y, a.y) 213 t2 := pool.Get() 214 t2.Mul(a.x, a.x) 215 t.Add(t, t2) 216 217 inv := pool.Get() 218 inv.ModInverse(t, P) 219 220 e.x.Neg(a.x) 221 e.x.Mul(e.x, inv) 222 e.x.Mod(e.x, P) 223 224 e.y.Mul(a.y, inv) 225 e.y.Mod(e.y, P) 226 227 pool.Put(t) 228 pool.Put(t2) 229 pool.Put(inv) 230 231 return e 232 } 233 234 func (e *gfP2) Real() *big.Int { 235 return e.x 236 } 237 238 func (e *gfP2) Imag() *big.Int { 239 return e.y 240 }