Skip to content

CNF-26737: fix: use correct PRIVATE KEY PEM tag for ECDSA PKCS#8 keys - #1827

Open
sebrandon1 wants to merge 1 commit into
rh-ecosystem-edge:mainfrom
sebrandon1:fix/ec-pkcs8-pem-tag
Open

sebrandon1 wants to merge 1 commit into
rh-ecosystem-edge:mainfrom
sebrandon1:fix/ec-pkcs8-pem-tag

Conversation

@sebrandon1

@sebrandon1 sebrandon1 commented Jul 21, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Emit PRIVATE KEY (RFC 5958) instead of EC PRIVATE KEY when serializing ECDSA PKCS#8 keys stored in PrivateKey::Ec
  • Route Serialize and filesystem commits through PrivateKey::pem() so output tags stay consistent
  • SEC1 (EC PRIVATE KEY) input still converts via openssl to PKCS#8, then reuses process_pem_private_key
  • Rebased onto main after feat: add Ed25519 and improved ECDSA support with e2e crypto tests #1941 Ed25519/ECDSA work; conflict resolution preserved the tag fix and added/kept EC serialize + full round-trip tests

Related PRs

PR Title Status
rh-ecosystem-edge/recert#1758 ECDSA PKCS#8 scanning support Merged
rh-ecosystem-edge/recert#1941 Ed25519 / ECDSA e2e crypto support Merged

Jira

Upstream References

Test Plan

  • CI passes
  • PrivateKey::Ec pem() / Serialize emit BEGIN PRIVATE KEY, not BEGIN EC PRIVATE KEY
  • SEC1 input still scans and stores PKCS#8 DER
  • Unit tests: test_ec_serialize_uses_correct_pem_tag, test_ec_pkcs8_full_round_trip_der_equality
  • Integration scenario test_crypto_ec_pkcs8_input.sh passes

@openshift-ci
openshift-ci Bot requested review from danmanor and tsorya July 21, 2026 15:12
@openshift-ci

openshift-ci Bot commented Jul 21, 2026

Copy link
Copy Markdown
Contributor

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by: sebrandon1
Once this PR has been reviewed and has the lgtm label, please assign danmanor for approval. For more information see the Code Review Process.

The full list of commands accepted by this bot can be found 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 commented Jul 21, 2026

Copy link
Copy Markdown
Contributor

Hi @sebrandon1. Thanks for your PR.

I'm waiting for a rh-ecosystem-edge member to verify that this patch is reasonable to test. If it is, they should reply with /ok-to-test on its own line. Until that is done, I will not automatically test new commits in this PR, but the usual testing commands by org members will still work.

Tip

We noticed you've done this a few times! Consider joining the org to skip this step and gain /lgtm and other bot rights. We recommend asking approvers on your previous PRs to sponsor you.

Once the patch is verified, the new status will be reflected by the ok-to-test label.

I understand the commands that are listed here.

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.

@coderabbitai

coderabbitai Bot commented Jul 21, 2026

Copy link
Copy Markdown

Review Change Stack

Walkthrough

EC private-key handling now converts SEC1 inputs through PKCS#8 parsing. EC serialization and persistence use the PRIVATE KEY PEM label. Tests cover round trips, DER equality, corrupted inputs, and unknown tags.

Changes

EC PEM label normalization

Layer / File(s) Summary
SEC1 to PKCS#8 parsing
src/cluster_crypto/crypto_objects.rs
Converted EC private-key PEM is processed through the shared PKCS#8 parser.
Unified PEM serialization and persistence
src/cluster_crypto/keys.rs, src/cluster_crypto/distributed_private_key.rs
EC serialization, etcd commits, and filesystem writes use shared PEM generation with the PRIVATE KEY label.
EC PEM round-trip and error validation
src/cluster_crypto/crypto_objects.rs
Tests cover SEC1 conversion, PKCS#8 DER preservation, PEM labels, corrupted input, and unknown tags.

