mirror of
https://github.com/emmansun/gmsm.git
synced 2025-04-27 04:36:19 +08:00
MAGIC - implement MarshalPKIXPublicKey
This commit is contained in:
parent
8b0741fed9
commit
cd8d60fc16
43
sm2/x509.go
43
sm2/x509.go
@ -3,12 +3,20 @@ package sm2
|
|||||||
import (
|
import (
|
||||||
"crypto/ecdsa"
|
"crypto/ecdsa"
|
||||||
"crypto/elliptic"
|
"crypto/elliptic"
|
||||||
|
"crypto/x509"
|
||||||
"crypto/x509/pkix"
|
"crypto/x509/pkix"
|
||||||
"encoding/asn1"
|
"encoding/asn1"
|
||||||
"errors"
|
"errors"
|
||||||
"math/big"
|
"math/big"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// pkixPublicKey reflects a PKIX public key structure. See SubjectPublicKeyInfo
|
||||||
|
// in RFC 3280.
|
||||||
|
type pkixPublicKey struct {
|
||||||
|
Algo pkix.AlgorithmIdentifier
|
||||||
|
BitString asn1.BitString
|
||||||
|
}
|
||||||
|
|
||||||
type publicKeyInfo struct {
|
type publicKeyInfo struct {
|
||||||
Raw asn1.RawContent
|
Raw asn1.RawContent
|
||||||
Algorithm pkix.AlgorithmIdentifier
|
Algorithm pkix.AlgorithmIdentifier
|
||||||
@ -45,13 +53,12 @@ func ParsePKIXPublicKey(derBytes []byte) (interface{}, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if !pki.Algorithm.Algorithm.Equal(oidPublicKeyECDSA) {
|
if !pki.Algorithm.Algorithm.Equal(oidPublicKeyECDSA) {
|
||||||
return nil, errors.New("x509: invalid public key algorithm")
|
return x509.ParsePKIXPublicKey(derBytes)
|
||||||
}
|
}
|
||||||
keyData := &pki
|
keyData := &pki
|
||||||
asn1Data := keyData.PublicKey.RightAlign()
|
asn1Data := keyData.PublicKey.RightAlign()
|
||||||
paramsData := keyData.Algorithm.Parameters.FullBytes
|
paramsData := keyData.Algorithm.Parameters.FullBytes
|
||||||
namedCurveOID := new(asn1.ObjectIdentifier)
|
namedCurveOID := new(asn1.ObjectIdentifier)
|
||||||
namedCurve := P256()
|
|
||||||
rest, err := asn1.Unmarshal(paramsData, namedCurveOID)
|
rest, err := asn1.Unmarshal(paramsData, namedCurveOID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.New("x509: failed to parse ECDSA parameters as named curve")
|
return nil, errors.New("x509: failed to parse ECDSA parameters as named curve")
|
||||||
@ -60,8 +67,9 @@ func ParsePKIXPublicKey(derBytes []byte) (interface{}, error) {
|
|||||||
return nil, errors.New("x509: trailing data after ECDSA parameters")
|
return nil, errors.New("x509: trailing data after ECDSA parameters")
|
||||||
}
|
}
|
||||||
if !namedCurveOID.Equal(oidNamedCurveP256SM2) {
|
if !namedCurveOID.Equal(oidNamedCurveP256SM2) {
|
||||||
return nil, errors.New("x509: it's not SM2 elliptic curve")
|
return x509.ParsePKIXPublicKey(derBytes)
|
||||||
}
|
}
|
||||||
|
namedCurve := P256()
|
||||||
x, y := elliptic.Unmarshal(namedCurve, asn1Data)
|
x, y := elliptic.Unmarshal(namedCurve, asn1Data)
|
||||||
if x == nil {
|
if x == nil {
|
||||||
return nil, errors.New("x509: failed to unmarshal elliptic curve point")
|
return nil, errors.New("x509: failed to unmarshal elliptic curve point")
|
||||||
@ -73,3 +81,32 @@ func ParsePKIXPublicKey(derBytes []byte) (interface{}, error) {
|
|||||||
}
|
}
|
||||||
return pub, nil
|
return pub, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// MarshalPKIXPublicKey converts a public key to PKIX, ASN.1 DER form.
|
||||||
|
//
|
||||||
|
// The following key types are currently supported: *rsa.PublicKey, *ecdsa.PublicKey
|
||||||
|
// and ed25519.PublicKey. Unsupported key types result in an error.
|
||||||
|
//
|
||||||
|
// This kind of key is commonly encoded in PEM blocks of type "PUBLIC KEY".
|
||||||
|
func MarshalPKIXPublicKey(pub interface{}) ([]byte, error) {
|
||||||
|
ecdPub, ok := pub.(*ecdsa.PublicKey)
|
||||||
|
if !ok || ecdPub.Curve != P256() {
|
||||||
|
return x509.MarshalPKIXPublicKey(pub)
|
||||||
|
}
|
||||||
|
|
||||||
|
publicKeyAlgorithm := pkix.AlgorithmIdentifier{Algorithm: oidPublicKeyECDSA}
|
||||||
|
publicKeyBytes := elliptic.Marshal(ecdPub.Curve, ecdPub.X, ecdPub.Y)
|
||||||
|
paramBytes, _ := asn1.Marshal(oidNamedCurveP256SM2)
|
||||||
|
publicKeyAlgorithm.Parameters.FullBytes = paramBytes
|
||||||
|
|
||||||
|
pkix := pkixPublicKey{
|
||||||
|
Algo: publicKeyAlgorithm,
|
||||||
|
BitString: asn1.BitString{
|
||||||
|
Bytes: publicKeyBytes,
|
||||||
|
BitLength: 8 * len(publicKeyBytes),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
ret, _ := asn1.Marshal(pkix)
|
||||||
|
return ret, nil
|
||||||
|
}
|
||||||
|
@ -5,11 +5,11 @@ import (
|
|||||||
"crypto/rand"
|
"crypto/rand"
|
||||||
"encoding/pem"
|
"encoding/pem"
|
||||||
"errors"
|
"errors"
|
||||||
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
const publicKeyPemFromAliKms = `
|
const publicKeyPemFromAliKms = `-----BEGIN PUBLIC KEY-----
|
||||||
-----BEGIN PUBLIC KEY-----
|
|
||||||
MFkwEwYHKoZIzj0CAQYIKoEcz1UBgi0DQgAELfjZP28bYfGSvbODYlXiB5bcoXE+
|
MFkwEwYHKoZIzj0CAQYIKoEcz1UBgi0DQgAELfjZP28bYfGSvbODYlXiB5bcoXE+
|
||||||
2LRjjpIH3DcCCct9FuVhi9cm60nDFrbW49k2D3GJco2iWPlr0+5LV+t4AQ==
|
2LRjjpIH3DcCCct9FuVhi9cm60nDFrbW49k2D3GJco2iWPlr0+5LV+t4AQ==
|
||||||
-----END PUBLIC KEY-----
|
-----END PUBLIC KEY-----
|
||||||
@ -34,3 +34,19 @@ func TestParsePKIXPublicKey(t *testing.T) {
|
|||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user