github.com/aigarnetwork/aigar@v0.0.0-20191115204914-d59a6eb70f8e/crypto/bn256/cloudflare/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 // gfP2 implements a field of size p² as a quadratic extension of the base field 25 // where i²=-1. 26 type gfP2 struct { 27 x, y gfP // value is xi+y. 28 } 29 30 func gfP2Decode(in *gfP2) *gfP2 { 31 out := &gfP2{} 32 montDecode(&out.x, &in.x) 33 montDecode(&out.y, &in.y) 34 return out 35 } 36 37 func (e *gfP2) String() string { 38 return "(" + e.x.String() + ", " + e.y.String() + ")" 39 } 40 41 func (e *gfP2) Set(a *gfP2) *gfP2 { 42 e.x.Set(&a.x) 43 e.y.Set(&a.y) 44 return e 45 } 46 47 func (e *gfP2) SetZero() *gfP2 { 48 e.x = gfP{0} 49 e.y = gfP{0} 50 return e 51 } 52 53 func (e *gfP2) SetOne() *gfP2 { 54 e.x = gfP{0} 55 e.y = *newGFp(1) 56 return e 57 } 58 59 func (e *gfP2) IsZero() bool { 60 zero := gfP{0} 61 return e.x == zero && e.y == zero 62 } 63 64 func (e *gfP2) IsOne() bool { 65 zero, one := gfP{0}, *newGFp(1) 66 return e.x == zero && e.y == one 67 } 68 69 func (e *gfP2) Conjugate(a *gfP2) *gfP2 { 70 e.y.Set(&a.y) 71 gfpNeg(&e.x, &a.x) 72 return e 73 } 74 75 func (e *gfP2) Neg(a *gfP2) *gfP2 { 76 gfpNeg(&e.x, &a.x) 77 gfpNeg(&e.y, &a.y) 78 return e 79 } 80 81 func (e *gfP2) Add(a, b *gfP2) *gfP2 { 82 gfpAdd(&e.x, &a.x, &b.x) 83 gfpAdd(&e.y, &a.y, &b.y) 84 return e 85 } 86 87 func (e *gfP2) Sub(a, b *gfP2) *gfP2 { 88 gfpSub(&e.x, &a.x, &b.x) 89 gfpSub(&e.y, &a.y, &b.y) 90 return e 91 } 92 93 // See "Multiplication and Squaring in Pairing-Friendly Fields", 94 // http://eprint.iacr.org/2006/471.pdf 95 func (e *gfP2) Mul(a, b *gfP2) *gfP2 { 96 tx, t := &gfP{}, &gfP{} 97 gfpMul(tx, &a.x, &b.y) 98 gfpMul(t, &b.x, &a.y) 99 gfpAdd(tx, tx, t) 100 101 ty := &gfP{} 102 gfpMul(ty, &a.y, &b.y) 103 gfpMul(t, &a.x, &b.x) 104 gfpSub(ty, ty, t) 105 106 e.x.Set(tx) 107 e.y.Set(ty) 108 return e 109 } 110 111 func (e *gfP2) MulScalar(a *gfP2, b *gfP) *gfP2 { 112 gfpMul(&e.x, &a.x, b) 113 gfpMul(&e.y, &a.y, b) 114 return e 115 } 116 117 // MulXi sets e=ξa where ξ=i+9 and then returns e. 118 func (e *gfP2) MulXi(a *gfP2) *gfP2 { 119 // (xi+y)(i+9) = (9x+y)i+(9y-x) 120 tx := &gfP{} 121 gfpAdd(tx, &a.x, &a.x) 122 gfpAdd(tx, tx, tx) 123 gfpAdd(tx, tx, tx) 124 gfpAdd(tx, tx, &a.x) 125 126 gfpAdd(tx, tx, &a.y) 127 128 ty := &gfP{} 129 gfpAdd(ty, &a.y, &a.y) 130 gfpAdd(ty, ty, ty) 131 gfpAdd(ty, ty, ty) 132 gfpAdd(ty, ty, &a.y) 133 134 gfpSub(ty, ty, &a.x) 135 136 e.x.Set(tx) 137 e.y.Set(ty) 138 return e 139 } 140 141 func (e *gfP2) Square(a *gfP2) *gfP2 { 142 // Complex squaring algorithm: 143 // (xi+y)² = (x+y)(y-x) + 2*i*x*y 144 tx, ty := &gfP{}, &gfP{} 145 gfpSub(tx, &a.y, &a.x) 146 gfpAdd(ty, &a.x, &a.y) 147 gfpMul(ty, tx, ty) 148 149 gfpMul(tx, &a.x, &a.y) 150 gfpAdd(tx, tx, tx) 151 152 e.x.Set(tx) 153 e.y.Set(ty) 154 return e 155 } 156 157 func (e *gfP2) Invert(a *gfP2) *gfP2 { 158 // See "Implementing cryptographic pairings", M. Scott, section 3.2. 159 // ftp://136.206.11.249/pub/crypto/pairings.pdf 160 t1, t2 := &gfP{}, &gfP{} 161 gfpMul(t1, &a.x, &a.x) 162 gfpMul(t2, &a.y, &a.y) 163 gfpAdd(t1, t1, t2) 164 165 inv := &gfP{} 166 inv.Invert(t1) 167 168 gfpNeg(t1, &a.x) 169 170 gfpMul(&e.x, t1, inv) 171 gfpMul(&e.y, &a.y, inv) 172 return e 173 }