From 7a6ae24e9f799ab999cb129454b5479d977e55c7 Mon Sep 17 00:00:00 2001 From: Dominik Roos Date: Fri, 28 Jan 2022 16:46:51 +0100 Subject: [PATCH] pki: calculate Subject Key Identifier according to RFC 5280 (#11218) Calculate the Subject Key Identifier as suggested in RFC 5280, Section 4.2.1.2 > (1) The keyIdentifier is composed of the 160-bit SHA-1 hash of the value of the BIT STRING subjectPublicKey (excluding the tag, length, and number of unused bits). fixes #11153 --- changelog/11218.txt | 3 +++ sdk/helper/certutil/helpers.go | 44 ++++++++++++++++++++++++---------- 2 files changed, 35 insertions(+), 12 deletions(-) create mode 100644 changelog/11218.txt diff --git a/changelog/11218.txt b/changelog/11218.txt new file mode 100644 index 000000000..ef5e87f0e --- /dev/null +++ b/changelog/11218.txt @@ -0,0 +1,3 @@ +```release-note:improvement +secrets/pki: Calculate the Subject Key Identifier as suggested in [RFC 5280, Section 4.2.1.2](https://datatracker.ietf.org/doc/html/rfc5280#section-4.2.1.2). +``` diff --git a/sdk/helper/certutil/helpers.go b/sdk/helper/certutil/helpers.go index 7d454e45c..b6bee2e34 100644 --- a/sdk/helper/certutil/helpers.go +++ b/sdk/helper/certutil/helpers.go @@ -77,21 +77,42 @@ func ParseHexFormatted(in, sep string) []byte { return ret.Bytes() } -// GetSubjKeyID returns the subject key ID, e.g. the SHA1 sum -// of the marshaled public key +// GetSubjKeyID returns the subject key ID. The computed ID is the SHA-1 hash of +// the marshaled public key according to +// https://tools.ietf.org/html/rfc5280#section-4.2.1.2 (1) func GetSubjKeyID(privateKey crypto.Signer) ([]byte, error) { if privateKey == nil { return nil, errutil.InternalError{Err: "passed-in private key is nil"} } + return getSubjectKeyID(privateKey.Public()) +} - marshaledKey, err := x509.MarshalPKIXPublicKey(privateKey.Public()) - if err != nil { - return nil, errutil.InternalError{Err: fmt.Sprintf("error marshalling public key: %s", err)} +func getSubjectKeyID(pub interface{}) ([]byte, error) { + var publicKeyBytes []byte + switch pub := pub.(type) { + case *rsa.PublicKey: + type pkcs1PublicKey struct { + N *big.Int + E int + } + + var err error + publicKeyBytes, err = asn1.Marshal(pkcs1PublicKey{ + N: pub.N, + E: pub.E, + }) + if err != nil { + return nil, errutil.InternalError{Err: fmt.Sprintf("error marshalling public key: %s", err)} + } + case *ecdsa.PublicKey: + publicKeyBytes = elliptic.Marshal(pub.Curve, pub.X, pub.Y) + case ed25519.PublicKey: + publicKeyBytes = pub + default: + return nil, errutil.InternalError{Err: fmt.Sprintf("unsupported public key type: %T", pub)} } - - subjKeyID := sha1.Sum(marshaledKey) - - return subjKeyID[:], nil + skid := sha1.Sum(publicKeyBytes) + return skid[:], nil } // ParsePKIMap takes a map (for instance, the Secret.Data @@ -986,11 +1007,10 @@ func signCertificate(data *CreationBundle, randReader io.Reader) (*ParsedCertBun return nil, err } - marshaledKey, err := x509.MarshalPKIXPublicKey(data.CSR.PublicKey) + subjKeyID, err := getSubjectKeyID(data.CSR.PublicKey) if err != nil { - return nil, errutil.InternalError{Err: fmt.Sprintf("error marshalling public key: %s", err)} + return nil, err } - subjKeyID := sha1.Sum(marshaledKey) caCert := data.SigningBundle.Certificate