Skip to content

Commit 63327aa

Browse files
authored
Move GenerateSKID into Core for sharing across ca, ceremony, and lints (#8922)
Create a new core.GenerateSKID function, which computes the Subject Key Identifier value in the way we want (a truncated hash). Use this to replace the two existing helper functions in the CA and Ceremony tool, and to prepare for additional usage inside our upcoming CP/CPS lints.
1 parent 3ebcb61 commit 63327aa

10 files changed

Lines changed: 171 additions & 146 deletions

File tree

ca/ca.go

Lines changed: 1 addition & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,8 @@ package ca
33
import (
44
"bytes"
55
"context"
6-
"crypto"
76
"crypto/rand"
8-
"crypto/sha256"
97
"crypto/x509"
10-
"crypto/x509/pkix"
11-
"encoding/asn1"
128
"encoding/hex"
139
"errors"
1410
"fmt"
@@ -251,7 +247,7 @@ func (ca *certificateAuthorityImpl) IssueCertificate(ctx context.Context, req *c
251247
return nil, err
252248
}
253249

254-
subjectKeyId, err := generateSKID(csr.PublicKey)
250+
subjectKeyId, err := core.GenerateSKID(csr.PublicKey)
255251
if err != nil {
256252
return nil, fmt.Errorf("computing subject key ID: %w", err)
257253
}
@@ -492,29 +488,6 @@ func (ca *certificateAuthorityImpl) generateSerialNumber() *big.Int {
492488
return serialBigInt
493489
}
494490

495-
// generateSKID computes the Subject Key Identifier using one of the methods in
496-
// RFC 7093 Section 2 Additional Methods for Generating Key Identifiers:
497-
// The keyIdentifier [may be] composed of the leftmost 160-bits of the
498-
// SHA-256 hash of the value of the BIT STRING subjectPublicKey
499-
// (excluding the tag, length, and number of unused bits).
500-
func generateSKID(pk crypto.PublicKey) ([]byte, error) {
501-
pkBytes, err := x509.MarshalPKIXPublicKey(pk)
502-
if err != nil {
503-
return nil, err
504-
}
505-
506-
var pkixPublicKey struct {
507-
Algo pkix.AlgorithmIdentifier
508-
BitString asn1.BitString
509-
}
510-
if _, err := asn1.Unmarshal(pkBytes, &pkixPublicKey); err != nil {
511-
return nil, err
512-
}
513-
514-
skid := sha256.Sum256(pkixPublicKey.BitString.Bytes)
515-
return skid[0:20:20], nil
516-
}
517-
518491
// verifyTBSCertIsDeterministic verifies that x509.CreateCertificate signing
519492
// operation is deterministic and produced identical DER bytes between the given
520493
// lint certificate and leaf certificate. If the DER byte equality check fails

ca/ca_test.go

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -941,18 +941,6 @@ func TestNoteSignError(t *testing.T) {
941941
test.AssertMetricWithLabelsEquals(t, metrics.signErrorCount, prometheus.Labels{"type": "HSM"}, 1)
942942
}
943943

944-
func TestGenerateSKID(t *testing.T) {
945-
t.Parallel()
946-
key, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
947-
test.AssertNotError(t, err, "Error generating key")
948-
949-
sha256skid, err := generateSKID(key.Public())
950-
test.AssertNotError(t, err, "Error generating SKID")
951-
test.AssertEquals(t, len(sha256skid), 20)
952-
test.AssertEquals(t, cap(sha256skid), 20)
953-
features.Reset()
954-
}
955-
956944
func TestVerifyTBSCertIsDeterministic(t *testing.T) {
957945
t.Parallel()
958946

cmd/ceremony/cert.go

Lines changed: 4 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -2,17 +2,17 @@ package main
22

33
import (
44
"crypto"
5-
"crypto/sha256"
65
"crypto/x509"
76
"crypto/x509/pkix"
8-
"encoding/asn1"
97
"errors"
108
"fmt"
119
"io"
1210
"math/big"
1311
"regexp"
1412
"slices"
1513
"time"
14+
15+
"github.com/letsencrypt/boulder/core"
1616
)
1717

1818
type policyInfoConfig struct {
@@ -187,25 +187,8 @@ var stringToKeyUsage = map[string]x509.KeyUsage{
187187
"Cert Sign": x509.KeyUsageCertSign,
188188
}
189189

190-
func generateSKID(pk []byte) ([]byte, error) {
191-
var pkixPublicKey struct {
192-
Algo pkix.AlgorithmIdentifier
193-
BitString asn1.BitString
194-
}
195-
if _, err := asn1.Unmarshal(pk, &pkixPublicKey); err != nil {
196-
return nil, err
197-
}
198-
199-
// RFC 7093 Section 2 Additional Methods for Generating Key Identifiers: The
200-
// keyIdentifier [may be] composed of the leftmost 160-bits of the SHA-256
201-
// hash of the value of the BIT STRING subjectPublicKey (excluding the tag,
202-
// length, and number of unused bits).
203-
skid := sha256.Sum256(pkixPublicKey.BitString.Bytes)
204-
return skid[0:20:20], nil
205-
}
206-
207190
// makeTemplate generates the certificate template for use in x509.CreateCertificate
208-
func makeTemplate(randReader io.Reader, profile *certProfile, pubKey []byte, tbcs *x509.Certificate, ct certType) (*x509.Certificate, error) {
191+
func makeTemplate(randReader io.Reader, profile *certProfile, pubKey crypto.PublicKey, tbcs *x509.Certificate, ct certType) (*x509.Certificate, error) {
209192
// Handle "unrestricted" vs "restricted" subordinate CA profile specifics.
210193
if ct == crossCert && tbcs == nil {
211194
return nil, fmt.Errorf("toBeCrossSigned cert field was nil, but was required to gather EKUs for the lint cert")
@@ -220,7 +203,7 @@ func makeTemplate(randReader io.Reader, profile *certProfile, pubKey []byte, tbc
220203
issuingCertificateURL = []string{profile.IssuerURL}
221204
}
222205

223-
subjectKeyID, err := generateSKID(pubKey)
206+
subjectKeyID, err := core.GenerateSKID(pubKey)
224207
if err != nil {
225208
return nil, err
226209
}

0 commit comments

Comments
 (0)