Skip to content

NO-JIRA: Add ECDSA P-256 support for certificates and CAs#2116

Open
fabiendupont wants to merge 1 commit intoopenshift:masterfrom
fabiendupont:add-ecdsa-support
Open

NO-JIRA: Add ECDSA P-256 support for certificates and CAs#2116
fabiendupont wants to merge 1 commit intoopenshift:masterfrom
fabiendupont:add-ecdsa-support

Conversation

@fabiendupont
Copy link

@fabiendupont fabiendupont commented Feb 4, 2026

Extends the crypto package to generate ECDSA P-256 key pairs and certificates in addition to existing RSA support, enabling OpenShift components to use modern elliptic curve cryptography.

Changes

Key generation:

  • KeyAlgorithm type for algorithm selection (AlgorithmRSA, AlgorithmECDSA)
  • ECDSA P-256 key pair generation with proper SubjectKeyIdentifier hashing (SHA-1 per RFC 5280)
  • newKeyPairWithAlgorithm() for unified key generation dispatch

Server certificates:

  • CA.MakeServerCertWithAlgorithm() and CA.MakeServerCertForDurationWithAlgorithm()

CA certificates:

  • MakeSelfSignedCAConfigForDurationWithAlgorithm() for ECDSA root CAs
  • MakeCAConfigForDurationWithAlgorithm() for ECDSA intermediate CAs

Template cleanup:

  • Removed hardcoded SignatureAlgorithm: x509.SHA256WithRSA from certificate templates
  • x509.CreateCertificate infers the correct algorithm from the signing key (SHA256WithRSA for RSA, ECDSAWithSHA256 for ECDSA P-256)
  • This is backward compatible and enables correct cross-algorithm signing (e.g. RSA CA signing ECDSA leaf certs)

All existing APIs remain unchanged — new functionality is opt-in through *WithAlgorithm variants.

Test coverage

  • Key generation, signature algorithm detection, and ECDSA PEM encoding
  • Server certs: RSA CA + ECDSA leaf, ECDSA CA + RSA leaf, ECDSA CA + ECDSA leaf
  • MakeServerCertForDurationWithAlgorithm (production code path from certrotation/target.go)
  • Self-signed ECDSA CAs and mixed-algorithm intermediate CA chains
  • Backwards compatibility: all existing RSA tests pass unchanged

@openshift-ci-robot openshift-ci-robot added the jira/valid-reference Indicates that this PR references a valid Jira ticket of any type. label Feb 4, 2026
@openshift-ci-robot
Copy link

@fabiendupont: This pull request explicitly references no jira issue.

Details

In response to this:

Extends the crypto package to generate ECDSA P-256 key pairs in addition to existing RSA support, enabling OpenShift components to use modern elliptic curve cryptography.

Adds:

  • KeyAlgorithm type for algorithm selection (RSA, ECDSA)
  • newECDSAKeyPair() and newECDSAKeyPairWithHash() functions using P-256 curve
  • newKeyPairWithAlgorithm() for unified key generation
  • signatureAlgorithmForKey() for automatic algorithm detection
  • CA.MakeServerCertWithAlgorithm() and CA.MakeServerCertForDurationWithAlgorithm()

All existing APIs remain unchanged, preserving 100% backwards compatibility. New functionality is opt-in through *WithAlgorithm functions.

ECDSA P-256 provides equivalent security to 3072-bit RSA with smaller keys (~87% smaller), faster operations, and better performance. This prepares OpenShift for modern TLS deployments and aligns with industry best practices.

Test coverage includes:

  • Unit tests for key generation, signature algorithm detection, and encoding
  • Integration tests for RSA CA + ECDSA server and vice versa
  • Backwards compatibility tests verifying existing RSA functionality

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the openshift-eng/jira-lifecycle-plugin repository.

@openshift-ci openshift-ci bot requested review from deads2k and p0lyn0mial February 4, 2026 17:26
fabiendupont added a commit to fabiendupont/openshift-service-ca-operator that referenced this pull request Feb 4, 2026
Adds support for generating ECDSA P-256 certificates by specifying the
key algorithm via the new service annotation:
  service.beta.openshift.io/serving-cert-key-algorithm: ecdsa

