diff --git a/internal/certificate/generate.go b/internal/certificate/generate.go index 21d7e27..c98a6aa 100644 --- a/internal/certificate/generate.go +++ b/internal/certificate/generate.go @@ -61,7 +61,7 @@ func GenerateLeaf( } // Sign certificate using CA - _, cert, err := pki.SignCertificate(template, caCert, pk.Public(), caPk) + cert, err := pki.SignCertificate(template, caCert, pk.Public(), caPk) return cert, pk, err } @@ -94,6 +94,6 @@ func GenerateCA( } // self sign the root CA - _, cert, err := pki.SignCertificate(template, template, pk.Public(), pk) + cert, err := pki.SignCertificate(template, template, pk.Public(), pk) return cert, pk, err } diff --git a/internal/errors/errors.go b/internal/errors/errors.go deleted file mode 100644 index 43d69e8..0000000 --- a/internal/errors/errors.go +++ /dev/null @@ -1,25 +0,0 @@ -/* -Copyright 2020 The cert-manager Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package errors - -import "fmt" - -type invalidDataError struct{ error } - -func NewInvalidData(str string, obj ...any) error { - return &invalidDataError{error: fmt.Errorf(str, obj...)} -} diff --git a/internal/pki/csr.go b/internal/pki/csr.go index 67c4728..5d2ed9b 100644 --- a/internal/pki/csr.go +++ b/internal/pki/csr.go @@ -33,12 +33,11 @@ import ( // *x509.Certificate crt and an issuer. // publicKey is the public key of the signee, and signerKey is the private // key of the signer. -// It returns a PEM encoded copy of the Certificate as well as a *x509.Certificate -// which can be used for reading the encoded values. -func SignCertificate(template *x509.Certificate, issuerCert *x509.Certificate, publicKey crypto.PublicKey, signerKey any) ([]byte, *x509.Certificate, error) { +// It returns a parsed *x509.Certificate on success. +func SignCertificate(template *x509.Certificate, issuerCert *x509.Certificate, publicKey crypto.PublicKey, signerKey any) (*x509.Certificate, error) { typedSigner, ok := signerKey.(crypto.Signer) if !ok { - return nil, nil, fmt.Errorf("didn't get an expected Signer in call to SignCertificate") + return nil, fmt.Errorf("didn't get an expected Signer in call to SignCertificate") } var pubKeyAlgo x509.PublicKeyAlgorithm @@ -64,32 +63,26 @@ func SignCertificate(template *x509.Certificate, issuerCert *x509.Certificate, p sigAlgoArg = nil // ignored by signatureAlgorithmFromPublicKey default: - return nil, nil, fmt.Errorf("unknown public key type on signing certificate: %T", issuerCert.PublicKey) + return nil, fmt.Errorf("unknown public key type on signing certificate: %T", issuerCert.PublicKey) } var err error template.SignatureAlgorithm, err = signatureAlgorithmFromPublicKey(pubKeyAlgo, sigAlgoArg) if err != nil { - return nil, nil, err + return nil, err } derBytes, err := x509.CreateCertificate(rand.Reader, template, issuerCert, publicKey, signerKey) if err != nil { - return nil, nil, fmt.Errorf("error creating x509 certificate: %s", err.Error()) + return nil, fmt.Errorf("error creating x509 certificate: %w", err) } cert, err := x509.ParseCertificate(derBytes) if err != nil { - return nil, nil, fmt.Errorf("error decoding DER certificate bytes: %s", err.Error()) - } - - pemBytes := bytes.NewBuffer([]byte{}) - err = pem.Encode(pemBytes, &pem.Block{Type: "CERTIFICATE", Bytes: derBytes}) - if err != nil { - return nil, nil, fmt.Errorf("error encoding certificate PEM: %s", err.Error()) + return nil, fmt.Errorf("error decoding DER certificate bytes: %w", err) } - return pemBytes.Bytes(), cert, err + return cert, nil } // EncodeX509 will encode a single *x509.Certificate into PEM format. diff --git a/internal/pki/generate.go b/internal/pki/generate.go index 5b701ab..176cce6 100644 --- a/internal/pki/generate.go +++ b/internal/pki/generate.go @@ -65,26 +65,22 @@ func encodePKCS8PrivateKey(pk any) ([]byte, error) { func encodeECPrivateKey(pk *ecdsa.PrivateKey) ([]byte, error) { keyBytes, err := x509.MarshalECPrivateKey(pk) if err != nil { - return nil, fmt.Errorf("error encoding private key: %s", err.Error()) + return nil, fmt.Errorf("error encoding private key: %w", err) } block := &pem.Block{Type: "EC PRIVATE KEY", Bytes: keyBytes} return pem.EncodeToMemory(block), nil } -// PublicKeysEqual compares two given public keys for equality. -// The definition of "equality" depends on the type of the public keys. -// Returns true if the keys are the same, false if they differ or an error if -// the key type of `a` cannot be determined. -func PublicKeysEqual(a, b crypto.PublicKey) (bool, error) { - switch pub := a.(type) { - case *rsa.PublicKey: - return pub.Equal(b), nil - case *ecdsa.PublicKey: - return pub.Equal(b), nil - case ed25519.PublicKey: - return pub.Equal(b), nil - default: - return false, fmt.Errorf("unrecognised public key type: %T", a) +type publicKeyEqual interface { + Equal(crypto.PublicKey) bool +} + +// PublicKeysEqual compares two public keys for equivalence across supported types. +func PublicKeysEqual(a, b any) (bool, error) { + if ak, ok := a.(publicKeyEqual); ok { + return ak.Equal(b), nil } + + return false, fmt.Errorf("unsupported public key type %T", a) } diff --git a/internal/pki/parse.go b/internal/pki/parse.go index 8f727a0..e56d867 100644 --- a/internal/pki/parse.go +++ b/internal/pki/parse.go @@ -20,8 +20,7 @@ import ( "crypto" "crypto/x509" "encoding/pem" - - "github.com/cert-manager/webhook-cert-lib/internal/errors" + "fmt" ) // DecodeX509CertificateBytes will decode a PEM encoded x509 Certificate. @@ -50,13 +49,13 @@ func DecodeX509CertificateSetBytes(certBytes []byte) ([]*x509.Certificate, error // parse the tls certificate cert, err := x509.ParseCertificate(block.Bytes) if err != nil { - return nil, errors.NewInvalidData("error parsing TLS certificate: %s", err.Error()) + return nil, fmt.Errorf("error parsing TLS certificate: %w", err) } certs = append(certs, cert) } if len(certs) == 0 { - return nil, errors.NewInvalidData("error decoding certificate PEM block") + return nil, fmt.Errorf("error decoding certificate PEM block") } return certs, nil @@ -68,40 +67,40 @@ func DecodePrivateKeyBytes(keyBytes []byte) (crypto.Signer, error) { // decode the private key pem block, _ := pem.Decode(keyBytes) if block == nil { - return nil, errors.NewInvalidData("error decoding private key PEM block") + return nil, fmt.Errorf("error decoding private key PEM block") } switch block.Type { case "PRIVATE KEY": key, err := x509.ParsePKCS8PrivateKey(block.Bytes) if err != nil { - return nil, errors.NewInvalidData("error parsing pkcs#8 private key: %s", err.Error()) + return nil, fmt.Errorf("error parsing pkcs#8 private key: %w", err) } signer, ok := key.(crypto.Signer) if !ok { - return nil, errors.NewInvalidData("error parsing pkcs#8 private key: invalid key type") + return nil, fmt.Errorf("error parsing pkcs#8 private key: invalid key type") } return signer, nil case "EC PRIVATE KEY": key, err := x509.ParseECPrivateKey(block.Bytes) if err != nil { - return nil, errors.NewInvalidData("error parsing ecdsa private key: %s", err.Error()) + return nil, fmt.Errorf("error parsing ecdsa private key: %w", err) } return key, nil case "RSA PRIVATE KEY": key, err := x509.ParsePKCS1PrivateKey(block.Bytes) if err != nil { - return nil, errors.NewInvalidData("error parsing rsa private key: %s", err.Error()) + return nil, fmt.Errorf("error parsing rsa private key: %w", err) } err = key.Validate() if err != nil { - return nil, errors.NewInvalidData("rsa private key failed validation: %s", err.Error()) + return nil, fmt.Errorf("rsa private key failed validation: %w", err) } return key, nil default: - return nil, errors.NewInvalidData("unknown private key type: %s", block.Type) + return nil, fmt.Errorf("unknown private key type: %s", block.Type) } } diff --git a/internal/pki/tls.go b/internal/pki/tls.go index 27c973c..9f3ab0d 100644 --- a/internal/pki/tls.go +++ b/internal/pki/tls.go @@ -22,6 +22,7 @@ import ( "crypto/x509" ) +// ToTLSCertificate converts a x509.Certificate and a crypto.Signer to a tls.Certificate. func ToTLSCertificate(cert *x509.Certificate, pk crypto.Signer) (tls.Certificate, error) { pkData, err := EncodePrivateKey(pk) if err != nil { diff --git a/pkg/authority/ca_secret_controller_test.go b/pkg/authority/ca_secret_controller_test.go index a71bc20..0bdb311 100644 --- a/pkg/authority/ca_secret_controller_test.go +++ b/pkg/authority/ca_secret_controller_test.go @@ -59,7 +59,7 @@ func Test__caRequiresRegeneration(t *testing.T) { if mod != nil { mod(cert) } - _, cert, err = pki.SignCertificate(cert, cert, pk.Public(), pk) + cert, err = pki.SignCertificate(cert, cert, pk.Public(), pk) assert.NoError(t, err) certBytes, err := pki.EncodeX509(cert) assert.NoError(t, err)