github.com/aigarnetwork/aigar@v0.0.0-20191115204914-d59a6eb70f8e/crypto/bn256/cloudflare/gfp.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 import ( 21 "errors" 22 "fmt" 23 ) 24 25 type gfP [4]uint64 26 27 func newGFp(x int64) (out *gfP) { 28 if x >= 0 { 29 out = &gfP{uint64(x)} 30 } else { 31 out = &gfP{uint64(-x)} 32 gfpNeg(out, out) 33 } 34 35 montEncode(out, out) 36 return out 37 } 38 39 func (e *gfP) String() string { 40 return fmt.Sprintf("%16.16x%16.16x%16.16x%16.16x", e[3], e[2], e[1], e[0]) 41 } 42 43 func (e *gfP) Set(f *gfP) { 44 e[0] = f[0] 45 e[1] = f[1] 46 e[2] = f[2] 47 e[3] = f[3] 48 } 49 50 func (e *gfP) Invert(f *gfP) { 51 bits := [4]uint64{0x3c208c16d87cfd45, 0x97816a916871ca8d, 0xb85045b68181585d, 0x30644e72e131a029} 52 53 sum, power := &gfP{}, &gfP{} 54 sum.Set(rN1) 55 power.Set(f) 56 57 for word := 0; word < 4; word++ { 58 for bit := uint(0); bit < 64; bit++ { 59 if (bits[word]>>bit)&1 == 1 { 60 gfpMul(sum, sum, power) 61 } 62 gfpMul(power, power, power) 63 } 64 } 65 66 gfpMul(sum, sum, r3) 67 e.Set(sum) 68 } 69 70 func (e *gfP) Marshal(out []byte) { 71 for w := uint(0); w < 4; w++ { 72 for b := uint(0); b < 8; b++ { 73 out[8*w+b] = byte(e[3-w] >> (56 - 8*b)) 74 } 75 } 76 } 77 78 func (e *gfP) Unmarshal(in []byte) error { 79 // Unmarshal the bytes into little endian form 80 for w := uint(0); w < 4; w++ { 81 for b := uint(0); b < 8; b++ { 82 e[3-w] += uint64(in[8*w+b]) << (56 - 8*b) 83 } 84 } 85 // Ensure the point respects the curve modulus 86 for i := 3; i >= 0; i-- { 87 if e[i] < p2[i] { 88 return nil 89 } 90 if e[i] > p2[i] { 91 return errors.New("bn256: coordinate exceeds modulus") 92 } 93 } 94 return errors.New("bn256: coordinate equals modulus") 95 } 96 97 func montEncode(c, a *gfP) { gfpMul(c, a, r2) } 98 func montDecode(c, a *gfP) { gfpMul(c, a, &gfP{1}) }