When the annotation is not specified or set to "rsa", the operator
generates RSA certificates for full backwards compatibility.

This enables services to opt into modern elliptic curve cryptography,
which provides equivalent security to 3072-bit RSA with significantly
smaller keys (~87% smaller) and better performance.

Implementation:
- Added ServingCertKeyAlgorithmAnnotation constant in api.go
- Modified MakeServingCert() to check annotation and select algorithm
- Uses library-go's new MakeServerCertWithAlgorithm() API
- Validates annotation values (rsa, ecdsa) with helpful error messages
- Case-insensitive algorithm matching

Testing:
- Added TestECDSACertificateGeneration with 5 test cases
- Verifies RSA (default and explicit), ECDSA, and invalid inputs
- All existing tests pass with no regressions

Depends on: openshift/library-go#2116

Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>
Signed-off-by: Fabien Dupont <fdupont@redhat.com>
}

// MakeServerCertWithAlgorithm creates a server certificate with the specified key algorithm
func (ca *CA) MakeServerCertWithAlgorithm(hostnames sets.Set[string], lifetime time.Duration, algorithm KeyAlgorithm, fns ...CertificateExtensionFunc) (*TLSCertificateConfig, error) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, I might be wrong, but it looks like MakeServerCert and MakeServerCertWithAlgorithm are very similar. There are two differences. The first is the key algorithm, and the second is that MakeServerCertWithAlgorithm sets the signature algorithm.

I’m wondering if it would make sense to create a private common function for both. I think something like the following could work:

func (ca *CA) MakeServerCertWithAlgorithm(hostnames sets.Set[string], lifetime time.Duration, algorithm KeyAlgorithm, fns ...CertificateExtensionFunc) (*TLSCertificateConfig, error) {
	sigFn := func(template *x509.Certificate) error {
		template.SignatureAlgorithm = signatureAlgorithmForKey(ca.Config.Key)
		return nil
	}
	fns = append([]CertificateExtensionFunc{sigFn}, fns...)
	return ca.makeServerCertWithAlgorithm(hostnames, lifetime, algorithm, fns...)
}

and

func (ca *CA) MakeServerCert(hostnames sets.Set[string], lifetime time.Duration, fns ...CertificateExtensionFunc) (*TLSCertificateConfig, error) {
	return ca.makeServerCertWithAlgorithm(hostnames, lifetime, AlgorithmRSA, fns...)
}

case AlgorithmRSA:
return newKeyPairWithHash()
default:
return newKeyPairWithHash() // Default to RSA for backwards compatibility
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since this is a private method I think we could return an error for unsupported algorithms.

}

// MakeServerCertForDurationWithAlgorithm creates a server certificate with specified duration and algorithm
func (ca *CA) MakeServerCertForDurationWithAlgorithm(hostnames sets.Set[string], lifetime time.Duration, algorithm KeyAlgorithm, fns ...CertificateExtensionFunc) (*TLSCertificateConfig, error) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

am I right that the differences between MakeServerCertForDuration and MakeServerCertForDurationWithAlgorithm mirror those between MakeServerCert and MakeServerCertWithAlgorithm (key algorithm and signature algorithm)? If so, could we refactor them in the same way?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good feedback. Makes sense.

@fabiendupont fabiendupont changed the title NO-JIRA: Add ECDSA P-256 key generation support NO-JIRA: Add ECDSA P-256 support for certificates and CAs Feb 13, 2026
@fabiendupont
Copy link
Author

@p0lyn0mial, I extended the changes to add the ECDSA CA support as well, so we can have a full ECDSA chain.

