From 462637a7fb42c456a8e5a6b7cf8fd404848eb709 Mon Sep 17 00:00:00 2001 From: Emman Date: Wed, 3 Feb 2021 15:29:53 +0800 Subject: [PATCH] MAGIC - use corrected ali csr for test --- sm2/sm2.go | 41 +++++++++++++++++++++++++++++++++++++---- sm2/x509_test.go | 18 +++++++++++------- 2 files changed, 48 insertions(+), 11 deletions(-) diff --git a/sm2/sm2.go b/sm2/sm2.go index ae5118c..4a7b450 100644 --- a/sm2/sm2.go +++ b/sm2/sm2.go @@ -26,6 +26,17 @@ const ( mixed07 byte = 0x07 ) +// A invertible implements fast inverse mod Curve.Params().N +type invertible interface { + // Inverse returns the inverse of k in GF(P) + Inverse(k *big.Int) *big.Int +} + +// combinedMult implements fast multiplication S1*g + S2*p (g - generator, p - arbitrary point) +type combinedMult interface { + CombinedMult(bigX, bigY *big.Int, baseScalar, scalar []byte) (x, y *big.Int) +} + // PrivateKey represents an ECDSA private key. type PrivateKey struct { ecdsa.PrivateKey @@ -223,6 +234,16 @@ const ( var errZeroParam = errors.New("zero parameter") +// fermatInverse calculates the inverse of k in GF(P) using Fermat's method. +// This has better constant-time properties than Euclid's method (implemented +// in math/big.Int.ModInverse) although math/big itself isn't strictly +// constant-time so it's not perfect. +func fermatInverse(k, N *big.Int) *big.Int { + two := big.NewInt(2) + nMinus2 := new(big.Int).Sub(N, two) + return new(big.Int).Exp(k, nMinus2, N) +} + // Sign signs a hash (which should be the result of hashing a larger message) // using the private key, priv. If the hash is longer than the bit-length of the // private key's curve order, the hash will be truncated to that length. It @@ -295,7 +316,15 @@ func Sign(rand io.Reader, priv *ecdsa.PrivateKey, hash []byte) (r, s *big.Int, e s = new(big.Int).Mul(priv.D, r) s = new(big.Int).Sub(k, s) dp1 := new(big.Int).Add(priv.D, one) - dp1Inv := new(big.Int).ModInverse(dp1, N) + + var dp1Inv *big.Int + + if in, ok := priv.Curve.(invertible); ok { + dp1Inv = in.Inverse(dp1) + } else { + dp1Inv = fermatInverse(dp1, N) // N != 0 + } + s.Mul(s, dp1Inv) s.Mod(s, N) // N != 0 if s.Sign() != 0 { @@ -367,9 +396,13 @@ func Verify(pub *ecdsa.PublicKey, hash []byte, r, s *big.Int) bool { } var x *big.Int - x1, y1 := c.ScalarBaseMult(s.Bytes()) - x2, y2 := c.ScalarMult(pub.X, pub.Y, t.Bytes()) - x, _ = c.Add(x1, y1, x2, y2) + if opt, ok := c.(combinedMult); ok { + x, _ = opt.CombinedMult(pub.X, pub.Y, s.Bytes(), t.Bytes()) + } else { + x1, y1 := c.ScalarBaseMult(s.Bytes()) + x2, y2 := c.ScalarMult(pub.X, pub.Y, t.Bytes()) + x, _ = c.Add(x1, y1, x2, y2) + } x.Add(x, e) x.Mod(x, N) diff --git a/sm2/x509_test.go b/sm2/x509_test.go index fa5b704..c32e8c1 100644 --- a/sm2/x509_test.go +++ b/sm2/x509_test.go @@ -30,15 +30,16 @@ MFkwEwYHKoZIzj0CAQYIKoEcz1UBgi0DQgAERrsLH25zLm2LIo6tivZM9afLprSX const hashBase64 = `Zsfw9GLu7dnR8tRr3BDk4kFnxIdc8veiKX2gK49LqOA=` const signature = `MEUCIHV5hOCgYzlO4HkrUhct1Cc8BeKmbXNP+ASje5rGOcCYAiEA2XOajXo3/IihtCEJmNpImtWw3uHIy5CX5TIxit7V0gQ=` const csrFromAli = `-----BEGIN CERTIFICATE REQUEST----- -MIIBaTCCAQ8CAQAwRzELMAkGA1UEBhMCQ04xEzARBgNVBAMMCkNhcmdvU21hcnQx +MIIBYjCCAQkCAQAwRzELMAkGA1UEBhMCQ04xEzARBgNVBAMMCkNhcmdvU21hcnQx DzANBgNVBAcMBlpodWhhaTESMBAGA1UECAwJR3Vhbmdkb25nMFkwEwYHKoZIzj0C AQYIKoEcz1UBgi0DQgAERrsLH25zLm2LIo6tivZM9afLprSX6TCKAmQJArAO7VOt -ZyW4PQwfaTsUIF7IXEFG4iI8bNuTQwMykUzLu2ypEKBmMC4GCSqGSIb3DQEJDjEh -MB8wHQYDVR0OBBYEFA3FO8vT+8qZBfGZa2TRhLRbme+9MDQGCSqGSIb3DQEJDjEn -MCUwIwYDVR0RBBwwGoEYZW1tYW4uc3VuQGNhcmdvc21hcnQuY29tMAoGCCqBHM9V -AYN1A0gAMEUCIDFGOqXaAIBBc1vQNlCXx8QJcKb5C1+NT+Ij6lSbWCgwAiEAlDIk -PUbitEIHvhvdoOmNGzPDV1LgCwGD5OHVO9Kpy08= ------END CERTIFICATE REQUEST-----` +ZyW4PQwfaTsUIF7IXEFG4iI8bNuTQwMykUzLu2ypEKBgMC4GCSqGSIb3DQEJDjEh +MB8wHQYDVR0OBBYEFA3FO8vT+8qZBfGZa2TRhLRbme+9MC4GCSqGSIb3DQEJDjEh +MB8wHQYDVR0RBBYwFIESZW1tYW4uc3VuQGlxYXguY29tMAoGCCqBHM9VAYN1A0cA +MEQCIBQx6yv3rzfWCkKqDZQOfNKESQc6NtpQbeVvcxfBrciwAiAj78kkrF5R3g4l +bxIHjKZHc2sztHCXe7cseWGiLq0syg== +-----END CERTIFICATE REQUEST----- +` func getPublicKey(pemContent []byte) (interface{}, error) { block, _ := pem.Decode(pemContent) @@ -76,6 +77,9 @@ func TestCreateCertificateRequest(t *testing.T) { if err != nil { t.Fatal(err) } + block := &pem.Block{Bytes: csrblock, Type: "CERTIFICATE REQUEST"} + pemContent := string(pem.EncodeToMemory(block)) + fmt.Printf("%s\n", pemContent) err = parseAndCheckCsr(csrblock) if err != nil { t.Fatal(err)