From 1317fd01349a8a89311821fc3a6a10274a8ceba9 Mon Sep 17 00:00:00 2001 From: Sun Yimin Date: Thu, 15 Aug 2024 10:43:45 +0800 Subject: [PATCH] =?UTF-8?q?Updated=20High=E2=80=90assurance=20field=20inve?= =?UTF-8?q?rsion=20for=20curve=E2=80=90based=20cryptography=20(markdown)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...nversion-for-curve‐based-cryptography.md | 229 ++++++++++++++++++ 1 file changed, 229 insertions(+) diff --git a/High‐assurance-field-inversion-for-curve‐based-cryptography.md b/High‐assurance-field-inversion-for-curve‐based-cryptography.md index cc69fb8..bcc70f6 100644 --- a/High‐assurance-field-inversion-for-curve‐based-cryptography.md +++ b/High‐assurance-field-inversion-for-curve‐based-cryptography.md @@ -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)