@fabiendupont fabiendupont force-pushed the add-ecdsa-support branch 2 times, most recently from 3e1f176 to 62ba714 Compare February 13, 2026 16:48
@openshift-merge-robot openshift-merge-robot added the needs-rebase Indicates a PR cannot be merged because it has merge conflicts with HEAD. label Feb 13, 2026
@openshift-merge-robot openshift-merge-robot removed the needs-rebase Indicates a PR cannot be merged because it has merge conflicts with HEAD. label Feb 13, 2026
template := &x509.Certificate{
Subject: subject,

SignatureAlgorithm: x509.SHA256WithRSA,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK. I think that the SignatureAlgorithm will be set by x509.CreateCertificate and our unit tests assert this. Is that correct ?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, that's correct. When SignatureAlgorithm is zero-valued in the template, x509.CreateCertificate infers it from the signing key — SHA256WithRSA for RSA keys, ECDSAWithSHA256 for ECDSA P-256 keys. Our tests assert the resulting SignatureAlgorithm on the generated certs for all combinations (RSA CA + RSA leaf, RSA CA + ECDSA leaf, ECDSA CA + RSA leaf, ECDSA CA + ECDSA leaf).

case AlgorithmRSA:
return newKeyPairWithHash()
default:
return nil, nil, nil, fmt.Errorf("unsupported key algorithm: %d", algo)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It looks like the error message will take the form of unsupported key algorithm: 2, which isn't meaningful to someone debugging. Is there a way to make it more descriptive ?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point. This default branch can only be reached if a new KeyAlgorithm constant is added to the const block (e.g. AlgorithmEd25519) without adding a corresponding case in this switch.

Since newKeyPairWithAlgorithm is private and the callers always pass one of the defined constants, a developer hitting this error would know they forgot to wire up their new algorithm.

I added a comment to clarify that, and kept %d so the numeric value is visible for debugging.

return makeSelfSignedCAConfigForSubjectAndDuration(subject, time.Now, caLifetime, AlgorithmRSA)
}

func MakeSelfSignedCAConfigForDurationWithAlgorithm(name string, caLifetime time.Duration, algorithm KeyAlgorithm) (*TLSCertificateConfig, error) {
Copy link
Contributor

@p0lyn0mial p0lyn0mial Feb 19, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I might be wrong but
MakeSelfSignedCAConfigForDurationWithAlgorithm & MakeCAConfigForDurationWithAlgorithm use newSigningCertificateTemplateForDuration which sets

KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature | x509.KeyUsageCertSign,

I found RFC 5480 where Section 3 says:

If the keyUsage extension is present in a Certification Authority
   (CA) certificate that indicates id-ecPublicKey in
   SubjectPublicKeyInfo, then any combination of the following values
   MAY be present:

     digitalSignature;
     nonRepudiation;
     keyAgreement;
     keyCertSign; and
     cRLSign.

which tells me that x509.KeyUsageKeyEncipherment (in newSigningCertificateTemplateForDuration) should not be used for ECDSA only for RSA.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added a keyUsageForAlgorithm helper that returns:

  • RSA: KeyEncipherment | DigitalSignature
  • ECDSA: DigitalSignature only

Per RFC 5480 Section 3, KeyEncipherment is not valid for ECDSA keys. The CA, server, and intermediate cert templates now receive the algorithm and set KeyUsage accordingly. Tests assert the correct KeyUsage for both RSA and ECDSA certs.

The public client cert template functions (NewClientCertificateTemplate / NewClientCertificateTemplateForDuration) are unchanged since client cert creation currently always uses RSA.

}

// MakeServerCertWithAlgorithm creates a server certificate with the specified key algorithm
func (ca *CA) MakeServerCertWithAlgorithm(hostnames sets.Set[string], lifetime time.Duration, algorithm KeyAlgorithm, fns ...CertificateExtensionFunc) (*TLSCertificateConfig, error) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the issue described at https://github.com/openshift/library-go/pull/2116/changes#r2826380341 is also applicable to the server, client cert template.

Copy link
Contributor

@p0lyn0mial p0lyn0mial left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added a few more nits, overall lgtm.

Before merging, should we pull the changes to the service-ca-operator to make sure the backward compatibility path works?

Also, are we planning some e2e tests for the service-ca-operator to cover the new path?

// keyUsageForAlgorithm returns the appropriate KeyUsage for the given algorithm.
// RSA keys use KeyEncipherment (for RSA key transport in TLS) + DigitalSignature.
// ECDSA keys use only DigitalSignature per RFC 5480 Section 3.
func keyUsageForAlgorithm(algorithm KeyAlgorithm) x509.KeyUsage {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: could we rename this to baseKeyUsageForAlgorithm (or something similar) to indicate the returned value is a starting point that callers may need to extend?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done. Renamed to baseKeyUsageForAlgorithm to make it clear the returned value is a starting point that callers extend (e.g. | KeyUsageCertSign for CAs).

case *rsa.PrivateKey:
return x509.SHA256WithRSA
default:
return x509.SHA256WithRSA
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why not to t.Fatal for unrecognized values?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done. signatureAlgorithmForKey now takes testing.TB and calls t.Fatalf on unrecognized key types instead of silently defaulting to RSA.

return x509.SHA256WithRSA
default:
t.Fatalf("unrecognized private key type: %T", key)
return 0
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: this is unreachable code - i think this could be removed.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unfortunately Go requires it — t.Fatalf does not have a "never returns" type, so the compiler needs a return statement to satisfy the function signature. Added a // unreachable, but required by the compiler comment and moved the t.Fatalf + return outside the switch to make it clearer.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

mhm, ok, thanks for checking.

fabiendupont added a commit to fabiendupont/openshift-service-ca-operator that referenced this pull request Feb 25, 2026
Adds support for generating ECDSA P-256 certificates by specifying the
key algorithm via the new service annotation:
  service.beta.openshift.io/serving-cert-key-algorithm: ecdsa

When the annotation is not specified or set to "rsa", the operator
generates RSA certificates for full backwards compatibility.

This enables services to opt into modern elliptic curve cryptography,
which provides equivalent security to 3072-bit RSA with significantly
smaller keys (~87% smaller) and better performance.

Implementation:
- Added ServingCertKeyAlgorithmAnnotation constant in api.go
- Modified MakeServingCert() to check annotation and select algorithm
- Uses library-go's new MakeServerCertWithAlgorithm() API
- Validates annotation values (rsa, ecdsa) with helpful error messages
- Case-insensitive algorithm matching
- Wired ECDSA CA support: caConfig now accepts a KeyAlgorithm field,
  initializeSigningSecret passes algorithm to CA creation
- CA rotation supports both RSA and ECDSA keys: removed RSA-only type
  assertion, rotateSigningCA and createIntermediateCACert accept
  crypto.PrivateKey, algorithm is detected and preserved on rotation

Testing:
- Added TestECDSACertificateGeneration with 5 test cases
- Verifies RSA (default and explicit), ECDSA, and invalid inputs
- Added e2e tests: ECDSA cert provisioning, invalid algorithm rejection,
  and ECDSA cert regeneration after corruption
- All existing tests pass with no regressions

Depends on: openshift/library-go#2116

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Signed-off-by: Fabien Dupont <fdupont@redhat.com>
@p0lyn0mial
Copy link
Contributor

/lgtm

/hold
putting this on hold until the service-ca-operator PR gets reviewed and we are confident the changes introduced in this PR are the ones we need.

@fabiendupont thanks for the pr and all your work :)

@openshift-ci openshift-ci bot added the do-not-merge/hold Indicates that a PR should not merge because someone has issued a /hold command. label Feb 26, 2026
@openshift-ci openshift-ci bot added the lgtm Indicates that a PR is ready to be merged. label Feb 26, 2026
@openshift-ci
Copy link
Contributor

openshift-ci bot commented Feb 26, 2026

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: fabiendupont, p0lyn0mial

The full list of commands accepted by this bot can be found here.

The pull request process is described here

Details Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@openshift-ci openshift-ci bot added the approved Indicates a PR has been approved by an approver from all required OWNERS files. label Feb 26, 2026
Copy link
Contributor

