github.com/consensys/gnark-crypto@v0.14.0/ecc/bls24-317/internal/fptower/e2.go (about) 1 // Copyright 2020 ConsenSys Software Inc. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package fptower 16 17 import ( 18 "math/big" 19 20 "github.com/consensys/gnark-crypto/ecc/bls24-317/fp" 21 ) 22 23 // E2 is a degree two finite field extension of fp.Element 24 type E2 struct { 25 A0, A1 fp.Element 26 } 27 28 // Equal returns true if z equals x, false otherwise 29 func (z *E2) Equal(x *E2) bool { 30 return z.A0.Equal(&x.A0) && z.A1.Equal(&x.A1) 31 } 32 33 // Cmp compares (lexicographic order) z and x and returns: 34 // 35 // -1 if z < x 36 // 0 if z == x 37 // +1 if z > x 38 func (z *E2) Cmp(x *E2) int { 39 if a1 := z.A1.Cmp(&x.A1); a1 != 0 { 40 return a1 41 } 42 return z.A0.Cmp(&x.A0) 43 } 44 45 // LexicographicallyLargest returns true if this element is strictly lexicographically 46 // larger than its negation, false otherwise 47 func (z *E2) LexicographicallyLargest() bool { 48 // adapted from github.com/zkcrypto/bls12_381 49 if z.A1.IsZero() { 50 return z.A0.LexicographicallyLargest() 51 } 52 return z.A1.LexicographicallyLargest() 53 } 54 55 // SetString sets a E2 element from strings 56 func (z *E2) SetString(s1, s2 string) *E2 { 57 z.A0.SetString(s1) 58 z.A1.SetString(s2) 59 return z 60 } 61 62 // SetZero sets an E2 elmt to zero 63 func (z *E2) SetZero() *E2 { 64 z.A0.SetZero() 65 z.A1.SetZero() 66 return z 67 } 68 69 // Set sets an E2 from x 70 func (z *E2) Set(x *E2) *E2 { 71 z.A0 = x.A0 72 z.A1 = x.A1 73 return z 74 } 75 76 // SetOne sets z to 1 in Montgomery form and returns z 77 func (z *E2) SetOne() *E2 { 78 z.A0.SetOne() 79 z.A1.SetZero() 80 return z 81 } 82 83 // SetRandom sets a0 and a1 to random values 84 func (z *E2) SetRandom() (*E2, error) { 85 if _, err := z.A0.SetRandom(); err != nil { 86 return nil, err 87 } 88 if _, err := z.A1.SetRandom(); err != nil { 89 return nil, err 90 } 91 return z, nil 92 } 93 94 // IsZero returns true if z is zero, false otherwise 95 func (z *E2) IsZero() bool { 96 return z.A0.IsZero() && z.A1.IsZero() 97 } 98 99 // IsOne returns true if z is one, false otherwise 100 func (z *E2) IsOne() bool { 101 return z.A0.IsOne() && z.A1.IsZero() 102 } 103 104 // Add adds two elements of E2 105 func (z *E2) Add(x, y *E2) *E2 { 106 addE2(z, x, y) 107 return z 108 } 109 110 // Sub subtracts two elements of E2 111 func (z *E2) Sub(x, y *E2) *E2 { 112 subE2(z, x, y) 113 return z 114 } 115 116 // Double doubles an E2 element 117 func (z *E2) Double(x *E2) *E2 { 118 doubleE2(z, x) 119 return z 120 } 121 122 // Neg negates an E2 element 123 func (z *E2) Neg(x *E2) *E2 { 124 negE2(z, x) 125 return z 126 } 127 128 // String implements Stringer interface for fancy printing 129 func (z *E2) String() string { 130 return (z.A0.String() + "+" + z.A1.String() + "*u") 131 } 132 133 // MulByElement multiplies an element in E2 by an element in fp 134 func (z *E2) MulByElement(x *E2, y *fp.Element) *E2 { 135 var yCopy fp.Element 136 yCopy.Set(y) 137 z.A0.Mul(&x.A0, &yCopy) 138 z.A1.Mul(&x.A1, &yCopy) 139 return z 140 } 141 142 // Conjugate conjugates an element in E2 143 func (z *E2) Conjugate(x *E2) *E2 { 144 z.A0 = x.A0 145 z.A1.Neg(&x.A1) 146 return z 147 } 148 149 // Legendre returns the Legendre symbol of z 150 func (z *E2) Legendre() int { 151 var n fp.Element 152 z.norm(&n) 153 return n.Legendre() 154 } 155 156 // Exp sets z=xᵏ (mod q²) and returns it 157 func (z *E2) Exp(x E2, k *big.Int) *E2 { 158 if k.IsUint64() && k.Uint64() == 0 { 159 return z.SetOne() 160 } 161 162 e := k 163 if k.Sign() == -1 { 164 // negative k, we invert 165 // if k < 0: xᵏ (mod q²) == (x⁻¹)ᵏ (mod q²) 166 x.Inverse(&x) 167 168 // we negate k in a temp big.Int since 169 // Int.Bit(_) of k and -k is different 170 e = bigIntPool.Get().(*big.Int) 171 defer bigIntPool.Put(e) 172 e.Neg(k) 173 } 174 175 z.SetOne() 176 b := e.Bytes() 177 for i := 0; i < len(b); i++ { 178 w := b[i] 179 for j := 0; j < 8; j++ { 180 z.Square(z) 181 if (w & (0b10000000 >> j)) != 0 { 182 z.Mul(z, &x) 183 } 184 } 185 } 186 187 return z 188 } 189 190 func init() { 191 q := fp.Modulus() 192 tmp := big.NewInt(3) 193 sqrtExp1.Set(q).Sub(&sqrtExp1, tmp).Rsh(&sqrtExp1, 2) 194 195 tmp.SetUint64(1) 196 sqrtExp2.Set(q).Sub(&sqrtExp2, tmp).Rsh(&sqrtExp2, 1) 197 } 198 199 var sqrtExp1, sqrtExp2 big.Int 200 201 // Sqrt sets z to the square root of and returns z 202 // The function does not test whether the square root 203 // exists or not, it's up to the caller to call 204 // Legendre beforehand. 205 // cf https://eprint.iacr.org/2012/685.pdf (algo 9) 206 func (z *E2) Sqrt(x *E2) *E2 { 207 208 var a1, alpha, b, x0, minusone E2 209 210 minusone.SetOne().Neg(&minusone) 211 212 a1.Exp(*x, &sqrtExp1) 213 alpha.Square(&a1). 214 Mul(&alpha, x) 215 x0.Mul(x, &a1) 216 if alpha.Equal(&minusone) { 217 var c fp.Element 218 c.Set(&x0.A0) 219 z.A0.Neg(&x0.A1) 220 z.A1.Set(&c) 221 return z 222 } 223 a1.SetOne() 224 b.Add(&a1, &alpha) 225 226 b.Exp(b, &sqrtExp2).Mul(&x0, &b) 227 z.Set(&b) 228 return z 229 } 230 231 // Select is conditional move. 232 // If cond = 0, it sets z to caseZ and returns it. otherwise caseNz. 233 func (z *E2) Select(cond int, caseZ *E2, caseNz *E2) *E2 { 234 //Might be able to save a nanosecond or two by an aggregate implementation 235 236 z.A0.Select(cond, &caseZ.A0, &caseNz.A0) 237 z.A1.Select(cond, &caseZ.A1, &caseNz.A1) 238 239 return z 240 } 241 242 // Div divides an element in E2 by an element in E2 243 func (z *E2) Div(x *E2, y *E2) *E2 { 244 var r E2 245 r.Inverse(y).Mul(x, &r) 246 return z.Set(&r) 247 }