Skip to content

Commit

Permalink
完善 ECGDSA 标准测试
Browse files Browse the repository at this point in the history
  • Loading branch information
deatil committed Sep 1, 2024
1 parent 3cf8ae9 commit c107157
Show file tree
Hide file tree
Showing 15 changed files with 1,148 additions and 57 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ go-cryptobin 是 go 的常用加密解密库
* 对称加密解密模式(ECB/CBC/PCBC/CFB/NCFB/OFB/NOFB/CTR/GCM/CCM)
* 对称加密解密补码(NoPadding/ZeroPadding/PKCS5Padding/PKCS7Padding/X923Padding/ISO10126Padding/ISO97971Padding/ISO7816_4Padding/PBOC2Padding/TBCPadding/PKCS1Padding)
* 非对称加密解密(RSA/SM2/EIGamal)
* 非对称签名验证(RSA/RSA-PSS/DSA/ECDSA/EdDSA/SM2/EIGamal/ED448/Gost)
* 非对称签名验证(RSA/RSA-PSS/DSA/ECDSA/ECGDSA/EdDSA/SM2/EIGamal/ED448/Gost)
* 默认 `Aes`, `ECB`, `NoPadding`


Expand Down
10 changes: 8 additions & 2 deletions ecgdsa/ecgdsa.go
Original file line number Diff line number Diff line change
Expand Up @@ -304,7 +304,9 @@ func SignToRS(rand io.Reader, priv *PrivateKey, hashFunc Hasher, msg []byte) (r,
}

e := new(big.Int).SetBytes(eBuf)
e.Rsh(e, uint(rshift))
if rshift > 0 {
e.Rsh(e, uint(rshift))
}

// 2: e = q - (h mod q) (except when h is 0).
e = e.Mod(e, n)
Expand Down Expand Up @@ -386,17 +388,21 @@ func VerifyWithRS(pub *PublicKey, hashFunc Hasher, data []byte, r, s *big.Int) b
}

e := new(big.Int).SetBytes(eBuf)
e.Rsh(e, uint(rshift))
if rshift > 0 {
e.Rsh(e, uint(rshift))
}

/* 3. Compute e by converting h to an integer and reducing it mod q */
e = e.Mod(e, n)

/* 4. Compute u = (r^-1)e mod q */
rinv := new(big.Int).ModInverse(r, n)
u := new(big.Int).Mul(rinv, e)
u.Mod(u, n)

/* 5. Compute v = (r^-1)s mod q */
v := new(big.Int).Mul(rinv, s)
v.Mod(v, n)

/* 6. Compute W' = uG + vY */
x21, y21 := curve.ScalarMult(pub.X, pub.Y, v.Bytes())
Expand Down
133 changes: 133 additions & 0 deletions ecgdsa/ecgdsa_test.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package ecgdsa

