github.com/emmansun/gmsm@v0.29.1/sm9/bn256/generate.go (about) 1 //go:build ignore 2 3 package main 4 5 import ( 6 "bytes" 7 "go/format" 8 "io" 9 "log" 10 "os" 11 "os/exec" 12 ) 13 14 // Running this generator requires addchain v0.4.0, which can be installed with 15 // 16 // go install github.com/mmcloughlin/addchain/cmd/addchain@v0.4.0 17 // 18 19 func generate(template, exp, element string) ([]byte, error) { 20 tmplAddchainFileInvert, err := os.CreateTemp("", "addchain-template") 21 if err != nil { 22 return nil, err 23 } 24 defer os.Remove(tmplAddchainFileInvert.Name()) 25 if _, err := io.WriteString(tmplAddchainFileInvert, template); err != nil { 26 return nil, err 27 } 28 if err := tmplAddchainFileInvert.Close(); err != nil { 29 return nil, err 30 } 31 32 f, err := os.CreateTemp("", "addchain-gfp") 33 if err != nil { 34 return nil, err 35 } 36 defer os.Remove(f.Name()) 37 cmd := exec.Command("addchain", "search", exp) 38 cmd.Stderr = os.Stderr 39 cmd.Stdout = f 40 if err := cmd.Run(); err != nil { 41 return nil, err 42 } 43 if err := f.Close(); err != nil { 44 return nil, err 45 } 46 cmd = exec.Command("addchain", "gen", "-tmpl", tmplAddchainFileInvert.Name(), f.Name()) 47 cmd.Stderr = os.Stderr 48 out, err := cmd.Output() 49 if err != nil { 50 return nil, err 51 } 52 out = bytes.Replace(out, []byte("Element"), []byte(element), -1) 53 return format.Source(out) 54 } 55 56 func writeFile(fileName string, buffers ...[]byte) error { 57 log.Printf("Generating %v...", fileName) 58 f, err := os.Create(fileName) 59 if err != nil { 60 log.Fatal(err) 61 } 62 defer f.Close() 63 for _, buffer := range buffers { 64 if _, err := f.Write(buffer); err != nil { 65 return err 66 } 67 } 68 return nil 69 } 70 71 func main() { 72 out, err := generate(tmplAddchainInvert, "0xb640000002a3a6f1d603ab4ff58ec74521f2934b1a7aeedbe56f9b27e351457b", "gfP") 73 if err != nil { 74 log.Fatal(err) 75 } 76 out1, err := generate(tmplAddchainSqrt, "0x16c80000005474de3ac07569feb1d8e8a43e5269634f5ddb7cadf364fc6a28af", "gfP") 77 if err != nil { 78 log.Fatal(err) 79 } 80 if err = writeFile("gfp_invert_sqrt.go", out, out1); err != nil { 81 log.Fatal(err) 82 } 83 84 out, err = generate(tmplAddchainExp1, "0x2d90000000a8e9bc7580ead3fd63b1d1487ca4d2c69ebbb6f95be6c9f8d4515f", "gfP2") 85 if err != nil { 86 log.Fatal(err) 87 } 88 out1, err = generate(tmplAddchainExp2, "0xb640000002a3a6f1d603ab4ff58ec74521f2934b1a7aeedbe56f9b27e351457d", "gfP2") 89 if err != nil { 90 log.Fatal(err) 91 } 92 out2, err := generate(tmplAddchainExp3, "0x5b2000000151d378eb01d5a7fac763a290f949a58d3d776df2b7cd93f1a8a2be", "gfP2") 93 if err != nil { 94 log.Fatal(err) 95 } 96 if err = writeFile("gfp2_sqrt.go", out, out1, out2); err != nil { 97 log.Fatal(err) 98 } 99 100 out, err = generate(tmplAddchainExp12, "0x600000000058f98a", "gfP12") 101 if err != nil { 102 log.Fatal(err) 103 } 104 if err = writeFile("gfp12_exp_u.go", out); err != nil { 105 log.Fatal(err) 106 } 107 } 108 109 const tmplAddchainExp1 = `// Code generated by {{ .Meta.Name }}. DO NOT EDIT. 110 package bn256 111 112 func (e *Element) expPMinus1Over4(x *Element) *Element { 113 // The sequence of {{ .Ops.Adds }} multiplications and {{ .Ops.Doubles }} squarings is derived from the 114 // following addition chain generated with {{ .Meta.Module }} {{ .Meta.ReleaseTag }}. 115 // 116 {{- range lines (format .Script) }} 117 // {{ . }} 118 {{- end }} 119 // 120 var z = new(Element).Set(e) 121 {{- range .Program.Temporaries }} 122 var {{ . }} = new(Element) 123 {{- end }} 124 {{ range $i := .Program.Instructions -}} 125 {{- with add $i.Op }} 126 {{ $i.Output }}.Mul({{ .X }}, {{ .Y }}) 127 {{- end -}} 128 {{- with double $i.Op }} 129 {{ $i.Output }}.Square({{ .X }}) 130 {{- end -}} 131 {{- with shift $i.Op -}} 132 {{- $first := 0 -}} 133 {{- if ne $i.Output.Identifier .X.Identifier }} 134 {{ $i.Output }}.Square({{ .X }}) 135 {{- $first = 1 -}} 136 {{- end }} 137 for s := {{ $first }}; s < {{ .S }}; s++ { 138 {{ $i.Output }}.Square({{ $i.Output }}) 139 } 140 {{- end -}} 141 {{- end }} 142 return e.Set(z) 143 } 144 ` 145 146 const tmplAddchainExp2 = ` 147 func (e *Element) expP(x *Element) *Element { 148 // The sequence of {{ .Ops.Adds }} multiplications and {{ .Ops.Doubles }} squarings is derived from the 149 // following addition chain generated with {{ .Meta.Module }} {{ .Meta.ReleaseTag }}. 150 // 151 {{- range lines (format .Script) }} 152 // {{ . }} 153 {{- end }} 154 // 155 var z = new(Element).Set(e) 156 {{- range .Program.Temporaries }} 157 var {{ . }} = new(Element) 158 {{- end }} 159 {{ range $i := .Program.Instructions -}} 160 {{- with add $i.Op }} 161 {{ $i.Output }}.Mul({{ .X }}, {{ .Y }}) 162 {{- end -}} 163 {{- with double $i.Op }} 164 {{ $i.Output }}.Square({{ .X }}) 165 {{- end -}} 166 {{- with shift $i.Op -}} 167 {{- $first := 0 -}} 168 {{- if ne $i.Output.Identifier .X.Identifier }} 169 {{ $i.Output }}.Square({{ .X }}) 170 {{- $first = 1 -}} 171 {{- end }} 172 for s := {{ $first }}; s < {{ .S }}; s++ { 173 {{ $i.Output }}.Square({{ $i.Output }}) 174 } 175 {{- end -}} 176 {{- end }} 177 return e.Set(z) 178 } 179 ` 180 181 const tmplAddchainExp3 = ` 182 func (e *Element) expPMinus1Over2(x *Element) *Element { 183 // The sequence of {{ .Ops.Adds }} multiplications and {{ .Ops.Doubles }} squarings is derived from the 184 // following addition chain generated with {{ .Meta.Module }} {{ .Meta.ReleaseTag }}. 185 // 186 {{- range lines (format .Script) }} 187 // {{ . }} 188 {{- end }} 189 // 190 var z = new(Element).Set(e) 191 {{- range .Program.Temporaries }} 192 var {{ . }} = new(Element) 193 {{- end }} 194 {{ range $i := .Program.Instructions -}} 195 {{- with add $i.Op }} 196 {{ $i.Output }}.Mul({{ .X }}, {{ .Y }}) 197 {{- end -}} 198 {{- with double $i.Op }} 199 {{ $i.Output }}.Square({{ .X }}) 200 {{- end -}} 201 {{- with shift $i.Op -}} 202 {{- $first := 0 -}} 203 {{- if ne $i.Output.Identifier .X.Identifier }} 204 {{ $i.Output }}.Square({{ .X }}) 205 {{- $first = 1 -}} 206 {{- end }} 207 for s := {{ $first }}; s < {{ .S }}; s++ { 208 {{ $i.Output }}.Square({{ $i.Output }}) 209 } 210 {{- end -}} 211 {{- end }} 212 return e.Set(z) 213 } 214 ` 215 216 const tmplAddchainInvert = `// Code generated by {{ .Meta.Name }}. DO NOT EDIT. 217 package bn256 218 // Invert sets e = 1/x, and returns e. 219 // 220 // If x == 0, Invert returns e = 0. 221 func (e *Element) Invert(x *Element) *Element { 222 // Inversion is implemented as exponentiation with exponent p − 2. 223 // The sequence of {{ .Ops.Adds }} multiplications and {{ .Ops.Doubles }} squarings is derived from the 224 // following addition chain generated with {{ .Meta.Module }} {{ .Meta.ReleaseTag }}. 225 // 226 {{- range lines (format .Script) }} 227 // {{ . }} 228 {{- end }} 229 // 230 var z = new(Element).Set(e) 231 {{- range .Program.Temporaries }} 232 var {{ . }} = new(Element) 233 {{- end }} 234 {{ range $i := .Program.Instructions -}} 235 {{- with add $i.Op }} 236 {{ $i.Output }}.Mul({{ .X }}, {{ .Y }}) 237 {{- end -}} 238 {{- with double $i.Op }} 239 {{ $i.Output }}.Square({{ .X }}) 240 {{- end -}} 241 {{- with shift $i.Op -}} 242 {{- $first := 0 -}} 243 {{- if ne $i.Output.Identifier .X.Identifier }} 244 {{ $i.Output }}.Square({{ .X }}) 245 {{- $first = 1 -}} 246 {{- end }} 247 for s := {{ $first }}; s < {{ .S }}; s++ { 248 {{ $i.Output }}.Square({{ $i.Output }}) 249 } 250 {{- end -}} 251 {{- end }} 252 return e.Set(z) 253 } 254 ` 255 256 const tmplAddchainSqrt = ` 257 // Sqrt sets e to a square root of x. If x is not a square, Sqrt returns 258 // false and e is unchanged. e and x can overlap. 259 func Sqrt(e, x *Element) (isSquare bool) { 260 candidate, b, i := &gfP{}, &gfP{}, &gfP{} 261 sqrtCandidate(candidate, x) 262 gfpMul(b, twoExpPMinus5Over8, candidate) // b=ta1 263 gfpMul(candidate, x, b) // a1=fb 264 gfpMul(i, two, candidate) // i=2(fb) 265 gfpMul(i, i, b) // i=2(fb)b 266 gfpSub(i, i, one) // i=2(fb)b-1 267 gfpMul(i, candidate, i) // i=(fb)(2(fb)b-1) 268 square := new(Element).Square(i) 269 if square.Equal(x) != 1 { 270 return false 271 } 272 e.Set(i) 273 return true 274 } 275 276 // sqrtCandidate sets z to a square root candidate for x. z and x must not overlap. 277 func sqrtCandidate(z, x *Element) { 278 // Since p = 8k+5, exponentiation by (p - 5) / 8 yields a square root candidate. 279 // 280 // The sequence of {{ .Ops.Adds }} multiplications and {{ .Ops.Doubles }} squarings is derived from the 281 // following addition chain generated with {{ .Meta.Module }} {{ .Meta.ReleaseTag }}. 282 // 283 {{- range lines (format .Script) }} 284 // {{ . }} 285 {{- end }} 286 // 287 {{- range .Program.Temporaries }} 288 var {{ . }} = new(Element) 289 {{- end }} 290 {{ range $i := .Program.Instructions -}} 291 {{- with add $i.Op }} 292 {{ $i.Output }}.Mul({{ .X }}, {{ .Y }}) 293 {{- end -}} 294 {{- with double $i.Op }} 295 {{ $i.Output }}.Square({{ .X }}) 296 {{- end -}} 297 {{- with shift $i.Op -}} 298 {{- $first := 0 -}} 299 {{- if ne $i.Output.Identifier .X.Identifier }} 300 {{ $i.Output }}.Square({{ .X }}) 301 {{- $first = 1 -}} 302 {{- end }} 303 for s := {{ $first }}; s < {{ .S }}; s++ { 304 {{ $i.Output }}.Square({{ $i.Output }}) 305 } 306 {{- end -}} 307 {{- end }} 308 } 309 ` 310 311 const tmplAddchainExp12 = `// Code generated by {{ .Meta.Name }}. DO NOT EDIT. 312 package bn256 313 314 func (e *Element) gfP12ExpU(x *Element) *Element { 315 // The sequence of {{ .Ops.Adds }} multiplications and {{ .Ops.Doubles }} squarings is derived from the 316 // following addition chain generated with {{ .Meta.Module }} {{ .Meta.ReleaseTag }}. 317 // 318 {{- range lines (format .Script) }} 319 // {{ . }} 320 {{- end }} 321 // 322 var z = new(Element).Set(e) 323 {{- range .Program.Temporaries }} 324 var {{ . }} = new(Element) 325 {{- end }} 326 {{ range $i := .Program.Instructions -}} 327 {{- with add $i.Op }} 328 {{ $i.Output }}.Mul({{ .X }}, {{ .Y }}) 329 {{- end -}} 330 {{- with double $i.Op }} 331 {{ $i.Output }}.Square({{ .X }}) 332 {{- end -}} 333 {{- with shift $i.Op -}} 334 {{- $first := 0 -}} 335 {{- if ne $i.Output.Identifier .X.Identifier }} 336 {{ $i.Output }}.Square({{ .X }}) 337 {{- $first = 1 -}} 338 {{- end }} 339 for s := {{ $first }}; s < {{ .S }}; s++ { 340 {{ $i.Output }}.Square({{ $i.Output }}) 341 } 342 {{- end -}} 343 {{- end }} 344 return e.Set(z) 345 } 346 `