github.com/consensys/gnark-crypto@v0.14.0/ecc/bls24-315/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-315/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 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 // Sqrt sets z to the square root of and returns z 191 // The function does not test whether the square root 192 // exists or not, it's up to the caller to call 193 // Legendre beforehand. 194 // cf https://eprint.iacr.org/2012/685.pdf (algo 10) 195 func (z *E2) Sqrt(x *E2) *E2 { 196 197 // precomputation 198 var b, c, d, e, f, x0 E2 199 var _b, o fp.Element 200 201 // c must be a non square (works for p=1 mod 12 hence 1 mod 4, only bls377 has such a p currently) 202 c.A1.SetOne() 203 204 q := fp.Modulus() 205 var exp, one big.Int 206 one.SetUint64(1) 207 exp.Set(q).Sub(&exp, &one).Rsh(&exp, 1) 208 d.Exp(c, &exp) 209 e.Mul(&d, &c).Inverse(&e) 210 f.Mul(&d, &c).Square(&f) 211 212 // computation 213 exp.Rsh(&exp, 1) 214 b.Exp(*x, &exp) 215 b.norm(&_b) 216 o.SetOne() 217 if _b.Equal(&o) { 218 x0.Square(&b).Mul(&x0, x) 219 _b.Set(&x0.A0).Sqrt(&_b) 220 z.Conjugate(&b).MulByElement(z, &_b) 221 return z 222 } 223 x0.Square(&b).Mul(&x0, x).Mul(&x0, &f) 224 _b.Set(&x0.A0).Sqrt(&_b) 225 z.Conjugate(&b).MulByElement(z, &_b).Mul(z, &e) 226 227 return z 228 } 229 230 func (z *E2) Div(x *E2, y *E2) *E2 { 231 var r E2 232 r.Inverse(y).Mul(x, &r) 233 return z.Set(&r) 234 }