import (
"fmt"
"strings"
"crypto"
"testing"
Expand All @@ -10,6 +11,7 @@ import (
"crypto/elliptic"
"encoding/hex"
"encoding/pem"
"encoding/base64"

cryptobin_test "github.com/deatil/go-cryptobin/tool/test"
)
Expand Down Expand Up @@ -37,6 +39,11 @@ func fromHex(s string) []byte {
return h
}

func fromBase64(s string) []byte {
res, _ := base64.StdEncoding.DecodeString(s)
return res
}

func toBigint(s string) *big.Int {
result, _ := new(big.Int).SetString(str(s), 16)

Expand Down Expand Up @@ -277,3 +284,129 @@ func test_Marshal_Check(t *testing.T, priv, pub string) {
assertEqual(privPemCheck, priv, "test_Marshal_Check privkey")
}

func Test_PKCS8PrivateKey_Check(t *testing.T) {
for i, tc := range ecgdsaTestCases {
t.Run(fmt.Sprintf("EC-GDSA index %d", i), func(t *testing.T) {
expectedDER := decodePEM(tc.pkcs8PrivateKey)

prikey, err := ParsePrivateKey(expectedDER)
if err != nil {
t.Error(err)
return
}

pubDER := decodePEM(tc.pkixPublicKey)
pubkey, err := ParsePublicKey(pubDER)
if err != nil {
t.Error(err)
return
}

parsePubkey := &prikey.PublicKey

if !pubkey.Equal(parsePubkey) {
t.Errorf("ParsePKCS8PrivateKey fail")
return
}

res := Verify(pubkey, sha256.New, []byte(tc.msg), tc.sig)
if !res {
t.Error("Verify fail")
return
}

{
sig, err := Sign(rand.Reader, prikey, sha256.New, []byte(tc.msg))
if err != nil {
t.Error(err)
return
}

res := Verify(pubkey, sha256.New, []byte(tc.msg), sig)
if !res {
t.Error("Verify 2 fail")
return
}
}

})
}

}

// botan 3.6.0
var ecgdsaTestCases = []struct {
pkcs8PrivateKey string
pkixPublicKey string
msg string
sig []byte
}{
// botan keygen --algo=ECGDSA --params=secp224r1 | tee priv.pem; botan pkcs8 --pub-out priv.pem | tee pub.pem
{
pkcs8PrivateKey: `-----BEGIN PRIVATE KEY-----
MHkCAQAwEQYIKyQDAwIFAgEGBSuBBAAhBGEwXwIBAQQchiYDBE//3ic1+4+qz1ft
0WrUqSLYnLiEbPLTKqE8AzoABO61dVky7ZIuvNzY6BjD6i9RXqbyz79hBpPEHX5Q
8P3DzmR99WQsTgIj2D3qLvYyshoqgXQlxzxp
-----END PRIVATE KEY-----`,
pkixPublicKey: `-----BEGIN PUBLIC KEY-----
ME8wEQYIKyQDAwIFAgEGBSuBBAAhAzoABO61dVky7ZIuvNzY6BjD6i9RXqbyz79h
BpPEHX5Q8P3DzmR99WQsTgIj2D3qLvYyshoqgXQlxzxp
-----END PUBLIC KEY-----`,
msg: `1111111111111111111111111111111122222222222222222222223333333333333333
`,
sig: fromBase64("MD0CHDOpFd+Fa5dliqUE6pwqa2bN1MmsDDdEncSaRh4CHQCovf7MyLUg/xPTtIY45pscV2NHCgSoiVQ2e9F4"),
},
// botan keygen --algo=ECGDSA --params=secp256r1 | tee priv.pem; botan pkcs8 --pub-out priv.pem | tee pub.pem
{
pkcs8PrivateKey: `-----BEGIN PRIVATE KEY-----
MIGIAgEAMBQGCCskAwMCBQIBBggqhkjOPQMBBwRtMGsCAQEEIEOx0qpCDkE7a0iX
nFecDv2bC0ozzoQS8Ao+SjheegOEoUQDQgAELAxKd0QeboAKI5AKatycaAA7EYPH
SpyEA9FzZ4dTHLePEBfCkN+qKAa6jSw06PvxNOPgPnMs5iiotGepVE/JYg==
-----END PRIVATE KEY-----`,
pkixPublicKey: `-----BEGIN PUBLIC KEY-----
MFowFAYIKyQDAwIFAgEGCCqGSM49AwEHA0IABCwMSndEHm6ACiOQCmrcnGgAOxGD
x0qchAPRc2eHUxy3jxAXwpDfqigGuo0sNOj78TTj4D5zLOYoqLRnqVRPyWI=
-----END PUBLIC KEY-----`,
msg: `1111111111111111111111111111111122222222222222222222223333333333333333
`,
sig: fromBase64("MEUCIQDS2RXiCqWHhOdua+fvaESF6N1mDBjBO8vv05Uxq1ZJsAIges9+59UTWRHWljwmsp2JlaUuD3KSZFo2SI3GCrrIJns="),
},
// botan keygen --algo=ECGDSA --params=secp384r1 | tee priv.pem; botan pkcs8 --pub-out priv.pem | tee pub.pem
{
pkcs8PrivateKey: `-----BEGIN PRIVATE KEY-----
MIG3AgEAMBEGCCskAwMCBQIBBgUrgQQAIgSBnjCBmwIBAQQwbZ6M6oeDCTh5e2lC
/rR3jVrZ7NkDyZinW3nG0gdm1rlee6piLNNuPIF3i7VQaK1XoWQDYgAEOzfgS1m2
VAc07wGNEeNuVfZpG7UiMBuF4gPuhde7a0sCWDvp/H8pQuFH1Jd1ijV8youexIAx
cfE25fu/QkqPgzkC1ocZVQfeTSW+NgotZDwzvYssmXUdjgc33WGcAKxt
-----END PRIVATE KEY-----`,
pkixPublicKey: `-----BEGIN PUBLIC KEY-----
MHcwEQYIKyQDAwIFAgEGBSuBBAAiA2IABDs34EtZtlQHNO8BjRHjblX2aRu1IjAb
heID7oXXu2tLAlg76fx/KULhR9SXdYo1fMqLnsSAMXHxNuX7v0JKj4M5AtaHGVUH
3k0lvjYKLWQ8M72LLJl1HY4HN91hnACsbQ==
-----END PUBLIC KEY-----`,
msg: `1111111111111111111111111111111122222222222222222222223333333333333333
`,
sig: fromBase64("MGUCMQDSVRfqCmyXHO+A/TV+wCvFWRXTBfHl3XilUhtqn9bOWDvfPnk9+l2eykH4xC+ZgdwCMBvtq/jMkuXgJbK1ZEXTQAwlRJ2yHQnzI+hGGqYKSWboNDbp8RqzBP+cCUXb/ZvOBw=="),
},
// botan keygen --algo=ECGDSA --params=secp521r1 | tee priv.pem; botan pkcs8 --pub-out priv.pem | tee pub.pem
{
pkcs8PrivateKey: `-----BEGIN PRIVATE KEY-----
MIHvAgEAMBEGCCskAwMCBQIBBgUrgQQAIwSB1jCB0wIBAQRCAdsCfYyoYQxYm3jh
3WyN3zapCr1MsCX8ozFTq47kYgeb5U5zBB79B7Ra6iBQfG2V8CInloDsXi+p1n5a
yIV+Ab5hoYGJA4GGAAQB7QbJQ+GmBV2X0EzUBCShB8HehflvTUPbtJXo5D7bnCmd
heOzJneOONmHw87d/qxhDGSN17JycXStt586J4B7EBsAXq596806GsmsNE548Hzy
jzJOZe1rr5hZuw0pEdr/5U8XyDD4OD8xH0DL99O3TXBhHMWCJ7Dis/hU8zYEx101
WVI=
-----END PRIVATE KEY-----`,
pkixPublicKey: `-----BEGIN PUBLIC KEY-----
MIGcMBEGCCskAwMCBQIBBgUrgQQAIwOBhgAEAe0GyUPhpgVdl9BM1AQkoQfB3oX5
b01D27SV6OQ+25wpnYXjsyZ3jjjZh8PO3f6sYQxkjdeycnF0rbefOieAexAbAF6u
fevNOhrJrDROePB88o8yTmXta6+YWbsNKRHa/+VPF8gw+Dg/MR9Ay/fTt01wYRzF
giew4rP4VPM2BMddNVlS
-----END PUBLIC KEY-----`,
msg: `1111111111111111111111111111111122222222222222222222223333333333333333
`,
sig: fromBase64("MIGIAkIBEzK2sNXoDe0URlqZs70Lv8yy3pRJUSARXopuq6+ve/ve4EcFxCcKk2o21vp/MBSCHghJfgKimDrUuG5Zn3AQyrYCQgGzfkYkbCwTDGtZGdsSh61x6yAWkXk2wpP8qC3o+w3tlFkPJjUp1iixKyUZvevnmqCB7TMed6bbO3gME+veaVOwzg=="),
},
}

56 changes: 27 additions & 29 deletions gm/sm2/sm2.go
Original file line number Diff line number Diff line change
Expand Up @@ -197,12 +197,7 @@ func (pub *PublicKey) Verify(msg, sign []byte, opts crypto.SignerOpts) bool {
return false
}

err = VerifyWithRS(pub, msg, r, s, opt)
if err != nil {
return false
}

return true
return VerifyWithRS(pub, msg, r, s, opt)
}

// 验证 asn.1 编码的数据 bytes(r + s)
Expand All @@ -213,12 +208,7 @@ func (pub *PublicKey) VerifyBytes(msg, sign []byte, opts crypto.SignerOpts) bool
return false
}

