From 31af1efa484a91f3f8e5c09dd413210b484ac2a2 Mon Sep 17 00:00:00 2001 From: Mariano Cano Date: Wed, 15 Jun 2022 19:10:58 -0700 Subject: [PATCH 1/2] Sign certificates with the issuer signature algorithm An RSA key can sign another certificates using the RSA PKCS#1 and the RSA-PSS scheme, this change will keep the signature algorithm used in the issuer in the signed certificates instead of using PKCS#1 by default. --- CHANGELOG.md | 7 +++++ cas/softcas/softcas.go | 3 ++ cas/softcas/softcas_test.go | 62 +++++++++++++++++++++++++++++++++++++ 3 files changed, 72 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5fb517a1..78d666ad 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,13 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html). +## [Unreleased] +### Changed +- Certificates signed by an issuer using an RSA key will use the same algorithm + and not default to PKCS #1. For example, if the issuer certificate uses + x509.SHA256WithRSAPSS, the signed certificate will also be signed using + x509.SHA256WithRSAPSS. + ## [0.20.0] - 2022-05-26 ### Added - Added Kubernetes auth method for Vault RAs. diff --git a/cas/softcas/softcas.go b/cas/softcas/softcas.go index 2a97145b..2c61fbae 100644 --- a/cas/softcas/softcas.go +++ b/cas/softcas/softcas.go @@ -3,6 +3,7 @@ package softcas import ( "context" "crypto" + "crypto/rsa" "crypto/x509" "time" @@ -244,6 +245,8 @@ func createCertificate(template, parent *x509.Certificate, pub crypto.PublicKey, if template.SignatureAlgorithm == 0 { if sa, ok := signer.(apiv1.SignatureAlgorithmGetter); ok { template.SignatureAlgorithm = sa.SignatureAlgorithm() + } else if _, ok := parent.PublicKey.(*rsa.PublicKey); ok { + template.SignatureAlgorithm = parent.SignatureAlgorithm } } return x509util.CreateCertificate(template, parent, pub, signer) diff --git a/cas/softcas/softcas_test.go b/cas/softcas/softcas_test.go index b4f5b440..0651ab4d 100644 --- a/cas/softcas/softcas_test.go +++ b/cas/softcas/softcas_test.go @@ -5,6 +5,7 @@ import ( "context" "crypto" "crypto/rand" + "crypto/rsa" "crypto/x509" "crypto/x509/pkix" "fmt" @@ -350,6 +351,67 @@ func TestSoftCAS_CreateCertificate(t *testing.T) { } } +func TestSoftCAS_CreateCertificate_pss(t *testing.T) { + signer, err := rsa.GenerateKey(rand.Reader, 2048) + if err != nil { + t.Fatal(err) + } + + now := time.Now() + template := &x509.Certificate{ + Subject: pkix.Name{CommonName: "Test Root CA"}, + KeyUsage: x509.KeyUsageCRLSign | x509.KeyUsageCertSign, + PublicKey: signer.Public(), + BasicConstraintsValid: true, + IsCA: true, + MaxPathLen: 0, + SerialNumber: big.NewInt(1234), + SignatureAlgorithm: x509.SHA256WithRSAPSS, + NotBefore: now, + NotAfter: now.Add(24 * time.Hour), + } + + iss, err := x509util.CreateCertificate(template, template, signer.Public(), signer) + if err != nil { + t.Fatal(err) + } + if iss.SignatureAlgorithm != x509.SHA256WithRSAPSS { + t.Errorf("Certificate.SignatureAlgorithm = %v, want %v", iss.SignatureAlgorithm, x509.SHA256WithRSAPSS) + } + + c := &SoftCAS{ + CertificateChain: []*x509.Certificate{iss}, + Signer: signer, + } + cert, err := c.CreateCertificate(&apiv1.CreateCertificateRequest{ + Template: &x509.Certificate{ + Subject: pkix.Name{CommonName: "test.smallstep.com"}, + DNSNames: []string{"test.smallstep.com"}, + KeyUsage: x509.KeyUsageDigitalSignature, + ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth, x509.ExtKeyUsageClientAuth}, + PublicKey: testSigner.Public(), + SerialNumber: big.NewInt(1234), + }, + Lifetime: time.Hour, Backdate: time.Minute, + }) + if err != nil { + t.Fatalf("SoftCAS.CreateCertificate() error = %v", err) + } + if cert.Certificate.SignatureAlgorithm != x509.SHA256WithRSAPSS { + t.Errorf("Certificate.SignatureAlgorithm = %v, want %v", iss.SignatureAlgorithm, x509.SHA256WithRSAPSS) + } + + pool := x509.NewCertPool() + pool.AddCert(iss) + if _, err = cert.Certificate.Verify(x509.VerifyOptions{ + CurrentTime: time.Now(), + Roots: pool, + KeyUsages: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth, x509.ExtKeyUsageServerAuth}, + }); err != nil { + t.Errorf("Certificate.Verify() error = %v", err) + } +} + func TestSoftCAS_RenewCertificate(t *testing.T) { mockNow(t) From 7ecb8c32aa58881d34bb6bb915cd6403765632f4 Mon Sep 17 00:00:00 2001 From: Mariano Cano Date: Thu, 16 Jun 2022 14:41:55 -0700 Subject: [PATCH 2/2] Update CHANGELOG.md Co-authored-by: Herman Slatman --- CHANGELOG.md | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 78d666ad..e3f9223e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,10 +6,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. ## [Unreleased] ### Changed -- Certificates signed by an issuer using an RSA key will use the same algorithm - and not default to PKCS #1. For example, if the issuer certificate uses - x509.SHA256WithRSAPSS, the signed certificate will also be signed using - x509.SHA256WithRSAPSS. +- Certificates signed by an issuer using an RSA key will be signed using the same algorithm as the issuer certificate was signed with. The signature will no longer default to PKCS #1. For example, if the issuer certificate was signed using RSA-PSS with SHA-256, a new certificate will also be signed using RSA-PSS with SHA-256. ## [0.20.0] - 2022-05-26 ### Added