Issuance: carry SKID forward from precert (#7253)
Rather than regenerating the Subject Key ID during both precertificate and final certificate issuance, carry the SKID forward from the precert to the final cert. This ensures that the SKID remains stable between the precert and final cert, even when the method for computing the SKID is updated in the middle of certificate finalization. Additionally, to ensure that the IssuanceRequest -> Certificate conversion process is nearly identical for both precerts and final certs, move SKID computation out of the issuance package and into the CA, so that the SKID is always supplied as part of the issuance request and the issuance package itself doesn't have conditionals or feature flags regarding this behavior.
This commit is contained in:
parent
7b347dd6c3
commit
19bd4a7a87
37
ca/ca.go
37
ca/ca.go
|
|
@ -2,8 +2,13 @@ package ca
|
|||
|
||||
import (
|
||||
"context"
|
||||
"crypto"
|
||||
"crypto/rand"
|
||||
"crypto/sha1"
|
||||
"crypto/sha256"
|
||||
"crypto/x509"
|
||||
"crypto/x509/pkix"
|
||||
"encoding/asn1"
|
||||
"encoding/hex"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
|
@ -344,6 +349,32 @@ func (ca *certificateAuthorityImpl) generateSerialNumberAndValidity() (*big.Int,
|
|||
return serialBigInt, validity, nil
|
||||
}
|
||||
|
||||
func generateSKID(pk crypto.PublicKey) ([]byte, error) {
|
||||
pkBytes, err := x509.MarshalPKIXPublicKey(pk)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var pkixPublicKey struct {
|
||||
Algo pkix.AlgorithmIdentifier
|
||||
BitString asn1.BitString
|
||||
}
|
||||
if _, err := asn1.Unmarshal(pkBytes, &pkixPublicKey); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if features.Get().SHA256SubjectKeyIdentifier {
|
||||
// RFC 7093 Section 2 Additional Methods for Generating Key Identifiers:
|
||||
// The keyIdentifier [may be] composed of the leftmost 160-bits of the
|
||||
// SHA-256 hash of the value of the BIT STRING subjectPublicKey
|
||||
// (excluding the tag, length, and number of unused bits).
|
||||
skid := sha256.Sum256(pkixPublicKey.BitString.Bytes)
|
||||
return skid[0:20:20], nil
|
||||
} else {
|
||||
skid := sha1.Sum(pkixPublicKey.BitString.Bytes)
|
||||
return skid[:], nil
|
||||
}
|
||||
}
|
||||
|
||||
func (ca *certificateAuthorityImpl) issuePrecertificateInner(ctx context.Context, issueReq *capb.IssueCertificateRequest, serialBigInt *big.Int, validity validity) ([]byte, *issuance.Issuer, error) {
|
||||
csr, err := x509.ParseCertificateRequest(issueReq.Csr)
|
||||
if err != nil {
|
||||
|
|
@ -385,6 +416,11 @@ func (ca *certificateAuthorityImpl) issuePrecertificateInner(ctx context.Context
|
|||
return nil, nil, err
|
||||
}
|
||||
|
||||
subjectKeyId, err := generateSKID(csr.PublicKey)
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("computing subject key ID: %w", err)
|
||||
}
|
||||
|
||||
serialHex := core.SerialToString(serialBigInt)
|
||||
|
||||
ca.log.AuditInfof("Signing precert: serial=[%s] regID=[%d] names=[%s] csr=[%s]",
|
||||
|
|
@ -393,6 +429,7 @@ func (ca *certificateAuthorityImpl) issuePrecertificateInner(ctx context.Context
|
|||
names := csrlib.NamesFromCSR(csr)
|
||||
req := &issuance.IssuanceRequest{
|
||||
PublicKey: csr.PublicKey,
|
||||
SubjectKeyId: subjectKeyId,
|
||||
Serial: serialBigInt.Bytes(),
|
||||
DNSNames: names.SANs,
|
||||
CommonName: names.CN,
|
||||
|
|
|
|||
|
|
@ -3,6 +3,9 @@ package ca
|
|||
import (
|
||||
"context"
|
||||
"crypto"
|
||||
"crypto/ecdsa"
|
||||
"crypto/elliptic"
|
||||
"crypto/rand"
|
||||
"crypto/x509"
|
||||
"crypto/x509/pkix"
|
||||
"encoding/asn1"
|
||||
|
|
@ -890,3 +893,25 @@ func TestIssueCertificateForPrecertificateDuplicateSerial(t *testing.T) {
|
|||
t.Fatalf("Wrong type of error issuing duplicate serial. Expected 'error checking for duplicate', got '%s'", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGenerateSKID(t *testing.T) {
|
||||
key, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
|
||||
test.AssertNotError(t, err, "Error generating key")
|
||||
|
||||
features.Set(features.Config{SHA256SubjectKeyIdentifier: true})
|
||||
defer features.Reset()
|
||||
// RFC 7093 section 2 method 1 allows us to use 160 of the leftmost bits for
|
||||
// the Subject Key Identifier. This is the same amount of bits as the
|
||||
// related SHA1 hash.
|
||||
sha256skid, err := generateSKID(key.Public())
|
||||
test.AssertNotError(t, err, "Error generating SKID")
|
||||
test.AssertEquals(t, len(sha256skid), 20)
|
||||
test.AssertEquals(t, cap(sha256skid), 20)
|
||||
features.Reset()
|
||||
|
||||
features.Set(features.Config{SHA256SubjectKeyIdentifier: false})
|
||||
sha1skid, err := generateSKID(key.Public())
|
||||
test.AssertNotError(t, err, "Error generating SKID")
|
||||
test.AssertEquals(t, len(sha1skid), 20)
|
||||
test.AssertEquals(t, cap(sha1skid), 20)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,8 +6,6 @@ import (
|
|||
"crypto/ecdsa"
|
||||
"crypto/rand"
|
||||
"crypto/rsa"
|
||||
"crypto/sha1"
|
||||
"crypto/sha256"
|
||||
"crypto/x509"
|
||||
"crypto/x509/pkix"
|
||||
"encoding/asn1"
|
||||
|
|
@ -22,7 +20,6 @@ import (
|
|||
ctx509 "github.com/google/certificate-transparency-go/x509"
|
||||
"github.com/jmhodges/clock"
|
||||
|
||||
"github.com/letsencrypt/boulder/features"
|
||||
"github.com/letsencrypt/boulder/precert"
|
||||
)
|
||||
|
||||
|
|
@ -88,6 +85,10 @@ func (p *Profile) requestValid(clk clock.Clock, req *IssuanceRequest) error {
|
|||
return errors.New("unsupported public key type")
|
||||
}
|
||||
|
||||
if len(req.SubjectKeyId) != 20 {
|
||||
return errors.New("unexpected subject key ID length")
|
||||
}
|
||||
|
||||
if !p.allowMustStaple && req.IncludeMustStaple {
|
||||
return errors.New("must-staple extension cannot be included")
|
||||
}
|
||||
|
|
@ -201,35 +202,10 @@ var mustStapleExt = pkix.Extension{
|
|||
Value: []byte{0x30, 0x03, 0x02, 0x01, 0x05},
|
||||
}
|
||||
|
||||
func generateSKID(pk crypto.PublicKey) ([]byte, error) {
|
||||
pkBytes, err := x509.MarshalPKIXPublicKey(pk)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var pkixPublicKey struct {
|
||||
Algo pkix.AlgorithmIdentifier
|
||||
BitString asn1.BitString
|
||||
}
|
||||
if _, err := asn1.Unmarshal(pkBytes, &pkixPublicKey); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if features.Get().SHA256SubjectKeyIdentifier {
|
||||
// RFC 7093 Section 2 Additional Methods for Generating Key Identifiers:
|
||||
// The keyIdentifier [may be] composed of the leftmost 160-bits of the
|
||||
// SHA-256 hash of the value of the BIT STRING subjectPublicKey
|
||||
// (excluding the tag, length, and number of unused bits).
|
||||
skid := sha256.Sum256(pkixPublicKey.BitString.Bytes)
|
||||
return skid[0:20:20], nil
|
||||
} else {
|
||||
skid := sha1.Sum(pkixPublicKey.BitString.Bytes)
|
||||
return skid[:], nil
|
||||
}
|
||||
}
|
||||
|
||||
// IssuanceRequest describes a certificate issuance request
|
||||
type IssuanceRequest struct {
|
||||
PublicKey crypto.PublicKey
|
||||
PublicKey crypto.PublicKey
|
||||
SubjectKeyId []byte
|
||||
|
||||
Serial []byte
|
||||
|
||||
|
|
@ -288,12 +264,6 @@ func (i *Issuer) Prepare(req *IssuanceRequest) ([]byte, *issuanceToken, error) {
|
|||
}
|
||||
template.DNSNames = req.DNSNames
|
||||
|
||||
skid, err := generateSKID(req.PublicKey)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
template.SubjectKeyId = skid
|
||||
|
||||
switch req.PublicKey.(type) {
|
||||
case *rsa.PublicKey:
|
||||
template.KeyUsage = x509.KeyUsageDigitalSignature | x509.KeyUsageKeyEncipherment
|
||||
|
|
@ -301,6 +271,8 @@ func (i *Issuer) Prepare(req *IssuanceRequest) ([]byte, *issuanceToken, error) {
|
|||
template.KeyUsage = x509.KeyUsageDigitalSignature
|
||||
}
|
||||
|
||||
template.SubjectKeyId = req.SubjectKeyId
|
||||
|
||||
if req.IncludeCTPoison {
|
||||
template.ExtraExtensions = append(template.ExtraExtensions, ctPoisonExt)
|
||||
} else if len(req.sctList) > 0 {
|
||||
|
|
@ -387,6 +359,7 @@ func RequestFromPrecert(precert *x509.Certificate, scts []ct.SignedCertificateTi
|
|||
}
|
||||
return &IssuanceRequest{
|
||||
PublicKey: precert.PublicKey,
|
||||
SubjectKeyId: precert.SubjectKeyId,
|
||||
Serial: precert.SerialNumber.Bytes(),
|
||||
NotBefore: precert.NotBefore,
|
||||
NotAfter: precert.NotAfter,
|
||||
|
|
|
|||
|
|
@ -18,11 +18,14 @@ import (
|
|||
"github.com/jmhodges/clock"
|
||||
|
||||
"github.com/letsencrypt/boulder/ctpolicy/loglist"
|
||||
"github.com/letsencrypt/boulder/features"
|
||||
"github.com/letsencrypt/boulder/linter"
|
||||
"github.com/letsencrypt/boulder/test"
|
||||
)
|
||||
|
||||
var (
|
||||
goodSKID = []byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
|
||||
)
|
||||
|
||||
func defaultProfile() *Profile {
|
||||
p, _ := NewProfile(defaultProfileConfig(), defaultIssuerConfig())
|
||||
return p
|
||||
|
|
@ -43,6 +46,7 @@ func TestNewProfileNoOCSPURL(t *testing.T) {
|
|||
func TestRequestValid(t *testing.T) {
|
||||
fc := clock.NewFake()
|
||||
fc.Add(time.Hour * 24)
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
profile *Profile
|
||||
|
|
@ -67,6 +71,21 @@ func TestRequestValid(t *testing.T) {
|
|||
request: &IssuanceRequest{PublicKey: &ecdsa.PublicKey{}},
|
||||
expectedError: "cannot sign ECDSA public keys",
|
||||
},
|
||||
{
|
||||
name: "skid too short",
|
||||
profile: &Profile{
|
||||
useForECDSALeaves: true,
|
||||
maxValidity: time.Hour * 2,
|
||||
},
|
||||
request: &IssuanceRequest{
|
||||
PublicKey: &ecdsa.PublicKey{},
|
||||
SubjectKeyId: []byte{0, 1, 2, 3, 4},
|
||||
NotBefore: fc.Now(),
|
||||
NotAfter: fc.Now().Add(time.Hour),
|
||||
Serial: []byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9},
|
||||
},
|
||||
expectedError: "unexpected subject key ID length",
|
||||
},
|
||||
{
|
||||
name: "must staple not allowed",
|
||||
profile: &Profile{
|
||||
|
|
@ -74,6 +93,7 @@ func TestRequestValid(t *testing.T) {
|
|||
},
|
||||
request: &IssuanceRequest{
|
||||
PublicKey: &ecdsa.PublicKey{},
|
||||
SubjectKeyId: goodSKID,
|
||||
IncludeMustStaple: true,
|
||||
},
|
||||
expectedError: "must-staple extension cannot be included",
|
||||
|
|
@ -85,6 +105,7 @@ func TestRequestValid(t *testing.T) {
|
|||
},
|
||||
request: &IssuanceRequest{
|
||||
PublicKey: &ecdsa.PublicKey{},
|
||||
SubjectKeyId: goodSKID,
|
||||
IncludeCTPoison: true,
|
||||
},
|
||||
expectedError: "ct poison extension cannot be included",
|
||||
|
|
@ -95,8 +116,9 @@ func TestRequestValid(t *testing.T) {
|
|||
useForECDSALeaves: true,
|
||||
},
|
||||
request: &IssuanceRequest{
|
||||
PublicKey: &ecdsa.PublicKey{},
|
||||
sctList: []ct.SignedCertificateTimestamp{},
|
||||
PublicKey: &ecdsa.PublicKey{},
|
||||
SubjectKeyId: goodSKID,
|
||||
sctList: []ct.SignedCertificateTimestamp{},
|
||||
},
|
||||
expectedError: "sct list extension cannot be included",
|
||||
},
|
||||
|
|
@ -109,6 +131,7 @@ func TestRequestValid(t *testing.T) {
|
|||
},
|
||||
request: &IssuanceRequest{
|
||||
PublicKey: &ecdsa.PublicKey{},
|
||||
SubjectKeyId: goodSKID,
|
||||
IncludeCTPoison: true,
|
||||
sctList: []ct.SignedCertificateTimestamp{},
|
||||
},
|
||||
|
|
@ -120,8 +143,9 @@ func TestRequestValid(t *testing.T) {
|
|||
useForECDSALeaves: true,
|
||||
},
|
||||
request: &IssuanceRequest{
|
||||
PublicKey: &ecdsa.PublicKey{},
|
||||
CommonName: "cn",
|
||||
PublicKey: &ecdsa.PublicKey{},
|
||||
SubjectKeyId: goodSKID,
|
||||
CommonName: "cn",
|
||||
},
|
||||
expectedError: "common name cannot be included",
|
||||
},
|
||||
|
|
@ -131,9 +155,10 @@ func TestRequestValid(t *testing.T) {
|
|||
useForECDSALeaves: true,
|
||||
},
|
||||
request: &IssuanceRequest{
|
||||
PublicKey: &ecdsa.PublicKey{},
|
||||
NotBefore: fc.Now().Add(time.Hour),
|
||||
NotAfter: fc.Now(),
|
||||
PublicKey: &ecdsa.PublicKey{},
|
||||
SubjectKeyId: goodSKID,
|
||||
NotBefore: fc.Now().Add(time.Hour),
|
||||
NotAfter: fc.Now(),
|
||||
},
|
||||
expectedError: "NotAfter must be after NotBefore",
|
||||
},
|
||||
|
|
@ -144,9 +169,10 @@ func TestRequestValid(t *testing.T) {
|
|||
maxValidity: time.Minute,
|
||||
},
|
||||
request: &IssuanceRequest{
|
||||
PublicKey: &ecdsa.PublicKey{},
|
||||
NotBefore: fc.Now(),
|
||||
NotAfter: fc.Now().Add(time.Hour - time.Second),
|
||||
PublicKey: &ecdsa.PublicKey{},
|
||||
SubjectKeyId: goodSKID,
|
||||
NotBefore: fc.Now(),
|
||||
NotAfter: fc.Now().Add(time.Hour - time.Second),
|
||||
},
|
||||
expectedError: "validity period is more than the maximum allowed period (1h0m0s>1m0s)",
|
||||
},
|
||||
|
|
@ -157,9 +183,10 @@ func TestRequestValid(t *testing.T) {
|
|||
maxValidity: time.Hour,
|
||||
},
|
||||
request: &IssuanceRequest{
|
||||
PublicKey: &ecdsa.PublicKey{},
|
||||
NotBefore: fc.Now(),
|
||||
NotAfter: fc.Now().Add(time.Hour),
|
||||
PublicKey: &ecdsa.PublicKey{},
|
||||
SubjectKeyId: goodSKID,
|
||||
NotBefore: fc.Now(),
|
||||
NotAfter: fc.Now().Add(time.Hour),
|
||||
},
|
||||
expectedError: "validity period is more than the maximum allowed period (1h0m1s>1h0m0s)",
|
||||
},
|
||||
|
|
@ -171,9 +198,10 @@ func TestRequestValid(t *testing.T) {
|
|||
maxBackdate: time.Hour,
|
||||
},
|
||||
request: &IssuanceRequest{
|
||||
PublicKey: &ecdsa.PublicKey{},
|
||||
NotBefore: fc.Now().Add(-time.Hour * 2),
|
||||
NotAfter: fc.Now().Add(-time.Hour),
|
||||
PublicKey: &ecdsa.PublicKey{},
|
||||
SubjectKeyId: goodSKID,
|
||||
NotBefore: fc.Now().Add(-time.Hour * 2),
|
||||
NotAfter: fc.Now().Add(-time.Hour),
|
||||
},
|
||||
expectedError: "NotBefore is backdated more than the maximum allowed period (2h0m0s>1h0m0s)",
|
||||
},
|
||||
|
|
@ -185,9 +213,10 @@ func TestRequestValid(t *testing.T) {
|
|||
maxBackdate: time.Hour,
|
||||
},
|
||||
request: &IssuanceRequest{
|
||||
PublicKey: &ecdsa.PublicKey{},
|
||||
NotBefore: fc.Now().Add(time.Hour),
|
||||
NotAfter: fc.Now().Add(time.Hour * 2),
|
||||
PublicKey: &ecdsa.PublicKey{},
|
||||
SubjectKeyId: goodSKID,
|
||||
NotBefore: fc.Now().Add(time.Hour),
|
||||
NotAfter: fc.Now().Add(time.Hour * 2),
|
||||
},
|
||||
expectedError: "NotBefore is in the future",
|
||||
},
|
||||
|
|
@ -198,10 +227,11 @@ func TestRequestValid(t *testing.T) {
|
|||
maxValidity: time.Hour * 2,
|
||||
},
|
||||
request: &IssuanceRequest{
|
||||
PublicKey: &ecdsa.PublicKey{},
|
||||
NotBefore: fc.Now(),
|
||||
NotAfter: fc.Now().Add(time.Hour),
|
||||
Serial: []byte{0, 1, 2, 3, 4, 5, 6, 7},
|
||||
PublicKey: &ecdsa.PublicKey{},
|
||||
SubjectKeyId: goodSKID,
|
||||
NotBefore: fc.Now(),
|
||||
NotAfter: fc.Now().Add(time.Hour),
|
||||
Serial: []byte{0, 1, 2, 3, 4, 5, 6, 7},
|
||||
},
|
||||
expectedError: "serial must be between 9 and 19 bytes",
|
||||
},
|
||||
|
|
@ -212,10 +242,11 @@ func TestRequestValid(t *testing.T) {
|
|||
maxValidity: time.Hour * 2,
|
||||
},
|
||||
request: &IssuanceRequest{
|
||||
PublicKey: &ecdsa.PublicKey{},
|
||||
NotBefore: fc.Now(),
|
||||
NotAfter: fc.Now().Add(time.Hour),
|
||||
Serial: []byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9},
|
||||
PublicKey: &ecdsa.PublicKey{},
|
||||
SubjectKeyId: goodSKID,
|
||||
NotBefore: fc.Now(),
|
||||
NotAfter: fc.Now().Add(time.Hour),
|
||||
Serial: []byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9},
|
||||
},
|
||||
expectedError: "serial must be between 9 and 19 bytes",
|
||||
},
|
||||
|
|
@ -226,10 +257,11 @@ func TestRequestValid(t *testing.T) {
|
|||
maxValidity: time.Hour * 2,
|
||||
},
|
||||
request: &IssuanceRequest{
|
||||
PublicKey: &ecdsa.PublicKey{},
|
||||
NotBefore: fc.Now(),
|
||||
NotAfter: fc.Now().Add(time.Hour),
|
||||
Serial: []byte{1, 2, 3, 4, 5, 6, 7, 8, 9},
|
||||
PublicKey: &ecdsa.PublicKey{},
|
||||
SubjectKeyId: goodSKID,
|
||||
NotBefore: fc.Now(),
|
||||
NotAfter: fc.Now().Add(time.Hour),
|
||||
Serial: []byte{1, 2, 3, 4, 5, 6, 7, 8, 9},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
|
@ -322,6 +354,7 @@ func TestIssue(t *testing.T) {
|
|||
test.AssertNotError(t, err, "failed to generate test key")
|
||||
lintCertBytes, issuanceToken, err := signer.Prepare(&IssuanceRequest{
|
||||
PublicKey: pk.Public(),
|
||||
SubjectKeyId: goodSKID,
|
||||
Serial: []byte{1, 2, 3, 4, 5, 6, 7, 8, 9},
|
||||
CommonName: "example.com",
|
||||
DNSNames: []string{"example.com"},
|
||||
|
|
@ -366,6 +399,7 @@ func TestIssueRSA(t *testing.T) {
|
|||
test.AssertNotError(t, err, "failed to generate test key")
|
||||
_, issuanceToken, err := signer.Prepare(&IssuanceRequest{
|
||||
PublicKey: pk.Public(),
|
||||
SubjectKeyId: goodSKID,
|
||||
Serial: []byte{1, 2, 3, 4, 5, 6, 7, 8, 9},
|
||||
DNSNames: []string{"example.com"},
|
||||
NotBefore: fc.Now(),
|
||||
|
|
@ -404,6 +438,7 @@ func TestIssueCommonName(t *testing.T) {
|
|||
test.AssertNotError(t, err, "failed to generate test key")
|
||||
ir := &IssuanceRequest{
|
||||
PublicKey: pk.Public(),
|
||||
SubjectKeyId: goodSKID,
|
||||
Serial: []byte{1, 2, 3, 4, 5, 6, 7, 8, 9},
|
||||
CommonName: "example.com",
|
||||
DNSNames: []string{"example.com", "www.example.com"},
|
||||
|
|
@ -453,6 +488,7 @@ func TestIssueCTPoison(t *testing.T) {
|
|||
test.AssertNotError(t, err, "failed to generate test key")
|
||||
_, issuanceToken, err := signer.Prepare(&IssuanceRequest{
|
||||
PublicKey: pk.Public(),
|
||||
SubjectKeyId: goodSKID,
|
||||
Serial: []byte{1, 2, 3, 4, 5, 6, 7, 8, 9},
|
||||
DNSNames: []string{"example.com"},
|
||||
IncludeCTPoison: true,
|
||||
|
|
@ -497,6 +533,7 @@ func TestIssueSCTList(t *testing.T) {
|
|||
test.AssertNotError(t, err, "failed to generate test key")
|
||||
_, issuanceToken, err := signer.Prepare(&IssuanceRequest{
|
||||
PublicKey: pk.Public(),
|
||||
SubjectKeyId: goodSKID,
|
||||
Serial: []byte{1, 2, 3, 4, 5, 6, 7, 8, 9},
|
||||
DNSNames: []string{"example.com"},
|
||||
NotBefore: fc.Now(),
|
||||
|
|
@ -568,6 +605,7 @@ func TestIssueMustStaple(t *testing.T) {
|
|||
test.AssertNotError(t, err, "failed to generate test key")
|
||||
_, issuanceToken, err := signer.Prepare(&IssuanceRequest{
|
||||
PublicKey: pk.Public(),
|
||||
SubjectKeyId: goodSKID,
|
||||
Serial: []byte{1, 2, 3, 4, 5, 6, 7, 8, 9},
|
||||
DNSNames: []string{"example.com"},
|
||||
IncludeMustStaple: true,
|
||||
|
|
@ -599,6 +637,7 @@ func TestIssueBadLint(t *testing.T) {
|
|||
test.AssertNotError(t, err, "failed to generate test key")
|
||||
_, _, err = signer.Prepare(&IssuanceRequest{
|
||||
PublicKey: pk.Public(),
|
||||
SubjectKeyId: goodSKID,
|
||||
Serial: []byte{1, 2, 3, 4, 5, 6, 7, 8, 9},
|
||||
DNSNames: []string{"example-com"},
|
||||
NotBefore: fc.Now(),
|
||||
|
|
@ -627,6 +666,7 @@ func TestIssuanceToken(t *testing.T) {
|
|||
test.AssertNotError(t, err, "failed to generate test key")
|
||||
_, issuanceToken, err := signer.Prepare(&IssuanceRequest{
|
||||
PublicKey: pk.Public(),
|
||||
SubjectKeyId: goodSKID,
|
||||
Serial: []byte{1, 2, 3, 4, 5, 6, 7, 8, 9},
|
||||
DNSNames: []string{"example.com"},
|
||||
NotBefore: fc.Now(),
|
||||
|
|
@ -643,6 +683,7 @@ func TestIssuanceToken(t *testing.T) {
|
|||
|
||||
_, issuanceToken, err = signer.Prepare(&IssuanceRequest{
|
||||
PublicKey: pk.Public(),
|
||||
SubjectKeyId: goodSKID,
|
||||
Serial: []byte{1, 2, 3, 4, 5, 6, 7, 8, 9},
|
||||
DNSNames: []string{"example.com"},
|
||||
NotBefore: fc.Now(),
|
||||
|
|
@ -676,6 +717,7 @@ func TestInvalidProfile(t *testing.T) {
|
|||
test.AssertNotError(t, err, "failed to generate test key")
|
||||
_, _, err = signer.Prepare(&IssuanceRequest{
|
||||
PublicKey: pk.Public(),
|
||||
SubjectKeyId: goodSKID,
|
||||
Serial: []byte{1, 2, 3, 4, 5, 6, 7, 8, 9},
|
||||
DNSNames: []string{"example.com"},
|
||||
NotBefore: fc.Now(),
|
||||
|
|
@ -686,11 +728,12 @@ func TestInvalidProfile(t *testing.T) {
|
|||
test.AssertError(t, err, "Invalid IssuanceRequest")
|
||||
|
||||
_, _, err = signer.Prepare(&IssuanceRequest{
|
||||
PublicKey: pk.Public(),
|
||||
Serial: []byte{1, 2, 3, 4, 5, 6, 7, 8, 9},
|
||||
DNSNames: []string{"example.com"},
|
||||
NotBefore: fc.Now(),
|
||||
NotAfter: fc.Now().Add(time.Hour - time.Second),
|
||||
PublicKey: pk.Public(),
|
||||
SubjectKeyId: goodSKID,
|
||||
Serial: []byte{1, 2, 3, 4, 5, 6, 7, 8, 9},
|
||||
DNSNames: []string{"example.com"},
|
||||
NotBefore: fc.Now(),
|
||||
NotAfter: fc.Now().Add(time.Hour - time.Second),
|
||||
sctList: []ct.SignedCertificateTimestamp{
|
||||
{
|
||||
SCTVersion: ct.V1,
|
||||
|
|
@ -723,6 +766,7 @@ func TestMismatchedProfiles(t *testing.T) {
|
|||
test.AssertNotError(t, err, "failed to generate test key")
|
||||
_, issuanceToken, err := issuer1.Prepare(&IssuanceRequest{
|
||||
PublicKey: pk.Public(),
|
||||
SubjectKeyId: goodSKID,
|
||||
Serial: []byte{1, 2, 3, 4, 5, 6, 7, 8, 9},
|
||||
CommonName: "example.com",
|
||||
DNSNames: []string{"example.com"},
|
||||
|
|
@ -765,25 +809,3 @@ func TestMismatchedProfiles(t *testing.T) {
|
|||
test.AssertError(t, err, "preparing final cert issuance")
|
||||
test.AssertContains(t, err.Error(), "precert does not correspond to linted final cert")
|
||||
}
|
||||
|
||||
func TestGenerateSKID(t *testing.T) {
|
||||
key, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
|
||||
test.AssertNotError(t, err, "Error generating key")
|
||||
|
||||
features.Set(features.Config{SHA256SubjectKeyIdentifier: true})
|
||||
defer features.Reset()
|
||||
// RFC 7093 section 2 method 1 allows us to use 160 of the leftmost bits for
|
||||
// the Subject Key Identifier. This is the same amount of bits as the
|
||||
// related SHA1 hash.
|
||||
sha256skid, err := generateSKID(key.Public())
|
||||
test.AssertNotError(t, err, "Error generating SKID")
|
||||
test.AssertEquals(t, len(sha256skid), 20)
|
||||
test.AssertEquals(t, cap(sha256skid), 20)
|
||||
features.Reset()
|
||||
|
||||
features.Set(features.Config{SHA256SubjectKeyIdentifier: false})
|
||||
sha1skid, err := generateSKID(key.Public())
|
||||
test.AssertNotError(t, err, "Error generating SKID")
|
||||
test.AssertEquals(t, len(sha1skid), 20)
|
||||
test.AssertEquals(t, cap(sha1skid), 20)
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue