[php-src] Issue #21083: openssl_pkey_new() fails for EC keys on OpenSSL 3.6 - incorrectly requires private_key_bits
[email protected] (ben182)
| Newsgroups | php.bugs |
|---|---|
| Message-ID | <[email protected]> |
Issue: https://github.com/php/php-src/issues/21083
Author: ben182
### Description
### Description
When using `openssl_pkey_new()` to generate EC keys with OpenSSL 3.6.0, the function incorrectly requires
`private_key_bits` even though this parameter is not relevant for elliptic curve keys (the key size is determined
by the curve itself).
The workaround requires setting `private_key_bits` to 384, which is semantically incorrect for a 256-bit curve
like `prime256v1`. Setting it to 256 (the actual curve size) still fails.
The OpenSSL CLI generates EC keys without issues (`openssl ecparam -name prime256v1 -genkey -noout`), suggesting
this is a PHP bindings issue.
**Environment:** PHP 8.5.2, OpenSSL 3.6.0
### Possible cause
OpenSSL 3.6 requires C-99 compilers (no longer ANSI-C), which changes integer behavior and sizes. Additionally,
OpenSSL 3.6 modified EC keygen error handling.
The `private_key_bits` parameter should not apply to EC keys at all - the curve name (e.g., `prime256v1`)
implicitly defines the key size. It appears PHP's OpenSSL bindings incorrectly validate `private_key_bits` for EC
keys when linked against OpenSSL 3.6.
This same error has been reported in other projects:
- https://community.librenms.org/t/new-install-openssl-pkey-new-private-key-length-must-be-at-least-384-bits-conf
igured-to-0/22396
- https://github.com/laravel/passport/issues/757
### References
- https://github.com/web-push-libs/web-push-php/issues/445
- https://github.com/openssl/openssl/blob/openssl-3.6.0/CHANGES.md
- https://github.com/openssl/technical-policies/pull/50 (C-99 requirement)
---
The following code:
```php
<?php
$key = openssl_pkey_new([
'curve_name' => 'prime256v1',
'private_key_type' => OPENSSL_KEYTYPE_EC,
]);
var_dump($key);
var_dump(openssl_error_string());
Resulted in this output:
bool(false)
string(63) "Private key length must be at least 384 bits, configured to 0"
But I expected this output instead:
object(OpenSSLAsymmetricKey)#1 (0) {}
bool(false)
### PHP Version
```plain
PHP 8.5.2 (cli) (built: Jan 17 2026 23:04:39) (NTS clang 15.0.0)
Copyright (c) The PHP Group
Built by Laravel Herd
Zend Engine v4.5.2, Copyright (c) Zend Technologies
with Zend OPcache v8.5.2, Copyright (c), by Zend Technologies
```
### Operating System
macOS (Darwin 25.2.0)