Estimated code review effort: 4 (Complex) | ~45 minutes

Sequence Diagram(s)

sequenceDiagram
  participant ECPrivateKeyPEM
  participant OpenSSL
  participant process_pem_ec_private_key
  participant process_pem_private_key
  ECPrivateKeyPEM->>OpenSSL: convert SEC1 PEM to PKCS#8 PEM
  OpenSSL->>process_pem_ec_private_key: return converted PEM
  process_pem_ec_private_key->>process_pem_private_key: parse PKCS#8 private key
Loading

Possibly related PRs

Suggested reviewers: tsorya, danmanor

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 57.14% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Title check ✅ Passed The title clearly identifies the fix to the ECDSA PKCS#8 PEM tag and matches the main changes.
Description check ✅ Passed The description accurately covers the PEM tag fix, affected serialization paths, SEC1 conversion, tests, and related context.
  • Fix all pre-merge checks with AI
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Comment @coderabbitai help to get the list of available commands.

@sebrandon1
sebrandon1 force-pushed the fix/ec-pkcs8-pem-tag branch 3 times, most recently from f097fff to ffffc89 Compare July 21, 2026 16:13

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
src/cluster_crypto/distributed_private_key.rs (1)

107-110: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Use PrivateKey::pem() to eliminate code duplication.

The PrivateKey enum already implements a pem() method that encapsulates this exact serialization logic (as seen in src/cluster_crypto/keys.rs). Refactor this block to use .pem() directly to keep the domain logic DRY, ensuring consistency with how it is done in commit_k8s_private_key.

♻️ Proposed refactor
-        let private_key_pem = match &self.key_regenerated.clone().context("key was no regenerated")? {
-            PrivateKey::Rsa(rsa_private_key) => pem::Pem::new("RSA PRIVATE KEY", rsa_private_key.to_pkcs1_der()?.as_bytes()),
-            PrivateKey::Ec(ec_bytes) => pem::Pem::new("PRIVATE KEY", ec_bytes.as_ref()),
-        };
+        let private_key_pem = self.key_regenerated.clone().context("key was no regenerated")?.pem()?;
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/cluster_crypto/distributed_private_key.rs` around lines 107 - 110,
Replace the duplicated RSA/EC serialization match in the key regeneration flow
with the existing `PrivateKey::pem()` method, while preserving the current
`key_regenerated` context/error handling. Follow the usage pattern in
`commit_k8s_private_key` and keep the resulting PEM value behavior unchanged.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@src/cluster_crypto/distributed_private_key.rs`:
- Around line 107-110: Replace the duplicated RSA/EC serialization match in the
key regeneration flow with the existing `PrivateKey::pem()` method, while
preserving the current `key_regenerated` context/error handling. Follow the
usage pattern in `commit_k8s_private_key` and keep the resulting PEM value
behavior unchanged.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: f3acd642-6826-43fd-bc6c-fcebf093b16a

📥 Commits

Reviewing files that changed from the base of the PR and between 638c606 and ffffc89.

📒 Files selected for processing (4)
  • src/cluster_crypto/crypto_objects.rs
  • src/cluster_crypto/distributed_private_key.rs
  • src/cluster_crypto/keys.rs
  • src/ocp_postprocess/cluster_domain_rename/etcd_rename.rs
💤 Files with no reviewable changes (1)
  • src/ocp_postprocess/cluster_domain_rename/etcd_rename.rs
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/cluster_crypto/keys.rs

@sebrandon1

Copy link
Copy Markdown
Contributor Author

Hey @omertuc, could you mark these ok-to-test when you get a chance? All builds are passing on GitHub Actions. Thanks!

@omertuc

omertuc commented Jul 21, 2026

Copy link
Copy Markdown
Member

/ok-to-test

@omertuc

omertuc commented Jul 21, 2026

Copy link
Copy Markdown
Member

/retest

1 similar comment
@sebrandon1

