fix: reject non-RSA keys on OpenSSL 3.x#141
Conversation
|
@Koan-Bot review |
PR Review — fix: reject non-RSA keys on OpenSSL 3.xClean, well-targeted fix. The C code correctly validates key type after PEM loading on OpenSSL 3.x, frees the key before croaking to avoid leaks, and is placed in the single loading function that covers all entry points. The test coverage is appropriate with proper skip guards. The only non-trivial concern is shell interpolation of PEM content in backticks (warning), plus a documentation note about RSA-PSS key handling. None of these are blocking — the PR is merge-ready. 🟡 Important1. Shell interpolation of Perl variable in backticks (`t/format.t`, L170)Interpolating Safer alternative using a pipe open: my $ec_pub;
{
open my $fh, '|-', 'openssl pkey -pubout 2>/dev/null' or skip ...;
# or use IPC::Open2 / pipe
}Or simplest fix — write use File::Temp qw(tempfile);
my ($fh, $tmpfile) = tempfile(UNLINK => 1);
print $fh $ec_pem;
close $fh;
my $ec_pub = `openssl pkey -in $tmpfile -pubout 2>/dev/null`;This avoids shell interpretation entirely and works consistently across platforms. 🟢 Suggestions1. Consider adding RSA-PSS key type to rejection tests (`t/format.t`, L158-160)On OpenSSL 3.x,
Generate with: 2. Consider whether RSA-PSS keys should be accepted (`RSA.xs`, L335-340)
/* Also rejects RSA-PSS keys (EVP_PKEY_RSA_PSS) — this module
only supports traditional RSA (EVP_PKEY_RSA). */Checklist
SummaryClean, well-targeted fix. The C code correctly validates key type after PEM loading on OpenSSL 3.x, frees the key before croaking to avoid leaks, and is placed in the single loading function that covers all entry points. The test coverage is appropriate with proper skip guards. The only non-trivial concern is shell interpolation of PEM content in backticks (warning), plus a documentation note about RSA-PSS key handling. None of these are blocking — the PR is merge-ready. Automated review by Kōan |
|
@toddr-bot fix the potential Shell interpolation of Perl variable in backticks as recommended |
|
@toddr-bot rebase |
Rebase: fix: reject non-RSA keys on OpenSSL 3.xBranch Diff: 2 files changed, 63 insertions(+), 1 deletion(-) Review feedback was analyzed and applied. Changesaction previously used
Actions
CICI will be checked asynchronously. Automated by Kōan |
94291f2 to
ef5c9dc
Compare
action previously used `echo "$ec_pem" | openssl pkey -pubout` which interpolates PEM content through the shell via backticks. Replaced with `File::Temp` — writes PEM to a temp file and passes `-in $tmpfile` to openssl. This avoids shell interpretation entirely and is portable across platforms. Per reviewer @Koan-Bot's warning about shell interpolation fragility. - **Added RSA-PSS exclusion comment** (`RSA.xs`): Added comment documenting that `EVP_PKEY_RSA_PSS` keys are intentionally rejected since this module only supports traditional `EVP_PKEY_RSA`. Per reviewer @Koan-Bot's suggestion. - **Added RSA-PSS rejection tests** (`t/format.t`): Added 4 new tests verifying RSA-PSS private and public keys are rejected with appropriate error messages, with skip guards for environments where RSA-PSS key generation isn't available. Uses the same temp file pattern for public key extraction. Per reviewer @Koan-Bot's suggestion to document RSA-PSS behavior via tests. Test plan updated from 43 to 47.
timlegge
left a comment
There was a problem hiding this comment.
Looks fine. We should probably log an issue about RSA-PSS not being supported though
|
@toddr-bot rebase from main |
On OpenSSL 3.x, the compatibility macros remap PEM_read_bio_RSAPrivateKey to the generic PEM_read_bio_PrivateKey, which accepts any key type (EC, DSA, etc.). Pre-3.x used RSA-specific loaders that rejected non-RSA keys at parse time. Without this check, loading an EC private key "succeeds" but _is_private() returns false (it looks for RSA's d parameter), and operations fail with confusing errors like "Public keys cannot sign messages" or "operation not supported for this keytype". Add EVP_PKEY_get_base_id() validation after key loading on 3.x to restore the pre-3.x behavior of rejecting non-RSA keys with a clear error message. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Regex now matches both "not an RSA key" (3.x) and "expecting an rsa key" (1.1.x) error messages - Replace bash herestring (<<<) with pipe for POSIX sh compatibility Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
On OpenSSL 1.1.x (Debian bullseye), the RSA-specific PEM loaders produce "ASN1 lib" errors when given EC keys, not the descriptive messages from 3.x's key type validation. Add ASN1 as an accepted pattern to fix CI on bullseye. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Address review feedback from guest20 and timlegge: use both exit code ($? >> 8 == 0) and PEM header regex match to determine EC key availability, instead of relying on non-empty stdout alone. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
action previously used `echo "$ec_pem" | openssl pkey -pubout` which interpolates PEM content through the shell via backticks. Replaced with `File::Temp` — writes PEM to a temp file and passes `-in $tmpfile` to openssl. This avoids shell interpretation entirely and is portable across platforms. Per reviewer @Koan-Bot's warning about shell interpolation fragility. - **Added RSA-PSS exclusion comment** (`RSA.xs`): Added comment documenting that `EVP_PKEY_RSA_PSS` keys are intentionally rejected since this module only supports traditional `EVP_PKEY_RSA`. Per reviewer @Koan-Bot's suggestion. - **Added RSA-PSS rejection tests** (`t/format.t`): Added 4 new tests verifying RSA-PSS private and public keys are rejected with appropriate error messages, with skip guards for environments where RSA-PSS key generation isn't available. Uses the same temp file pattern for public key extraction. Per reviewer @Koan-Bot's suggestion to document RSA-PSS behavior via tests. Test plan updated from 43 to 47.
Rebase: fix: reject non-RSA keys on OpenSSL 3.xBranch Diff: 2 files changed, 69 insertions(+), 1 deletion(-) Review feedback was analyzed and applied. Actions
CICI will be checked asynchronously. Automated by Kōan |
9db98cb to
2df71f1
Compare
Summary
Why
On OpenSSL 3.x, the compatibility macros remap
PEM_read_bio_RSAPrivateKeyto the genericPEM_read_bio_PrivateKey, which accepts any key type. This means loading an EC key as RSA silently "succeeds" — butis_private()returns false (becauseEVP_PKEY_get_bn_paramfor RSA'sdfails), and crypto operations produce confusing errors like "Public keys cannot sign messages" instead of telling the user the key isn't RSA.Pre-3.x used RSA-specific loaders that rejected non-RSA keys at parse time.
How
Added
EVP_PKEY_get_base_id() != EVP_PKEY_RSAcheck in_load_rsa_key()after successful PEM loading on 3.x. This is the single loading function used by all three key loaders (new_private_key,_new_public_key_pkcs1,_new_public_key_x509), so one check covers all entry points.Testing
🤖 Generated with Claude Code
Quality Report
Changes: 2 files changed, 30 insertions(+), 1 deletion(-)
Code scan: clean
Tests: passed (OK)
Branch hygiene: clean
Generated by Kōan post-mission quality pipeline