-
Notifications
You must be signed in to change notification settings - Fork 8k
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 - passport:install error (openssl_pkey_new(): private key length is too short; it needs to be at least 384 bits, not 0) laravel/passport#757
References
- openssl_pkey_new() fails on OpenSSL 3.6 - missing private_key_bits parameter web-push-libs/web-push-php#445
- https://github.com/openssl/openssl/blob/openssl-3.6.0/CHANGES.md
- Switch to C99 without the features that became optional in C11 openssl/technical-policies#50 (C-99 requirement)
The following code:
<?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
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)