mirror of
https://github.com/emmansun/gmsm.git
synced 2025-04-26 12:16:20 +08:00
respect GODEBUG changes for allowing SHA1 certificates #93
This commit is contained in:
parent
d11a8bc940
commit
8b25009e6f
@ -4,6 +4,7 @@ import (
|
||||
"bytes"
|
||||
"crypto/rsa"
|
||||
"encoding/asn1"
|
||||
"encoding/hex"
|
||||
"encoding/pem"
|
||||
"math/big"
|
||||
"strings"
|
||||
@ -183,3 +184,24 @@ func TestMarshalRSAPublicKey(t *testing.T) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const hexPKCS1TestPKCS8Key = "30820278020100300d06092a864886f70d0101010500048202623082025e02010002818100cfb1b5bf9685ffa97b4f99df4ff122b70e59ac9b992f3bc2b3dde17d53c1a34928719b02e8fd17839499bfbd515bd6ef99c7a1c47a239718fe36bfd824c0d96060084b5f67f0273443007a24dfaf5634f7772c9346e10eb294c2306671a5a5e719ae24b4de467291bc571014b0e02dec04534d66a9bb171d644b66b091780e8d020301000102818100b595778383c4afdbab95d2bfed12b3f93bb0a73a7ad952f44d7185fd9ec6c34de8f03a48770f2009c8580bcd275e9632714e9a5e3f32f29dc55474b2329ff0ebc08b3ffcb35bc96e6516b483df80a4a59cceb71918cbabf91564e64a39d7e35dce21cb3031824fdbc845dba6458852ec16af5dddf51a8397a8797ae0337b1439024100ea0eb1b914158c70db39031dd8904d6f18f408c85fbbc592d7d20dee7986969efbda081fdf8bc40e1b1336d6b638110c836bfdc3f314560d2e49cd4fbde1e20b024100e32a4e793b574c9c4a94c8803db5152141e72d03de64e54ef2c8ed104988ca780cd11397bc359630d01b97ebd87067c5451ba777cf045ca23f5912f1031308c702406dfcdbbd5a57c9f85abc4edf9e9e29153507b07ce0a7ef6f52e60dcfebe1b8341babd8b789a837485da6c8d55b29bbb142ace3c24a1f5b54b454d01b51e2ad03024100bd6a2b60dee01e1b3bfcef6a2f09ed027c273cdbbaf6ba55a80f6dcc64e4509ee560f84b4f3e076bd03b11e42fe71a3fdd2dffe7e0902c8584f8cad877cdc945024100aa512fa4ada69881f1d8bb8ad6614f192b83200aef5edf4811313d5ef30a86cbd0a90f7b025c71ea06ec6b34db6306c86b1040670fd8654ad7291d066d06d031"
|
||||
const hexPKCS1TestECKey = "3081a40201010430bdb9839c08ee793d1157886a7a758a3c8b2a17a4df48f17ace57c72c56b4723cf21dcda21d4e1ad57ff034f19fcfd98ea00706052b81040022a16403620004feea808b5ee2429cfcce13c32160e1c960990bd050bb0fdf7222f3decd0a55008e32a6aa3c9062051c4cba92a7a3b178b24567412d43cdd2f882fa5addddd726fe3e208d2c26d733a773a597abb749714df7256ead5105fa6e7b3650de236b50"
|
||||
|
||||
var pkcs1MismatchKeyTests = []struct {
|
||||
hexKey string
|
||||
errorContains string
|
||||
}{
|
||||
{hexKey: hexPKCS1TestPKCS8Key, errorContains: "use ParsePKCS8PrivateKey instead"},
|
||||
{hexKey: hexPKCS1TestECKey, errorContains: "use ParseECPrivateKey instead"},
|
||||
}
|
||||
|
||||
func TestPKCS1MismatchKeyFormat(t *testing.T) {
|
||||
for i, test := range pkcs1MismatchKeyTests {
|
||||
derBytes, _ := hex.DecodeString(test.hexKey)
|
||||
_, err := ParsePKCS1PrivateKey(derBytes)
|
||||
if !strings.Contains(err.Error(), test.errorContains) {
|
||||
t.Errorf("#%d: expected error containing %q, got %s", i, test.errorContains, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -625,6 +625,8 @@ func (c *Certificate) isValid(certType int, currentChain []*Certificate, opts *V
|
||||
// list. (While this is not specified, it is common practice in order to limit
|
||||
// the types of certificates a CA can issue.)
|
||||
//
|
||||
// Certificates other than c in the returned chains should not be modified.
|
||||
//
|
||||
// WARNING: this function doesn't do any revocation checking.
|
||||
func (c *Certificate) Verify(opts VerifyOptions) (chains [][]*Certificate, err error) {
|
||||
// Platform-specific verification needs the ASN.1 contents so
|
||||
@ -670,6 +672,13 @@ func (c *Certificate) Verify(opts VerifyOptions) (chains [][]*Certificate, err e
|
||||
return
|
||||
}
|
||||
|
||||
if len(opts.DNSName) > 0 {
|
||||
err = c.VerifyHostname(opts.DNSName)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
var candidateChains [][]*Certificate
|
||||
if opts.Roots.contains(c) {
|
||||
candidateChains = [][]*Certificate{{c}}
|
||||
@ -700,7 +709,7 @@ func (c *Certificate) Verify(opts VerifyOptions) (chains [][]*Certificate, err e
|
||||
}
|
||||
|
||||
if len(chains) == 0 {
|
||||
return nil, CertificateInvalidError{c.asX509(), IncompatibleUsage, ""}
|
||||
return nil, CertificateInvalidError{Cert: c.asX509(), Reason: IncompatibleUsage, Detail: ""}
|
||||
}
|
||||
|
||||
return chains, nil
|
||||
|
@ -469,6 +469,9 @@ func testVerify(t *testing.T, test verifyTest, useSystemRoots bool) {
|
||||
chains, err := leaf.Verify(opts)
|
||||
|
||||
if test.errorCallback == nil && err != nil {
|
||||
//if runtime.GOOS == "windows" && strings.HasSuffix(testenv.Builder(), "-2008") && err.Error() == "x509: certificate signed by unknown authority" {
|
||||
// testenv.SkipFlaky(t, 19564)
|
||||
//}
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
if test.errorCallback != nil {
|
||||
@ -533,6 +536,18 @@ func testVerify(t *testing.T, test verifyTest, useSystemRoots bool) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestGoVerify(t *testing.T) {
|
||||
// Temporarily enable SHA-1 verification since a number of test chains
|
||||
// require it. TODO(filippo): regenerate test chains.
|
||||
t.Setenv("GODEBUG", "x509sha1=1")
|
||||
|
||||
for _, test := range verifyTests {
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
testVerify(t, test, false)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestSystemVerify(t *testing.T) {
|
||||
if runtime.GOOS != "windows" {
|
||||
t.Skipf("skipping verify test using system APIs on %q", runtime.GOOS)
|
||||
@ -1501,7 +1516,7 @@ func TestUnknownAuthorityError(t *testing.T) {
|
||||
for i, tt := range unknownAuthorityErrorTests {
|
||||
der, _ := pem.Decode([]byte(tt.cert))
|
||||
if der == nil {
|
||||
t.Errorf("#%d: Unable to decode PEM block", i)
|
||||
t.Fatalf("#%d: Unable to decode PEM block", i)
|
||||
}
|
||||
c, err := ParseCertificate(der.Bytes)
|
||||
if err != nil {
|
||||
@ -1853,7 +1868,6 @@ func TestSystemRootsError(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
/* failed with golang 1.15.x
|
||||
func TestSystemRootsErrorUnwrap(t *testing.T) {
|
||||
var err1 = errors.New("err1")
|
||||
err := x509.SystemRootsError{Err: err1}
|
||||
@ -1861,7 +1875,6 @@ func TestSystemRootsErrorUnwrap(t *testing.T) {
|
||||
t.Error("errors.Is failed, wanted success")
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
func TestIssue51759(t *testing.T) {
|
||||
// badCertData contains a cert that we parse as valid
|
||||
|
@ -249,8 +249,8 @@ var (
|
||||
//
|
||||
// http://gmssl.org/docs/oid.html
|
||||
oidSignatureSM2WithSM3 = asn1.ObjectIdentifier{1, 2, 156, 10197, 1, 501}
|
||||
oidSignatureSM2WithSHA1 = asn1.ObjectIdentifier{1, 2, 156, 10197, 1, 502}
|
||||
oidSignatureSM2WithSHA256 = asn1.ObjectIdentifier{1, 2, 156, 10197, 1, 503}
|
||||
//oidSignatureSM2WithSHA1 = asn1.ObjectIdentifier{1, 2, 156, 10197, 1, 502}
|
||||
//oidSignatureSM2WithSHA256 = asn1.ObjectIdentifier{1, 2, 156, 10197, 1, 503}
|
||||
)
|
||||
|
||||
var signatureAlgorithmDetails = []struct {
|
||||
@ -548,9 +548,6 @@ func oidFromExtKeyUsage(eku ExtKeyUsage) (oid asn1.ObjectIdentifier, ok bool) {
|
||||
return
|
||||
}
|
||||
|
||||
// debugAllowSHA1 allows SHA-1 signatures. See issue 41682.
|
||||
var debugAllowSHA1 = godebug.Get("x509sha1") == "1"
|
||||
|
||||
// A Certificate represents an X.509 certificate.
|
||||
type Certificate x509.Certificate
|
||||
|
||||
@ -596,7 +593,7 @@ func (c *Certificate) CheckSignatureFrom(parent *Certificate) error {
|
||||
|
||||
// TODO(agl): don't ignore the path length constraint.
|
||||
|
||||
return checkSignature(c.SignatureAlgorithm, c.RawTBSCertificate, c.Signature, parent.PublicKey, debugAllowSHA1)
|
||||
return checkSignature(c.SignatureAlgorithm, c.RawTBSCertificate, c.Signature, parent.PublicKey, false)
|
||||
}
|
||||
|
||||
// CheckSignature verifies that signature is a valid signature over signed from
|
||||
@ -644,7 +641,7 @@ func checkSignature(algo SignatureAlgorithm, signed, signature []byte, publicKey
|
||||
case crypto.MD5:
|
||||
return x509.InsecureAlgorithmError(algo)
|
||||
case crypto.SHA1:
|
||||
if !allowSHA1 {
|
||||
if !allowSHA1 && godebug.Get("x509sha1") != "1" {
|
||||
return x509.InsecureAlgorithmError(algo)
|
||||
}
|
||||
fallthrough
|
||||
|
188
smx509/x509_additional_test.go
Normal file
188
smx509/x509_additional_test.go
Normal file
@ -0,0 +1,188 @@
|
||||
package smx509
|
||||
|
||||
import (
|
||||
"crypto/ecdsa"
|
||||
"crypto/rand"
|
||||
"crypto/x509"
|
||||
"crypto/x509/pkix"
|
||||
"encoding/base64"
|
||||
"encoding/json"
|
||||
"encoding/pem"
|
||||
"errors"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/emmansun/gmsm/sm2"
|
||||
)
|
||||
|
||||
const publicKeyPemFromAliKms = `-----BEGIN PUBLIC KEY-----
|
||||
MFkwEwYHKoZIzj0CAQYIKoEcz1UBgi0DQgAELfjZP28bYfGSvbODYlXiB5bcoXE+
|
||||
2LRjjpIH3DcCCct9FuVhi9cm60nDFrbW49k2D3GJco2iWPlr0+5LV+t4AQ==
|
||||
-----END PUBLIC KEY-----
|
||||
`
|
||||
const publicKeyPemFromHuaweiKms = `-----BEGIN PUBLIC KEY-----
|
||||
MFkwEwYHKoZIzj0CAQYIKoEcz1UBgi0DQgAEP3JLMIBPGUx88KChOY3WhjNVKOsk
|
||||
RzYP5lpimwVS9CAK6MzL4kqudI7Pqi6hcir35zH8/BHMXzQ4fM2Ojp+59w==
|
||||
-----END PUBLIC KEY-----
|
||||
`
|
||||
|
||||
const publicKeyPemFromHuaweiKmsForSign = `-----BEGIN PUBLIC KEY-----
|
||||
MFkwEwYHKoZIzj0CAQYIKoEcz1UBgi0DQgAENpoOih+9ASfmKYx5lK5mLsrUK3Am
|
||||
B6kLUsqHlVyglXgoMEwo8Sr8xb/Q3gDMNnd7Wyp2bJE9ksb60ansO4QaKg==
|
||||
-----END PUBLIC KEY-----
|
||||
`
|
||||
|
||||
const publicKeyPemFromAliKmsForSign = `-----BEGIN PUBLIC KEY-----
|
||||
MFkwEwYHKoZIzj0CAQYIKoEcz1UBgi0DQgAERrsLH25zLm2LIo6tivZM9afLprSX
|
||||
6TCKAmQJArAO7VOtZyW4PQwfaTsUIF7IXEFG4iI8bNuTQwMykUzLu2ypEA==
|
||||
-----END PUBLIC KEY-----
|
||||
`
|
||||
|
||||
const hashBase64 = `Zsfw9GLu7dnR8tRr3BDk4kFnxIdc8veiKX2gK49LqOA=`
|
||||
const signature = `MEUCIHV5hOCgYzlO4HkrUhct1Cc8BeKmbXNP+ASje5rGOcCYAiEA2XOajXo3/IihtCEJmNpImtWw3uHIy5CX5TIxit7V0gQ=`
|
||||
const signatureFromHuawei = `MEQCIGK8rWDJw5K7a6RZP5pDii8iqY3yLmavaXpkl7aDLORqAiAlMiiSvp7OJYBCJmzmwadBiBhdBnCCfIdjiWhXHX9xcw==`
|
||||
|
||||
const csrFromAli = `-----BEGIN CERTIFICATE REQUEST-----
|
||||
MIIBYjCCAQkCAQAwRzELMAkGA1UEBhMCQ04xEzARBgNVBAMMCkNhcmdvU21hcnQx
|
||||
DzANBgNVBAcMBlpodWhhaTESMBAGA1UECAwJR3Vhbmdkb25nMFkwEwYHKoZIzj0C
|
||||
AQYIKoEcz1UBgi0DQgAERrsLH25zLm2LIo6tivZM9afLprSX6TCKAmQJArAO7VOt
|
||||
ZyW4PQwfaTsUIF7IXEFG4iI8bNuTQwMykUzLu2ypEKBgMC4GCSqGSIb3DQEJDjEh
|
||||
MB8wHQYDVR0OBBYEFA3FO8vT+8qZBfGZa2TRhLRbme+9MC4GCSqGSIb3DQEJDjEh
|
||||
MB8wHQYDVR0RBBYwFIESZW1tYW4uc3VuQGlxYXguY29tMAoGCCqBHM9VAYN1A0cA
|
||||
MEQCIBQx6yv3rzfWCkKqDZQOfNKESQc6NtpQbeVvcxfBrciwAiAj78kkrF5R3g4l
|
||||
bxIHjKZHc2sztHCXe7cseWGiLq0syg==
|
||||
-----END CERTIFICATE REQUEST-----
|
||||
`
|
||||
|
||||
func TestParsePKIXPublicKeyFromExternal(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
pem string
|
||||
}{
|
||||
{"ALI", publicKeyPemFromAliKms},
|
||||
{"HUAWEI", publicKeyPemFromHuaweiKms},
|
||||
}
|
||||
for _, test := range tests {
|
||||
pub, err := getPublicKey([]byte(test.pem))
|
||||
if err != nil {
|
||||
t.Fatalf("%s failed to get public key %v", test.name, err)
|
||||
}
|
||||
pub1 := pub.(*ecdsa.PublicKey)
|
||||
_, err = sm2.Encrypt(rand.Reader, pub1, []byte("encryption standard"), sm2.ASN1EncrypterOpts)
|
||||
if err != nil {
|
||||
t.Fatalf("%s failed to encrypt %v", test.name, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestSignByCloudVerifyAtLocal(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
pem string
|
||||
signature string
|
||||
}{
|
||||
{"ALI", publicKeyPemFromAliKmsForSign, signature},
|
||||
{"HUAWEI", publicKeyPemFromHuaweiKmsForSign, signatureFromHuawei},
|
||||
}
|
||||
for _, test := range tests {
|
||||
dig, err := base64.StdEncoding.DecodeString(test.signature)
|
||||
if err != nil {
|
||||
t.Fatalf("%s failed to decode signature %v", test.name, err)
|
||||
}
|
||||
pub, err := getPublicKey([]byte(test.pem))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
pub1 := pub.(*ecdsa.PublicKey)
|
||||
hashValue, _ := base64.StdEncoding.DecodeString(hashBase64)
|
||||
result := sm2.VerifyASN1(pub1, hashValue, dig)
|
||||
if !result {
|
||||
t.Fatalf("%s Verify fail", test.name)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func getPublicKey(pemContent []byte) (interface{}, error) {
|
||||
block, _ := pem.Decode(pemContent)
|
||||
if block == nil {
|
||||
return nil, errors.New("Failed to parse PEM block")
|
||||
}
|
||||
return ParsePKIXPublicKey(block.Bytes)
|
||||
}
|
||||
|
||||
const sm2Certificate = `
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIICiDCCAiygAwIBAgIQLaGmvQznbGJOY0t9ainQKjAMBggqgRzPVQGDdQUAMC4x
|
||||
CzAJBgNVBAYTAkNOMQ4wDAYDVQQKDAVOUkNBQzEPMA0GA1UEAwwGUk9PVENBMB4X
|
||||
DTEzMDkxMzA4MTAyNVoXDTMzMDkwODA4MTAyNVowNDELMAkGA1UEBhMCQ04xETAP
|
||||
BgNVBAoMCFVuaVRydXN0MRIwEAYDVQQDDAlTSEVDQSBTTTIwWTATBgcqhkjOPQIB
|
||||
BggqgRzPVQGCLQNCAAR90R+RLQZKVBDwhIRVJR28ovu1x3duw2yxaWaY6E3lUKDW
|
||||
IsmAwMOqE71MW3gQOxm68QJfPy6JT4Evil10FwyAo4IBIjCCAR4wHwYDVR0jBBgw
|
||||
FoAUTDKxl9kzG8SmBcHG5YtiW/CXdlgwDwYDVR0TAQH/BAUwAwEB/zCBugYDVR0f
|
||||
BIGyMIGvMEGgP6A9pDswOTELMAkGA1UEBhMCQ04xDjAMBgNVBAoMBU5SQ0FDMQww
|
||||
CgYDVQQLDANBUkwxDDAKBgNVBAMMA2FybDAqoCigJoYkaHR0cDovL3d3dy5yb290
|
||||
Y2EuZ292LmNuL2FybC9hcmwuY3JsMD6gPKA6hjhsZGFwOi8vbGRhcC5yb290Y2Eu
|
||||
Z292LmNuOjM4OS9DTj1hcmwsT1U9QVJMLE89TlJDQUMsQz1DTjAOBgNVHQ8BAf8E
|
||||
BAMCAQYwHQYDVR0OBBYEFIkxBJF7Q6qqmr+EHZuG7vC4cJmgMAwGCCqBHM9VAYN1
|
||||
BQADSAAwRQIhAIp7/3vva+ZxFePKdqkzdGoVyGsfGHhiLLQeKrCZQ2Q5AiAmMOdf
|
||||
0f0b8CilrVWdi8pfZyO6RqYfnpcJ638l7KHfNA==
|
||||
-----END CERTIFICATE-----`
|
||||
|
||||
func Test_ParseCertificate(t *testing.T) {
|
||||
cert, err := ParseCertificatePEM([]byte(sm2Certificate))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
_, err = json.Marshal(cert)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCreateSM2CertificateRequest(t *testing.T) {
|
||||
priv, _ := sm2.GenerateKey(rand.Reader)
|
||||
|
||||
names := pkix.Name{CommonName: "TestName"}
|
||||
var template = x509.CertificateRequest{Subject: names, SignatureAlgorithm: SM2WithSM3}
|
||||
csrblock, err := CreateCertificateRequest(rand.Reader, &template, priv)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
block := &pem.Block{Bytes: csrblock, Type: "CERTIFICATE REQUEST"}
|
||||
pemContent := string(pem.EncodeToMemory(block))
|
||||
err = parseAndCheckCsr([]byte(pemContent))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestParseAliCertificateRequest(t *testing.T) {
|
||||
err := parseAndCheckCsr([]byte(csrFromAli))
|
||||
if err == nil {
|
||||
t.Fatal("ParseCertificate should fail when parsing certificate with duplicate extensions")
|
||||
}
|
||||
}
|
||||
|
||||
func TestMarshalPKIXPublicKey(t *testing.T) {
|
||||
pub, err := getPublicKey([]byte(publicKeyPemFromAliKms))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
result, err := MarshalPKIXPublicKey(pub)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
block := &pem.Block{Bytes: result, Type: "PUBLIC KEY"}
|
||||
pemContent := string(pem.EncodeToMemory(block))
|
||||
if !strings.EqualFold(publicKeyPemFromAliKms, pemContent) {
|
||||
t.Errorf("expected=%s, result=%s", publicKeyPemFromAliKms, pemContent)
|
||||
}
|
||||
}
|
||||
|
||||
func parseAndCheckCsr(csrPem []byte) error {
|
||||
csr, err := ParseCertificateRequestPEM(csrPem)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return csr.CheckSignature()
|
||||
}
|
2410
smx509/x509_test.go
2410
smx509/x509_test.go
File diff suppressed because it is too large
Load Diff
Loading…
x
Reference in New Issue
Block a user