Copy link
Copy Markdown
Contributor Author

/retest

@sebrandon1
sebrandon1 force-pushed the fix/ec-pkcs8-pem-tag branch 5 times, most recently from 02a6daf to 74fc42c Compare July 27, 2026 15:35
@sebrandon1

sebrandon1 commented Jul 27, 2026

Copy link
Copy Markdown
Contributor Author

The baremetalds-sno-recert-cluster-rename CI failure on this PR is a known infrastructure issue — the test step polls the node at its original IP after recert changes it, causing SSH timeouts. A fix is in progress: openshift/release#82217

@sebrandon1

Copy link
Copy Markdown
Contributor Author

/retest

@sebrandon1
sebrandon1 force-pushed the fix/ec-pkcs8-pem-tag branch 2 times, most recently from 65bdd57 to 4c24167 Compare July 30, 2026 15:18

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/cluster_crypto/keys.rs (1)

36-46: 🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

Keep the EC private key serialization contract in sync with RSA.

PrivateKey::Rsa serializes as Base64, while PrivateKey::Ec serializes as raw PEM text (BEGIN PRIVATE KEY). Consumers that handle PrivateKey as one JSON string type will decode RSA correctly but get invalid key material for EC. Align the EC branch with the existing RSA/Base64 contract and adjust only the serialization-focused test assertion if needed.

