Search code examples
phpcryptographyelliptic-curvephp-openssl

Why can't I use key lengths < 384bit for EC in PHP OpenSSL?


It is obvious to me that a 384bit RSA Key is tremendously insecure. There is a similar question regarding RSA: Why is keysize < 384 bits deemed too small for openssl_pkey_new()?

However, a 384bit EC key is currently seen as extremely secure. In my case, 384bit are too long which is why I'd like to use 256bit keys.

Why does the following code throw Warning: openssl_pkey_new(): private key length is too short; it needs to be at least 384 bits, not 256?

<?php
$config = array(
    "private_key_type" => OPENSSL_KEYTYPE_EC,
    "private_key_bits" => 256,
    "curve_name" => "prime256v1"
);

// Create the private and public key
$res = openssl_pkey_new($config);

Am I doing something wrong or does openssl_pkey_new() really have the same requirements for RSA and EC?


Solution

  • From the PHP source code it can be seen that openssl_pkey_new calls php_openssl_generate_private_key, which checks the key size passed with private_key_bits regardless of the key type and returns the posted error if the size is less than MIN_KEY_LENGTH, which is defined as 384. This applies to the current version (v 7.4.7) down to v 4.0. In contrast to the current version, v 4.0 only supports RSA keys, so it can be concluded from this that the key size of 384 bits refers to RSA keys.

    Since EC keys are smaller than RSA keys with comparable security (NIST and ECRYPT, Chapter 7, Recommended Key Sizes), a key type-specific check would be more useful. A minimum length for EC keys of 384 bits is not reasonable. But also for RSA the value of 384 bits is too small from today's view.

    In php_openssl_generate_private_key it can also be seen that during key generation the key size is only used in the context of RSA, DSA and DH keys, but not at all in the context of EC keys, where the curve name is used instead. I.e. the key size specified with private_key_bits is not required for the context of EC keys (and probably not intended) and should therefore be omitted, which also avoids the error message:

    <?php
    $config = array(
        "private_key_type" => OPENSSL_KEYTYPE_EC,
        "curve_name" => "prime256v1"
    );
    
    $res = openssl_pkey_new($config);
    print_r(openssl_pkey_get_details($res));
    ?>
    

    For completeness: If the key size is not specified with private_key_bits, it is initialized with a default value from the OpenSSL configuration file, which is 2048 bits for the current version. This value corresponds to the current recommendation for RSA (NIST, Recommendation for Key Management, 2.2.1 Recommended Key Sizes and Algorithms) and is also the reason why the error message is not triggered in the context of EC keys.