@benluddy benluddy left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks reasonable. I spoke with @sanchezl about potential overlap with openshift/enhancements#1882 and I don't think it would be harmful to grow a second way to do this in the future or have to do some refactoring.

authorityKeyId := ca.Config.Certs[0].SubjectKeyId
subjectKeyId := publicKeyHash
serverTemplate := newServerCertificateTemplateForDuration(pkix.Name{CommonName: sets.List(hostnames)[0]}, sets.List(hostnames), lifetime, time.Now, authorityKeyId, subjectKeyId)
serverTemplate := newServerCertificateTemplateForDuration(pkix.Name{CommonName: sets.List(hostnames)[0]}, sets.List(hostnames), lifetime, time.Now, authorityKeyId, subjectKeyId, algorithm)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The difference between MakeServerCert[WithAlgorithm] and MakeServerCertForDuration[WithAlgorithm] appears to come down to whether they call newServerCertificateTemplate or newServerCertificateTemplateForDuration, and those two have evolved in a strange way.

The first accepted the lifetime as number of days, applied a default, then converted it to a time.Duration before delegating to the ...ForDuration func. Last year, this was changed so that both accept time.Duration. The remaining differences are (1) the first form applies a default lifetime and (2) has a side effect of writing to stderr.

I think this means that MakeServerCert[WithAlgorithm] will apply a default when the provided lifetime is <= 0, whereas MakeServerCertForDuration[WithAlgorithm] will not. I doubt this difference is obvious to anyone who might be using this package. I agree with what Fabien has done in this PR (i.e., MakeServerCertWithAlgorithm is consistent with MakeServerCert, and MakeServerCertForDuration is consistent with MakeServerCertForDurationWithAlgorithm), but this feels like something we should improve later (cc @p0lyn0mial @sanchezl).

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sgtm, the distinction is almost invisible.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done. Consolidated the two paths:

  • Removed makeServerCertForDurationMakeServerCertForDuration and MakeServerCertForDurationWithAlgorithm now delegate to makeServerCert.
  • Removed the newServerCertificateTemplate lifetime-defaulting wrapper — newServerCertificateTemplateForDuration is now the sole newServerCertificateTemplate.
  • Updated TestValidityPeriodOfServerCertificate to remove the test cases for 0 and negative lifetime that relied on the removed defaulting behavior.

Comment on lines +161 to +175
@@ -151,7 +168,11 @@ func newSigningCertificateTemplate(subject pkix.Name, lifetime time.Duration, cu
warnAboutCertificateLifeTime(subject.CommonName, DefaultCACertificateLifetimeDuration)
}

return newSigningCertificateTemplateForDuration(subject, lifetime, currentTime, nil, nil)
algo := AlgorithmRSA
if len(algorithm) > 0 {
algo = algorithm[0]
}
return newSigningCertificateTemplateForDuration(subject, lifetime, currentTime, nil, nil, algo)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of making the function variadic with a default (and tossing all but the first KeyAlgorithm), can we make the KeyAlgorithm a normal parameter and update the callers to always provide a value?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done. newSigningCertificateTemplate now takes algorithm KeyAlgorithm as a required parameter. All callers updated to explicitly pass AlgorithmRSA (or tt.caAlgorithm for the mixed test).

Comment on lines +614 to +616
// Verify public key matches private key
require.True(t, publicKey.X.Cmp(privateKey.PublicKey.X) == 0, "public key X should match")
require.True(t, publicKey.Y.Cmp(privateKey.PublicKey.Y) == 0, "public key Y should match")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would https://pkg.go.dev/crypto/ecdsa#PublicKey.Equal be suitable for this test?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done. Replaced the manual X.Cmp/Y.Cmp checks with publicKey.Equal(&privateKey.PublicKey).

fabiendupont added a commit to fabiendupont/openshift-service-ca-operator that referenced this pull request Mar 2, 2026
Adds support for generating ECDSA P-256 certificates by specifying the
key algorithm via the new service annotation:
  service.beta.openshift.io/serving-cert-key-algorithm: ecdsa