🔧 Proposed fix to align encodings
-            Self::Ec(_) => serializer.serialize_str(&self.pem().map_err(serde::ser::Error::custom)?.to_string()),
+            Self::Ec(_) => serializer.serialize_str(&base64_standard.encode(self.pem().map_err(serde::ser::Error::custom)?.to_string())),
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/cluster_crypto/keys.rs` around lines 36 - 46, Update the EC branch in
PrivateKey’s Serialize implementation to Base64-encode the PEM bytes using the
same base64_standard encoder as the Rsa branch, while preserving the existing
PEM generation and error propagation. Adjust only the serialization-focused test
assertion if it expects raw EC PEM text.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In `@src/cluster_crypto/keys.rs`:
- Around line 36-46: Update the EC branch in PrivateKey’s Serialize
implementation to Base64-encode the PEM bytes using the same base64_standard
encoder as the Rsa branch, while preserving the existing PEM generation and
error propagation. Adjust only the serialization-focused test assertion if it
expects raw EC PEM text.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: e62f6b71-5000-4ce0-b9e1-c579c16508e5

📥 Commits

Reviewing files that changed from the base of the PR and between ffffc89 and 4c24167.

📒 Files selected for processing (3)
  • src/cluster_crypto/crypto_objects.rs
  • src/cluster_crypto/distributed_private_key.rs
  • src/cluster_crypto/keys.rs

@sebrandon1
sebrandon1 force-pushed the fix/ec-pkcs8-pem-tag branch 2 times, most recently from fe2ccd0 to 8d3a434 Compare August 6, 2026 15:47
@sebrandon1

Copy link
Copy Markdown
Contributor Author

openshift/release#82217 is now merged — issuing retests to see if it passes.

/retest

@sebrandon1
sebrandon1 force-pushed the fix/ec-pkcs8-pem-tag branch from 8d3a434 to e069ba6 Compare August 10, 2026 12:52
@sebrandon1

Copy link
Copy Markdown
Contributor Author

/retest

1 similar comment
@sebrandon1

Copy link
Copy Markdown
Contributor Author

/retest

@sebrandon1
sebrandon1 force-pushed the fix/ec-pkcs8-pem-tag branch 2 times, most recently from c6bfa31 to 22cd35b Compare August 17, 2026 17:45
@sebrandon1 sebrandon1 changed the title fix: use correct PRIVATE KEY PEM tag for ECDSA PKCS#8 keys CNF-26737: fix: use correct PRIVATE KEY PEM tag for ECDSA PKCS#8 keys Aug 24, 2026
@openshift-ci-robot

openshift-ci-robot commented Aug 24, 2026

Copy link
Copy Markdown
Collaborator

@sebrandon1: This pull request references CNF-26737 which is a valid jira issue.

Warning: The referenced jira issue has an invalid target version for the target branch this PR targets: expected the story to target the "5.1.0" version, but no target version was set.

Details

In response to this:

Summary

Corrects the PEM tag used when serializing ECDSA PKCS#8 private keys. Since #1758, PrivateKey::Ec stores PKCS#8 DER bytes but the output paths emitted them with the "EC PRIVATE KEY" PEM tag (SEC1 format, RFC 5915). The correct tag for PKCS#8 is "PRIVATE KEY" (RFC 5958).

Impact: Low. Real-world TLS consumers (OpenSSL, Go crypto/tls, cert-manager) parse the ASN.1 content rather than relying on the PEM tag, so this does not cause functional failures. E2E IBU testing with cert-manager ECDSA certs passed with the old tag. This is a standards-compliance fix to eliminate a class of potential issues with strict PEM parsers.

Changes

  • Changed PEM tag from "EC PRIVATE KEY" to "PRIVATE KEY" in Serialize, pem(), and commit_filesystem_private_key()
  • Added round-trip PEM tag assertion to existing ECDSA PKCS#8 tests
  • Added 4 new tests covering SEC1 scanning, full round-trip, Serialize output, and corrupted DER

Unit tests

Test File Verifies
test_process_pem_private_key_ecdsa_p256_pkcs8 crypto_objects.rs P-256 PKCS#8 round-trip + PEM tag assertion
test_process_pem_private_key_ecdsa_p384_pkcs8 crypto_objects.rs P-384 PKCS#8 round-trip + PEM tag assertion
test_process_pem_ec_private_key_sec1_p256 crypto_objects.rs SEC1 scanning path produces PrivateKey::Ec + valid PublicKey
test_ec_pkcs8_full_round_trip crypto_objects.rs pem() output re-parsed by process_single_pem succeeds
test_ec_serialize_uses_correct_pem_tag crypto_objects.rs Serialize impl emits "PRIVATE KEY" tag, not "EC PRIVATE KEY"
test_process_pem_private_key_corrupted_pkcs8 crypto_objects.rs Corrupted PKCS#8 DER rejected with error
test_process_pem_private_key_rsa_pkcs8_still_works crypto_objects.rs RSA PKCS#8 regression guard

Files changed

File Change
keys.rs Serialize and pem() -- tag fix
distributed_private_key.rs commit_filesystem_private_key() -- same tag fix
crypto_objects.rs PEM tag round-trip assertions + 4 new tests

Context

Follow-up to #1758 which correctly changed the input path to store PKCS#8 DER in PrivateKey::Ec, but did not update the output paths to use the matching PEM tag.

Summary by CodeRabbit

  • Bug Fixes

  • Improved elliptic-curve private-key handling and serialization.

  • Standardized EC private-key output to use the PRIVATE KEY PEM format.

  • Preserved key data during PEM round trips and when storing keys on disk or in Kubernetes.

  • Improved handling of corrupted private-key data and unsupported PEM labels.

  • Ensured regenerated keys are committed consistently across supported storage methods.

  • Tests

  • Expanded coverage for EC key formats, serialization, round trips, and error scenarios.

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.

@sebrandon1
sebrandon1 force-pushed the fix/ec-pkcs8-pem-tag branch 2 times, most recently from ef8fee6 to 57aac7f Compare August 26, 2026 16:16
@sebrandon1
sebrandon1 force-pushed the fix/ec-pkcs8-pem-tag branch 4 times, most recently from d1e882e to bb816cb Compare September 8, 2026 13:31
@openshift-ci-robot

openshift-ci-robot commented Sep 18, 2026

Copy link
Copy Markdown
Collaborator

@sebrandon1: This pull request references CNF-26737 which is a valid jira issue.

Warning: The referenced jira issue has an invalid target version for the target branch this PR targets: expected the story to target the "5.1.0" version, but no target version was set.

Details

In response to this:

Summary

  • Emit PRIVATE KEY (RFC 5958) instead of EC PRIVATE KEY when serializing ECDSA PKCS#8 keys stored in PrivateKey::Ec
  • Route Serialize and filesystem commits through PrivateKey::pem() so output tags stay consistent
  • SEC1 (EC PRIVATE KEY) input still converts via openssl to PKCS#8, then reuses process_pem_private_key
  • Rebased onto main after feat: add Ed25519 and improved ECDSA support with e2e crypto tests #1941 Ed25519/ECDSA work; conflict resolution preserved the tag fix and added/kept EC serialize + full round-trip tests

Related PRs

PR Title Status
rh-ecosystem-edge/recert#1758 ECDSA PKCS#8 scanning support Merged
rh-ecosystem-edge/recert#1941 Ed25519 / ECDSA e2e crypto support Merged

Jira

Upstream References

Test Plan

  • CI passes
  • PrivateKey::Ec pem() / Serialize emit BEGIN PRIVATE KEY, not BEGIN EC PRIVATE KEY
  • SEC1 input still scans and stores PKCS#8 DER
  • Unit tests: test_ec_serialize_uses_correct_pem_tag, test_ec_pkcs8_full_round_trip_der_equality
  • Integration scenario test_crypto_ec_pkcs8_input.sh passes

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-robot

openshift-ci-robot commented Sep 18, 2026

Copy link
Copy Markdown
Collaborator

@sebrandon1: This pull request references CNF-26737 which is a valid jira issue.

Warning: The referenced jira issue has an invalid target version for the target branch this PR targets: expected the story to target the "5.1.0" version, but no target version was set.

Details

In response to this:

Summary

  • Emit PRIVATE KEY (RFC 5958) instead of EC PRIVATE KEY when serializing ECDSA PKCS#8 keys stored in PrivateKey::Ec
  • Route Serialize and filesystem commits through PrivateKey::pem() so output tags stay consistent
  • SEC1 (EC PRIVATE KEY) input still converts via openssl to PKCS#8, then reuses process_pem_private_key
  • Rebased onto main after feat: add Ed25519 and improved ECDSA support with e2e crypto tests #1941 Ed25519/ECDSA work; conflict resolution preserved the tag fix and added/kept EC serialize + full round-trip tests

Related PRs

PR Title Status
rh-ecosystem-edge/recert#1758 ECDSA PKCS#8 scanning support Merged
rh-ecosystem-edge/recert#1941 Ed25519 / ECDSA e2e crypto support Merged

Jira

Upstream References

Test Plan

  • CI passes
  • PrivateKey::Ec pem() / Serialize emit BEGIN PRIVATE KEY, not BEGIN EC PRIVATE KEY
  • SEC1 input still scans and stores PKCS#8 DER
  • Unit tests: test_ec_serialize_uses_correct_pem_tag, test_ec_pkcs8_full_round_trip_der_equality
  • Integration scenario test_crypto_ec_pkcs8_input.sh passes

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 commented Sep 19, 2026

Copy link
Copy Markdown
Contributor

@sebrandon1: The following tests failed, say /retest to rerun all failed tests or /retest-required to rerun all mandatory failed tests:

Test name Commit Details Required Rerun command
ci/prow/e2e-aws-ovn-single-node-recert-serial 55e7cc4 link true /test e2e-aws-ovn-single-node-recert-serial
ci/prow/ipc-e2e-flow 55e7cc4 link true /test ipc-e2e-flow
ci/prow/ibi-e2e-flow 55e7cc4 link true /test ibi-e2e-flow
ci/prow/e2e-aws-ovn-single-node-recert-parallel 55e7cc4 link true /test e2e-aws-ovn-single-node-recert-parallel

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants