github.com/emmansun/gmsm@v0.29.1/sm9/bn256/gfp.go (about) 1 package bn256 2 3 import ( 4 "encoding/binary" 5 "errors" 6 "fmt" 7 "math/big" 8 "math/bits" 9 ) 10 11 type gfP [4]uint64 12 13 var zero = newGFp(0) 14 var one = newGFp(1) 15 var two = newGFp(2) 16 17 func newGFp(x int64) (out *gfP) { 18 if x >= 0 { 19 out = &gfP{uint64(x)} 20 } else { 21 out = &gfP{uint64(-x)} 22 gfpNeg(out, out) 23 } 24 25 montEncode(out, out) 26 return out 27 } 28 29 func fromBigInt(x *big.Int) (out *gfP) { 30 out = &gfP{} 31 var a *big.Int 32 if x.Sign() >= 0 { 33 a = x 34 } else { 35 a = new(big.Int).Neg(x) 36 } 37 bytes := a.Bytes() 38 if len(bytes) > 32 { 39 panic("sm9: invalid byte length") 40 } else if len(bytes) < 32 { 41 fixedBytes := make([]byte, 32) 42 copy(fixedBytes[32-len(bytes):], bytes) 43 bytes = fixedBytes 44 } 45 for i := 0; i < 4; i++ { 46 start := len(bytes) - 8 47 out[i] = binary.BigEndian.Uint64(bytes[start:]) 48 bytes = bytes[:start] 49 } 50 if x.Sign() < 0 { 51 gfpNeg(out, out) 52 } 53 if x.Sign() != 0 { 54 montEncode(out, out) 55 } 56 return out 57 } 58 59 func (e *gfP) String() string { 60 return fmt.Sprintf("%16.16x%16.16x%16.16x%16.16x", e[3], e[2], e[1], e[0]) 61 } 62 63 func (e *gfP) Set(f *gfP) *gfP { 64 gfpCopy(e, f) 65 return e 66 } 67 68 func (e *gfP) exp(f *gfP, bits [4]uint64) { 69 sum, power := &gfP{}, &gfP{} 70 sum.Set(rN1) 71 power.Set(f) 72 73 for word := 0; word < 4; word++ { 74 for bit := uint(0); bit < 64; bit++ { 75 if (bits[word]>>bit)&1 == 1 { 76 gfpMul(sum, sum, power) 77 } 78 gfpSqr(power, power, 1) 79 } 80 } 81 82 gfpMul(sum, sum, r3) 83 e.Set(sum) 84 } 85 86 func (e *gfP) Mul(a, b *gfP) *gfP { 87 gfpMul(e, a, b) 88 return e 89 } 90 91 func (e *gfP) Square(a *gfP, n int) *gfP { 92 gfpSqr(e, a, n) 93 return e 94 } 95 96 // Equal returns 1 if e == t, and zero otherwise. 97 func (e *gfP) Equal(t *gfP) int { 98 var acc uint64 99 for i := range e { 100 acc |= e[i] ^ t[i] 101 } 102 return uint64IsZero(acc) 103 } 104 105 func (e *gfP) Sqrt(f *gfP) { 106 // Since p = 8k+5, 107 // Atkin algorithm 108 // https://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.896.6057&rep=rep1&type=pdf 109 // https://eprint.iacr.org/2012/685.pdf 110 // 111 a1, b, i := &gfP{}, &gfP{}, &gfP{} 112 sqrtCandidate(a1, f) 113 gfpMul(b, twoExpPMinus5Over8, a1) // b=ta1 114 gfpMul(a1, f, b) // a1=fb 115 gfpMul(i, two, a1) // i=2(fb) 116 gfpMul(i, i, b) // i=2(fb)b 117 gfpSub(i, i, one) // i=2(fb)b-1 118 gfpMul(i, a1, i) // i=(fb)(2(fb)b-1) 119 e.Set(i) 120 } 121 122 func (e *gfP) Marshal(out []byte) { 123 gfpMarshal((*[32]byte)(out), e) 124 } 125 126 // uint64IsZero returns 1 if x is zero and zero otherwise. 127 func uint64IsZero(x uint64) int { 128 x = ^x 129 x &= x >> 32 130 x &= x >> 16 131 x &= x >> 8 132 x &= x >> 4 133 x &= x >> 2 134 x &= x >> 1 135 return int(x & 1) 136 } 137 138 func lessThanP(x *gfP) int { 139 var b uint64 140 _, b = bits.Sub64(x[0], p2[0], b) 141 _, b = bits.Sub64(x[1], p2[1], b) 142 _, b = bits.Sub64(x[2], p2[2], b) 143 _, b = bits.Sub64(x[3], p2[3], b) 144 return int(b) 145 } 146 147 func (e *gfP) Unmarshal(in []byte) error { 148 gfpUnmarshal(e, (*[32]byte)(in)) 149 // Ensure the point respects the curve modulus 150 // TODO: Do we need to change it to constant time version ? 151 for i := 3; i >= 0; i-- { 152 if e[i] < p2[i] { 153 return nil 154 } 155 if e[i] > p2[i] { 156 return errors.New("sm9: coordinate exceeds modulus") 157 } 158 } 159 return errors.New("sm9: coordinate equals modulus") 160 } 161 162 func montEncode(c, a *gfP) { gfpMul(c, a, r2) } 163 func montDecode(c, a *gfP) { gfpFromMont(c, a) } 164 165 // cmovznzU64 is a single-word conditional move. 166 // 167 // Postconditions: 168 // 169 // out1 = (if arg1 = 0 then arg2 else arg3) 170 // 171 // Input Bounds: 172 // 173 // arg1: [0x0 ~> 0x1] 174 // arg2: [0x0 ~> 0xffffffffffffffff] 175 // arg3: [0x0 ~> 0xffffffffffffffff] 176 // 177 // Output Bounds: 178 // 179 // out1: [0x0 ~> 0xffffffffffffffff] 180 func cmovznzU64(out1 *uint64, arg1 uint64, arg2 uint64, arg3 uint64) { 181 x1 := (uint64(arg1) * 0xffffffffffffffff) 182 x2 := ((x1 & arg3) | ((^x1) & arg2)) 183 *out1 = x2 184 } 185 186 // Select sets e to p1 if cond == 1, and to p2 if cond == 0. 187 func (e *gfP) Select(p1, p2 *gfP, cond int) *gfP { 188 var x1 uint64 189 cmovznzU64(&x1, uint64(cond), p2[0], p1[0]) 190 var x2 uint64 191 cmovznzU64(&x2, uint64(cond), p2[1], p1[1]) 192 var x3 uint64 193 cmovznzU64(&x3, uint64(cond), p2[2], p1[2]) 194 var x4 uint64 195 cmovznzU64(&x4, uint64(cond), p2[3], p1[3]) 196 e[0] = x1 197 e[1] = x2 198 e[2] = x3 199 e[3] = x4 200 return e 201 }