From 04953fb8205efea41105baddbac4b189a6e05876 Mon Sep 17 00:00:00 2001 From: Naomi Kirby Date: Thu, 13 Jun 2024 12:32:09 -0700 Subject: [PATCH] Add certificate fingerprints and validity dates too --- signer/signer.go | 44 +++++++++++++++++++++++++++++++---------- signer/signer_test.go | 46 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 80 insertions(+), 10 deletions(-) diff --git a/signer/signer.go b/signer/signer.go index 7fd6863e4..1f45eecb5 100644 --- a/signer/signer.go +++ b/signer/signer.go @@ -12,11 +12,13 @@ import ( "crypto/elliptic" "crypto/rand" "crypto/rsa" + "crypto/sha1" "crypto/sha256" "crypto/x509" "encoding/base64" "encoding/pem" "fmt" + "hash" "io" "regexp" "strings" @@ -186,24 +188,26 @@ type SanitizedConfig struct { PrivateKey string `json:"privatekey,omitempty" yaml:"privatekey,omitempty"` IssuerPrivKey string `json:"issuerprivkey,omitempty" yaml:"issuerprivkey,omitempty"` - // TODO: To fully replace the config-sanitizer tool, we should also include - // fingerprints and expiration times of the certificate (if present). + // If a certificate is present, add fingerprints and expiration dates. + CertFingerprintSha1 string `json:"cert_sha1,omitempty" yaml:"cert_sha1,omitempty"` + CertFingerprintSha256 string `json:"cert_sha256,omitempty" yaml:"cert_sha256,omitempty"` + CertDateStart string `json:"cert_date_start,omitempty" yaml:"cert_date_start,omitempty"` + CertDateEnd string `json:"cert_date_end,omitempty" yaml:"cert_date_end,omitempty"` } -func hashSecretString(secret string) string { +func hashFingerprint(secret []byte, algorithm hash.Hash) string { // Empty strings should stay empty - if secret == "" { + if len(secret) == 0 { return "" } - h := sha256.New() - h.Write([]byte(secret)) - return fmt.Sprintf("%x", h.Sum(nil)) + algorithm.Write(secret) + return fmt.Sprintf("%x", algorithm.Sum(nil)) } // Sanitize configuration to make it suitable for public export func (cfg *Configuration) Sanitize() *SanitizedConfig { - return &SanitizedConfig{ + result := &SanitizedConfig{ // Copy public values verbatim. ID: cfg.ID, Type: cfg.Type, @@ -222,9 +226,29 @@ func (cfg *Configuration) Sanitize() *SanitizedConfig { SaltLength: cfg.SaltLength, // Hash private keys, if present. - PrivateKey: hashSecretString(cfg.PrivateKey), - IssuerPrivKey: hashSecretString(cfg.IssuerPrivKey), + PrivateKey: hashFingerprint([]byte(cfg.PrivateKey), sha256.New()), + IssuerPrivKey: hashFingerprint([]byte(cfg.IssuerPrivKey), sha256.New()), + } + + // If a certificate exists - parse it. + certDER, _ := pem.Decode([]byte(cfg.Certificate)) + if certDER != nil && certDER.Type == "CERTIFICATE" { + certX509, err := x509.ParseCertificate(certDER.Bytes) + if err == nil { + result.CertFingerprintSha1 = hashFingerprint(certDER.Bytes, sha1.New()) + result.CertFingerprintSha256 = hashFingerprint(certDER.Bytes, sha256.New()) + start, err := certX509.NotBefore.MarshalText() + if err == nil { + result.CertDateStart = string(start) + } + end, err := certX509.NotAfter.MarshalText() + if err == nil { + result.CertDateEnd = string(end) + } + } } + + return result } // InitHSM indicates that an HSM has been initialized diff --git a/signer/signer_test.go b/signer/signer_test.go index 74fdac791..b01bcff84 100644 --- a/signer/signer_test.go +++ b/signer/signer_test.go @@ -373,4 +373,50 @@ var sanitizerTestCases = []struct { // echo -n "Lorem Ipsum" | sha256sum IssuerPrivKey: "030dc1f936c3415aff3f3357163515190d347a28e758e1f717d17bae453541c9", }}, + // Certificates should parse out the fingerping and validity dates. + {cfg: Configuration{ + ID: "cert-extra-data", + Certificate: ` +-----BEGIN CERTIFICATE----- +MIICXDCCAeKgAwIBAgIIFYW6xg9HrnAwCgYIKoZIzj0EAwMwXzELMAkGA1UEBhMC +VVMxCzAJBgNVBAgTAkNBMRYwFAYDVQQHEw1Nb3VudGFpbiBWaWV3MRAwDgYDVQQK +EwdNb3ppbGxhMRkwFwYDVQQDExBjc3Jvb3QxNTUwODUxMDA2MB4XDTE4MTIyMTE1 +NTY0NloXDTI5MDIyMjE1NTY0NlowYDELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAkNB +MRYwFAYDVQQHEw1Nb3VudGFpbiBWaWV3MRAwDgYDVQQKEwdNb3ppbGxhMRowGAYD +VQQDExFjc2ludGVyMTU1MDg1MTAwNjB2MBAGByqGSM49AgEGBSuBBAAiA2IABAwF +9wOPiv/1oBdxSyOO6fe8KkFJCiyRx2KIXhsT4BwWY8AGHoCfBNm/Swdg+OSi+TdH +dF+5eUrKiqG4PvdWoGGS4rtHqY3ayeF9GRaaLpLMdZkhc/MVJygJoecmsXM2O6Nq +MGgwDgYDVR0PAQH/BAQDAgGGMBMGA1UdJQQMMAoGCCsGAQUFBwMDMA8GA1UdEwEB +/wQFMAMBAf8wMAYDVR0eAQH/BCYwJKAiMCCCHi5jb250ZW50LXNpZ25hdHVyZS5t +b3ppbGxhLm9yZzAKBggqhkjOPQQDAwNoADBlAjBss+GLdMdLT2Y/g73OE9x0WyUG +vqzO7klt20yytmhaYMIPT/zRnWsHZbqEijHMzGsCMQDEoKetuWkyBkzAytS6l+ss +mYigBlwySY+gTqsjuIrydWlKaOv1GU+PXbwX0cQuaN8= +-----END CERTIFICATE-----`, + }, + result: SanitizedConfig{ + ID: "cert-extra-data", + Certificate: ` +-----BEGIN CERTIFICATE----- +MIICXDCCAeKgAwIBAgIIFYW6xg9HrnAwCgYIKoZIzj0EAwMwXzELMAkGA1UEBhMC +VVMxCzAJBgNVBAgTAkNBMRYwFAYDVQQHEw1Nb3VudGFpbiBWaWV3MRAwDgYDVQQK +EwdNb3ppbGxhMRkwFwYDVQQDExBjc3Jvb3QxNTUwODUxMDA2MB4XDTE4MTIyMTE1 +NTY0NloXDTI5MDIyMjE1NTY0NlowYDELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAkNB +MRYwFAYDVQQHEw1Nb3VudGFpbiBWaWV3MRAwDgYDVQQKEwdNb3ppbGxhMRowGAYD +VQQDExFjc2ludGVyMTU1MDg1MTAwNjB2MBAGByqGSM49AgEGBSuBBAAiA2IABAwF +9wOPiv/1oBdxSyOO6fe8KkFJCiyRx2KIXhsT4BwWY8AGHoCfBNm/Swdg+OSi+TdH +dF+5eUrKiqG4PvdWoGGS4rtHqY3ayeF9GRaaLpLMdZkhc/MVJygJoecmsXM2O6Nq +MGgwDgYDVR0PAQH/BAQDAgGGMBMGA1UdJQQMMAoGCCsGAQUFBwMDMA8GA1UdEwEB +/wQFMAMBAf8wMAYDVR0eAQH/BCYwJKAiMCCCHi5jb250ZW50LXNpZ25hdHVyZS5t +b3ppbGxhLm9yZzAKBggqhkjOPQQDAwNoADBlAjBss+GLdMdLT2Y/g73OE9x0WyUG +vqzO7klt20yytmhaYMIPT/zRnWsHZbqEijHMzGsCMQDEoKetuWkyBkzAytS6l+ss +mYigBlwySY+gTqsjuIrydWlKaOv1GU+PXbwX0cQuaN8= +-----END CERTIFICATE-----`, + // openssl x509 -outform DER | shasum + CertFingerprintSha1: "793a92cb335c3846ffed7f8c112137cd8a75e7c7", + // openssl x509 -outform DER | sha256sum + CertFingerprintSha256: "61bd2500b732d2889a1b17c24365741550534fb715cd4f7c463a23a35bd931ee", + // openssl x509 -noout -text + CertDateStart: "2018-12-21T15:56:46Z", + CertDateEnd: "2029-02-22T15:56:46Z", + }}, }