mirror of
https://github.com/emmansun/gmsm.git
synced 2025-05-11 03:26:17 +08:00
Updated High‐assurance field inversion for curve‐based cryptography (markdown)
parent
541ee1c0df
commit
1317fd0134
@ -1,3 +1,232 @@
|
||||
# 尝试1
|
||||
使用**fiat-crypto**生成的代码,来事先模求逆:
|
||||
代码片段1是原有的通过**addchain**生成的模求逆:
|
||||
```go
|
||||
// Invert sets e = 1/x, and returns e.
|
||||
//
|
||||
// If x == 0, Invert returns e = 0.
|
||||
func (e *SM2P256Element) Invert(x *SM2P256Element) *SM2P256Element {
|
||||
// Inversion is implemented as exponentiation with exponent p − 2.
|
||||
// The sequence of 14 multiplications and 255 squarings is derived from the
|
||||
// following addition chain generated with github.com/mmcloughlin/addchain v0.4.0.
|
||||
//
|
||||
// _10 = 2*1
|
||||
// _11 = 1 + _10
|
||||
// _110 = 2*_11
|
||||
// _111 = 1 + _110
|
||||
// _111000 = _111 << 3
|
||||
// _111111 = _111 + _111000
|
||||
// _1111110 = 2*_111111
|
||||
// _1111111 = 1 + _1111110
|
||||
// x12 = _1111110 << 5 + _111111
|
||||
// x24 = x12 << 12 + x12
|
||||
// x31 = x24 << 7 + _1111111
|
||||
// i39 = x31 << 2
|
||||
// i68 = i39 << 29
|
||||
// x62 = x31 + i68
|
||||
// i71 = i68 << 2
|
||||
// x64 = i39 + i71 + _11
|
||||
// i265 = ((i71 << 32 + x64) << 64 + x64) << 94
|
||||
// return (x62 + i265) << 2 + 1
|
||||
//
|
||||
var z = new(SM2P256Element).Set(e)
|
||||
var t0 = new(SM2P256Element)
|
||||
var t1 = new(SM2P256Element)
|
||||
var t2 = new(SM2P256Element)
|
||||
|
||||
z.Square(x)
|
||||
t0.Mul(x, z)
|
||||
z.Square(t0)
|
||||
z.Mul(x, z)
|
||||
t1.Square(z)
|
||||
for s := 1; s < 3; s++ {
|
||||
t1.Square(t1)
|
||||
}
|
||||
t1.Mul(z, t1)
|
||||
t2.Square(t1)
|
||||
z.Mul(x, t2)
|
||||
for s := 0; s < 5; s++ {
|
||||
t2.Square(t2)
|
||||
}
|
||||
t1.Mul(t1, t2)
|
||||
t2.Square(t1)
|
||||
for s := 1; s < 12; s++ {
|
||||
t2.Square(t2)
|
||||
}
|
||||
t1.Mul(t1, t2)
|
||||
for s := 0; s < 7; s++ {
|
||||
t1.Square(t1)
|
||||
}
|
||||
z.Mul(z, t1)
|
||||
t2.Square(z)
|
||||
for s := 1; s < 2; s++ {
|
||||
t2.Square(t2)
|
||||
}
|
||||
t1.Square(t2)
|
||||
for s := 1; s < 29; s++ {
|
||||
t1.Square(t1)
|
||||
}
|
||||
z.Mul(z, t1)
|
||||
for s := 0; s < 2; s++ {
|
||||
t1.Square(t1)
|
||||
}
|
||||
t2.Mul(t2, t1)
|
||||
t0.Mul(t0, t2)
|
||||
for s := 0; s < 32; s++ {
|
||||
t1.Square(t1)
|
||||
}
|
||||
t1.Mul(t0, t1)
|
||||
for s := 0; s < 64; s++ {
|
||||
t1.Square(t1)
|
||||
}
|
||||
t0.Mul(t0, t1)
|
||||
for s := 0; s < 94; s++ {
|
||||
t0.Square(t0)
|
||||
}
|
||||
z.Mul(z, t0)
|
||||
for s := 0; s < 2; s++ {
|
||||
z.Square(z)
|
||||
}
|
||||
z.Mul(x, z)
|
||||
return e.Set(z)
|
||||
}
|
||||
```
|
||||
|
||||
代码片段2通过**safegcd**介绍的最基本方法模求逆:
|
||||
```go
|
||||
// Reference https://github.com/mit-plv/fiat-crypto/blob/master/inversion/c/inversion_template.c
|
||||
func P256Inverse(g *[4]uint64) *[4]uint64 {
|
||||
var precomp, v, out4, out5 [4]uint64
|
||||
var d, out1 uint64
|
||||
var f, out2, out3, gs [5]uint64
|
||||
var r sm2p256MontgomeryDomainFieldElement
|
||||
r1 := (*[4]uint64)(&r)
|
||||
sm2p256DivstepPrecomp(&precomp)
|
||||
sm2p256Msat(&f)
|
||||
sm2p256SetOne(&r)
|
||||
|
||||
for i := 0; i < 4; i++ {
|
||||
gs[i] = g[i]
|
||||
}
|
||||
|
||||
// 370 = (256 * 49 + 57) / 17 - 1
|
||||
for i := 0; i < 370; i++ {
|
||||
sm2p256Divstep(&out1, &out2, &out3, &out4, &out5, d, &f, &gs, &v, r1)
|
||||
sm2p256Divstep(&d, &f, &gs, &v, r1, out1, &out2, &out3, &out4, &out5)
|
||||
}
|
||||
|
||||
sm2p256Divstep(&out1, &out2, &out3, &out4, &out5, d, &f, &gs, &v, r1)
|
||||
for i := 0; i < 4; i++ {
|
||||
v[i] = out4[i]
|
||||
f[i] = out2[i]
|
||||
}
|
||||
f[4] = out2[4]
|
||||
|
||||
var out sm2p256MontgomeryDomainFieldElement
|
||||
sm2p256Opp(&out, (*sm2p256MontgomeryDomainFieldElement)(&v))
|
||||
sm2p256Selectznz(&v, (sm2p256Uint1)(f[4]>>63), &v, (*[4]uint64)(&out))
|
||||
|
||||
sm2p256Mul(&out, (*sm2p256MontgomeryDomainFieldElement)(&v), (*sm2p256MontgomeryDomainFieldElement)(&precomp))
|
||||
return (*[4]uint64)(&out)
|
||||
}
|
||||
```
|
||||
|
||||
以下是测试代码:
|
||||
```go
|
||||
package fiat
|
||||
|
||||
import (
|
||||
"encoding/hex"
|
||||
"testing"
|
||||
)
|
||||
|
||||
|
||||
var testValues = []string{
|
||||
"0000000000000000000000000000000000000000000000000000000000000001",
|
||||
"0000000000000000000000000000000000000000000000000000000000000002",
|
||||
"0000000000000000000000000000000000000000000000000000000000000003",
|
||||
"1000000000000000000000000000000000000000000000000000000000000000",
|
||||
"1000000000000000000000000000000000000000000000000000000000000001",
|
||||
"1000000000000000000000000000000000000000000000000000000000000002",
|
||||
"1000000000000000000000000000000000000000000000000000000000000003",
|
||||
"8356e642a40ebd18d29ba3532fbd9f3bbee8f027c3f6f39a5ba2f870369f9988",
|
||||
"981f5efe55d1c5cdf6c0ef2b070847a14f7fdf4272a8df09c442f3058af94ba1",
|
||||
"d6833540d019e0438a5dd73b414f26ab43d8064b99671206944e284dbd969093",
|
||||
"6c5a0a0b2eed3cbec3e4f1252bfe0e28c504a1c6bf1999eebb0af9ef0f8e6c85",
|
||||
}
|
||||
|
||||
func TestP256Inverse(t *testing.T) {
|
||||
for _, v := range testValues {
|
||||
vBytes, _ := hex.DecodeString(v)
|
||||
|
||||
in, err := new(SM2P256Element).SetBytes(vBytes)
|
||||
if err != nil {
|
||||
t.Errorf("SetBytes failed: %v", err)
|
||||
}
|
||||
in2 := *(*[4]uint64)(&in.x)
|
||||
out1 := new(SM2P256Element).Invert(in)
|
||||
out1r := (*[4]uint64)(&out1.x)
|
||||
out2 := P256Inverse(&in2)
|
||||
tmp := (*sm2p256NonMontgomeryDomainFieldElement)(out2)
|
||||
out3 := new(sm2p256MontgomeryDomainFieldElement)
|
||||
sm2p256ToMontgomery(out3, tmp)
|
||||
if *out3 != *out1r {
|
||||
t.Errorf("got %v, want %v", out3, &out1.x)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkP256Inverse(b *testing.B) {
|
||||
vBytes, _ := hex.DecodeString(testValues[0])
|
||||
|
||||
in, _ := new(SM2P256Element).SetBytes(vBytes)
|
||||
in2 := *(*[4]uint64)(&in.x)
|
||||
b.ReportAllocs()
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
P256Inverse(&in2)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkInvert(b *testing.B) {
|
||||
vBytes, _ := hex.DecodeString(testValues[0])
|
||||
|
||||
in, _ := new(SM2P256Element).SetBytes(vBytes)
|
||||
out := new(SM2P256Element)
|
||||
b.ReportAllocs()
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
out.Invert(in)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
1. 还有就是fiat-cyrpto目前的实现,输入、输出有些小问题:输入是蒙哥马利型,输出是非蒙哥马利型;输入是非蒙哥马利型,输出是蒙哥马利型。这个是已知问题。https://github.com/mit-plv/fiat-crypto/issues/1020
|
||||
```
|
||||
goos: windows
|
||||
goarch: amd64
|
||||
pkg: github.com/emmansun/gmsm/internal/sm2ec/fiat
|
||||
cpu: Intel(R) Core(TM) i5-9500 CPU @ 3.00GHz
|
||||
BenchmarkInvert
|
||||
BenchmarkInvert-6
|
||||
227496 5806 ns/op 0 B/op 0 allocs/op
|
||||
PASS
|
||||
ok github.com/emmansun/gmsm/internal/sm2ec/fiat 1.792s
|
||||
|
||||
goos: windows
|
||||
goarch: amd64
|
||||
pkg: github.com/emmansun/gmsm/internal/sm2ec/fiat
|
||||
cpu: Intel(R) Core(TM) i5-9500 CPU @ 3.00GHz
|
||||
BenchmarkP256Inverse
|
||||
BenchmarkP256Inverse-6
|
||||
58394 20644 ns/op 32 B/op 1 allocs/op
|
||||
PASS
|
||||
ok github.com/emmansun/gmsm/internal/sm2ec/fiat 1.793s
|
||||
```
|
||||
|
||||
2. 用devsteps2事先的模求逆并没有比经过addchain优化的模求逆方法性能好。
|
||||
|
||||
# Reference
|
||||
- [High-assurance field inversion for curve-based cryptography](https://eprint.iacr.org/2021/549.pdf)
|
||||
- [Fast constant-time gcd and modular inversion](https://gcd.cr.yp.to/papers.html#safegcd)
|
||||
|
Loading…
x
Reference in New Issue
Block a user