When the annotation is not specified or set to "rsa", the operator
generates RSA certificates for full backwards compatibility.

This enables services to opt into modern elliptic curve cryptography,
which provides equivalent security to 3072-bit RSA with significantly
smaller keys (~87% smaller) and better performance.

Implementation:
- Added ServingCertKeyAlgorithmAnnotation constant in api.go
- Modified MakeServingCert() to check annotation and select algorithm
- Uses library-go's new MakeServerCertWithAlgorithm() API
- Validates annotation values (rsa, ecdsa) with helpful error messages
- Case-insensitive algorithm matching
- Wired ECDSA CA support: caConfig now accepts a KeyAlgorithm field,
  initializeSigningSecret passes algorithm to CA creation
- CA rotation supports both RSA and ECDSA keys: removed RSA-only type
  assertion, rotateSigningCA and createIntermediateCACert accept
  crypto.PrivateKey, algorithm is detected and preserved on rotation

Testing:
- Added TestECDSACertificateGeneration with 5 test cases
- Verifies RSA (default and explicit), ECDSA, and invalid inputs
- Added e2e tests: ECDSA cert provisioning, invalid algorithm rejection,
  and ECDSA cert regeneration after corruption
- All existing tests pass with no regressions

Depends on: openshift/library-go#2116

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Signed-off-by: Fabien Dupont <fdupont@redhat.com>

// newECDSAKeyPair generates a new P-256 ECDSA key pair
func newECDSAKeyPair() (*ecdsa.PublicKey, *ecdsa.PrivateKey, error) {
privateKey, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not a review, just a note for the PKI feature team that will refactor this down the line openshift/enhancements#1882

Support RSA (with configurable key sizes: 2048, 3072, 4096) and ECDSA (with configurable curves: P-256, P-384, P-521) algorithms in the initial implementation

/cc @rh-roman @sanchezl We'll have to thread the key size here and for newKeyPairWithHash() for the RSA case.

func newKeyPairWithHash() (crypto.PublicKey, crypto.PrivateKey, []byte, error) {

And through newKeyPairWithAlgorithm() as well.

Extends the crypto package to generate ECDSA P-256 key pairs and
certificates in addition to existing RSA support, enabling OpenShift
components to use modern elliptic curve cryptography.

Adds:
- KeyAlgorithm type for algorithm selection (RSA, ECDSA)
- ECDSA P-256 key pair generation with proper SubjectKeyIdentifier hashing
- MakeServerCertWithAlgorithm() and MakeServerCertForDurationWithAlgorithm()
- MakeSelfSignedCAConfigForDurationWithAlgorithm() for ECDSA root CAs
- MakeCAConfigForDurationWithAlgorithm() for ECDSA intermediate CAs

Removes hardcoded SignatureAlgorithm from certificate templates, letting
x509.CreateCertificate infer the correct algorithm from the signing key.
This is backward compatible and enables correct cross-algorithm signing
(e.g. RSA CA signing ECDSA leaf certs).

All existing APIs remain unchanged, preserving backwards compatibility.
New functionality is opt-in through *WithAlgorithm variants.

Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Signed-off-by: Fabien Dupont <fdupont@redhat.com>
@openshift-ci openshift-ci bot removed the lgtm Indicates that a PR is ready to be merged. label Mar 4, 2026
@openshift-ci
Copy link
Contributor

openshift-ci bot commented Mar 4, 2026

New changes are detected. LGTM label has been removed.

@openshift-ci
Copy link
Contributor

openshift-ci bot commented Mar 4, 2026

@fabiendupont: all tests passed!

Full PR test history. Your PR dashboard.

Details

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes-sigs/prow repository. I understand the commands that are listed here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

approved Indicates a PR has been approved by an approver from all required OWNERS files. do-not-merge/hold Indicates that a PR should not merge because someone has issued a /hold command. jira/valid-reference Indicates that this PR references a valid Jira ticket of any type.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants