php / php/php-src

Allow constructing a public-only RSA key with openssl_pkey_new()

Đang mở
#22,702 0 bình luận 0 reaction 0 người được giao Xem trên GitHub

Chưa có ai nhận issue này.

Extension: openssl Feature Status: Verified
Ngôn ngữ chính
C
Star
40.4k
Fork
8.2k
Merge trung bình
2 ngày 13 giờ
Pull request đã merge (30 ngày)
96

Mô tả

Description

openssl_pkey_new() can construct a public key directly from raw parameters for every asymmetric key type except RSA:

  • ['ec' => ['curve_name' => …, 'x' => …, 'y' => …]] → public EC key ✅
  • ['ed25519' => ['pub_key' => …]] / ['ed448' => …] → public EdDSA key ✅
  • ['dsa' | 'dh' => ['pub_key' => …]] → public key ✅
  • ['rsa' => ['n' => …, 'e' => …]] → ❌ a private exponent d is mandatory, and the result is always flagged private

So there is no way to obtain an RSA public key object from n and e that openssl_verify() will accept:

// (1) Without d — construction fails outright:
var_dump(openssl_pkey_new(['rsa' => ['n' => $n, 'e' => $e]])); // bool(false)

// (2) With a dummy d — builds, but is flagged private, so verify() refuses it:
$k = openssl_pkey_new(['rsa' => ['n' => $n, 'e' => $e, 'd' => "\x00"]]);
openssl_verify($msg, $sig, $k, OPENSSL_ALGO_SHA256);
// Warning: openssl_verify(): Don't know how to get public key from this private key
// Warning: openssl_verify(): Supplied key param cannot be coerced into a public key

The only workarounds today are to build a throwaway "private" key with a placeholder d, then round-trip it back out via openssl_pkey_get_details($k)['key'] and reload with openssl_pkey_get_public(), or to hand-encode a DER SubjectPublicKeyInfo in userland. Both are awkward for something every other key type supports natively.

Why this is worth adding

a) Consistency — RSA is the only outlier. In ext/openssl, php_openssl_pkey_init_dsa(), _dh(), _ec(), and the curve-25519/448 path all take an is_private out-parameter, derive it from whether private material was supplied, and build public-only keys just fine. php_openssl_pkey_init_rsa() alone (i) hard-requires d, (ii) never computes is_private, and (iii) its caller in openssl_pkey_new() hardcodes is_private = true. Bringing RSA in line with the others is a small, localized change.

b) WebAuthn / COSE key conversion. WebAuthn credential public keys arrive as COSE_Key maps (RFC 9052; RSA parameters per RFC 8230) — i.e. raw n and e bytes for RS256. Relying parties need to turn those into an OpenSSL key purely to verify assertion signatures. For EC2 (ES256) and OKP (EdDSA) keys this is already a clean one-liner via openssl_pkey_new(); for RSA it forces the dummy-d PEM round-trip above or a hand-rolled ASN.1 encoder. Public-only RSA construction would let libraries handle all three COSE key types uniformly, with zero userland ASN.1.

Suggested implementation

Mirror the existing init_dsa/init_ec pattern:

  • give php_openssl_pkey_init_rsa() a bool *is_private out-param;
  • make d optional (require n and e), push OSSL_PKEY_PARAM_RSA_D only when present, and set *is_private = (d != NULL);
  • select EVP_PKEY_PUBLIC_KEY vs EVP_PKEY_KEYPAIR accordingly (v3 backend), and pass d == NULL through to RSA_set0_key() (v1 backend, which already permits it);
  • have the rsa branch of openssl_pkey_new() pass the flag to php_openssl_pkey_object_init(), exactly like the dsa/ec branches.

This is purely additive — keys constructed with d stay flagged private, so no BC break. Happy to send a PR with tests if this is welcome.

PHP Version

master (8.5-dev); behaviour also confirmed on 8.4.23.

Hướng dẫn đóng góp

Mở hướng dẫn đóng góp

Bắt đầu từ đâu

  1. Đọc hết issue, rồi đọc hướng dẫn đóng góp của dự án.
  2. Bình luận trên issue rằng bạn sẽ nhận — tránh hai người làm cùng một việc.
  3. Fork repository và làm thay đổi trên một nhánh.
  4. Mở pull request có tham chiếu số hiệu của issue.

Hướng nghiên cứu

Bắt đầu tại php_openssl_pkey_init_rsa() và nhánh rsa của openssl_pkey_new(), so sánh chúng với các đường dẫn init_dsa và init_ec hiện có. Xác minh rằng các khóa RSA chỉ có n/e được openssl_verify() chấp nhận, trong khi các khóa có d vẫn là khóa riêng tư; thêm các bài kiểm thử bao phủ cả hai trường hợp.

Do mô hình lập chỉ mục viết ra từ nội dung của issue.

Đánh giá

Công nghệ
c, php
Lĩnh vực
cryptography
Loại issue
Tính năng
Độ khó
3/5
Thời gian dự kiến
1-2 ngày
Mức độ hoạt động
Ít trao đổi
Độ rõ ràng
Đặc tả rõ ràng
Mức phù hợp với người mới
68/100

Nhận issue mới trong hộp thư của bạn

Bản tóm tắt ngắn những issue GitHub phù hợp với người mới.