err = VerifyWithRS(pub, msg, r, s, opts)
if err != nil {
return false
}

return true
return VerifyWithRS(pub, msg, r, s, opts)
}

// Encrypt with bytes
Expand Down Expand Up @@ -588,17 +578,16 @@ func Sign(random io.Reader, priv *PrivateKey, msg []byte, opts crypto.SignerOpts

// 验证 asn.1 编码的数据 ans1(r, s)
// Verify asn.1 marshal data
func Verify(pub *PublicKey, msg, sign []byte, opts crypto.SignerOpts) error {
func Verify(pub *PublicKey, msg, sign []byte, opts crypto.SignerOpts) bool {
if pub == nil {
return errPublicKey
return false
}

ok := pub.Verify(msg, sign, opts)
if !ok {
return errors.New("cryptobin/sm2: incorrect signature")
if !pub.Verify(msg, sign, opts) {
return false
}

return nil
return true
}

// 签名返回 Bytes 编码数据
Expand All @@ -613,17 +602,16 @@ func SignBytes(random io.Reader, priv *PrivateKey, msg []byte, opts crypto.Signe

// 验证 asn.1 编码的数据 bytes(r + s)
// Verify Bytes marshal data
func VerifyBytes(pub *PublicKey, msg, sign []byte, opts crypto.SignerOpts) error {
func VerifyBytes(pub *PublicKey, msg, sign []byte, opts crypto.SignerOpts) bool {
if pub == nil {
return errPublicKey
return false
}

ok := pub.VerifyBytes(msg, sign, opts)
if !ok {
return errors.New("cryptobin/sm2: incorrect signature")
if !pub.VerifyBytes(msg, sign, opts) {
return false
}

return nil
return true
}

// sm2 sign with SignerOpts
Expand All @@ -642,18 +630,23 @@ func SignToRS(random io.Reader, priv *PrivateKey, msg []byte, opts crypto.Signer
}

// sm2 verify with SignerOpts
func VerifyWithRS(pub *PublicKey, msg []byte, r, s *big.Int, opts crypto.SignerOpts) error {
func VerifyWithRS(pub *PublicKey, msg []byte, r, s *big.Int, opts crypto.SignerOpts) bool {
opt := DefaultSignerOpts
if o, ok := opts.(SignerOpts); ok {
opt = o
}

hashed, err := calculateHash(pub, opt.GetHash(), msg, opt.GetUid())
if err != nil {
return err
return false
}

return verify(pub, hashed, r, s)
err = verify(pub, hashed, r, s)
if err != nil {
return false
}

return true
}

// sm2 sign legacy
Expand All @@ -662,8 +655,13 @@ func SignLegacy(random io.Reader, priv *PrivateKey, hash []byte) (r, s *big.Int,
}

// sm2 verify legacy
func VerifyLegacy(pub *PublicKey, hash []byte, r, s *big.Int) error {
return verify(pub, hash, r, s)
func VerifyLegacy(pub *PublicKey, hash []byte, r, s *big.Int) bool {
err := verify(pub, hash, r, s)
if err != nil {
return false
}

return true
}

// sm2 sign
Expand Down
Loading

0 comments on commit c107157

Please sign in to comment.