MAGIC - use interface to avoid implementation dependency

This commit is contained in:
emmansun 2021-02-16 10:17:46 +08:00
parent 1183f9d3c2
commit d8dc283187
3 changed files with 69 additions and 20 deletions

View File

@ -63,6 +63,11 @@ type EncrypterOpts struct {
PointMarshalMode pointMarshalMode
}
// Signer SM2 special signer
type Signer interface {
SignWithSM2(rand io.Reader, uid, msg []byte) ([]byte, error)
}
func (mode pointMarshalMode) mashal(curve elliptic.Curve, x, y *big.Int) []byte {
switch mode {
case MarshalCompressed:

View File

@ -375,20 +375,16 @@ func CreateCertificateRequest(rand io.Reader, template *x509.CertificateRequest,
if !ok {
return nil, errors.New("x509: certificate private key does not implement crypto.Signer")
}
privKey, ok := key.(*sm2.PrivateKey)
if !ok {
ecKey, ok := key.(*ecdsa.PrivateKey)
if !ok || ecKey.Curve != sm2.P256() {
return x509.CreateCertificateRequest(rand, template, priv)
}
privKey, _ = new(sm2.PrivateKey).FromECPrivateKey(ecKey)
var hashFunc crypto.Hash
var sigAlgo pkix.AlgorithmIdentifier
hashFunc, sigAlgo, err = signingParamsForPublicKey(key.Public(), template.SignatureAlgorithm)
if err != nil {
return nil, err
}
var sigAlgo = pkix.AlgorithmIdentifier{}
sigAlgo.Algorithm = oidSignatureSM2WithSM3
var publicKeyBytes []byte
var publicKeyAlgorithm pkix.AlgorithmIdentifier
publicKeyBytes, publicKeyAlgorithm, err = marshalPublicKey(key.Public().(*ecdsa.PublicKey))
publicKeyBytes, publicKeyAlgorithm, err = marshalPublicKey(key.Public())
if err != nil {
return nil, err
}
@ -520,8 +516,23 @@ func CreateCertificateRequest(rand io.Reader, template *x509.CertificateRequest,
tbsCSR.Raw = tbsCSRContents
signed := tbsCSRContents
var signature []byte
if sigAlgo.Algorithm.Equal(oidSignatureSM2WithSM3) {
if smKey, ok := priv.(sm2.Signer); ok {
signature, err = smKey.SignWithSM2(rand, nil, signed)
} else {
return nil, errors.New("x509: require sm2 private key")
}
} else {
if hashFunc != 0 {
h := hashFunc.New()
h.Write(signed)
signed = h.Sum(nil)
}
signature, err = key.Sign(rand, signed, hashFunc)
}
signature, err := privKey.SignWithSM2(rand, nil, signed)
if err != nil {
return
}
@ -1532,7 +1543,7 @@ func signingParamsForPublicKey(pub interface{}, requestedSigAlgo x509.SignatureA
return
}
if requestedSigAlgo == 0 {
if requestedSigAlgo == 0 || sigAlgo.Algorithm.Equal(oidSignatureSM2WithSM3) {
return
}
@ -1671,14 +1682,11 @@ func CreateCertificate(rand io.Reader, template, parent *x509.Certificate, pub,
var signature []byte
if signatureAlgorithm.Algorithm.Equal(oidSignatureSM2WithSM3) {
privKey, ok := key.(*sm2.PrivateKey)
if !ok {
ecKey, ok := key.(*ecdsa.PrivateKey)
if ok && ecKey.Curve == sm2.P256() {
privKey, _ = new(sm2.PrivateKey).FromECPrivateKey(ecKey)
}
if smKey, ok := priv.(sm2.Signer); ok {
signature, err = smKey.SignWithSM2(rand, nil, signed)
} else {
return nil, errors.New("x509: require sm2 private key")
}
signature, err = privKey.SignWithSM2(rand, nil, signed)
} else {
if hashFunc != 0 {
h := hashFunc.New()

View File

@ -12,6 +12,7 @@ import (
"encoding/asn1"
"encoding/base64"
"encoding/hex"
"encoding/json"
"encoding/pem"
"errors"
"fmt"
@ -141,6 +142,24 @@ FOq7cMJvODRwvMin9HwNHijXKp8iikXoAnaEHi1kLR4JtSlxH5WKTnmHUWCa54ZA
9mDH0e5odhcdkMySkwc=
-----END CERTIFICATE-----`
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-----`
var testPrivateKey *rsa.PrivateKey
func init() {
@ -162,6 +181,14 @@ func getPublicKey(pemContent []byte) (interface{}, error) {
return ParsePKIXPublicKey(block.Bytes)
}
func getCertificate(pemContent []byte) (*Certificate, error) {
block, _ := pem.Decode(pemContent)
if block == nil {
return nil, errors.New("Failed to parse PEM block")
}
return ParseCertificate(block.Bytes)
}
func parseAndCheckCsr(csrblock []byte) error {
csr, err := ParseCertificateRequest(csrblock)
if err != nil {
@ -171,6 +198,15 @@ func parseAndCheckCsr(csrblock []byte) error {
return csr.CheckSignature()
}
func Test_ParseCertificate(t *testing.T) {
cert, err := getCertificate([]byte(sm2Certificate))
if err != nil {
t.Fatalf("%v\n", err)
}
jsonContent, err := json.Marshal(cert)
fmt.Printf("%s\n", jsonContent)
}
func TestParseCertificateRequest(t *testing.T) {
block, _ := pem.Decode([]byte(csrFromAli))
if block == nil {
@ -287,7 +323,7 @@ func Test_CreateCertificateRequest(t *testing.T) {
sigAlgo x509.SignatureAlgorithm
}{
{"RSA", testPrivateKey, x509.SHA1WithRSA},
{"SM2-256", sm2Priv, -1},
{"SM2-256", sm2Priv, x509.UnknownSignatureAlgorithm},
{"ECDSA-256", ecdsa256Priv, x509.ECDSAWithSHA1},
{"ECDSA-384", ecdsa384Priv, x509.ECDSAWithSHA1},
{"ECDSA-521", ecdsa521Priv, x509.ECDSAWithSHA1},