I am having trouble creating / using RSA keys created and used in PHP. The problem is that (public and private) keys must be exchanged between different servers (for example, when moving a user account).
Now, opensl-lib PHP does not provide detailed information about the format in which keys are generated. The latest documentation at http://php.net/manual/en/function.openssl-pkey-export.php says that it is in PEM format but does not say if it is in PKCS # 1 or PKCS # 8
In addition, the headers and trailers of the PEM private key are different between PHP versions, as shown in the following code:
<?php $config = array( "digest_alg" => 'sha512', "private_key_bits" => 4096, "private_key_type" => OPENSSL_KEYTYPE_RSA ); $keyPair = openssl_pkey_new($config); $privateKey = NULL; openssl_pkey_export($keyPair, $privateKey); var_dump($privateKey); $keyDetails = openssl_pkey_get_details($keyPair); $publicKey = $keyDetails['key']; var_dump($publicKey); die(); ?>
outputs different things:
PHP v 5.4:
string(3272) "-----BEGIN PRIVATE KEY----- MIIJRAIBADANBgkqhkiG9w0BAQEFAASCCS4wggkqA//... -----END PRIVATE KEY----- " string(800) "-----BEGIN PUBLIC KEY----- MIICIjANBgkqhkiG9w0BAQEFAAO//... -----END PUBLIC KEY----- "
PHP v 5.5:
string(3272) "-----BEGIN RSA PRIVATE KEY----- MIIJRAIBADANBgkqhkiG9w0BAQEFAASCCS4wggkqA//... -----END RSA PRIVATE KEY----- " string(800) "-----BEGIN PUBLIC KEY----- MIICIjANBgkqhkiG9w0BAQEFAAO//... -----END PUBLIC KEY----- "
PHP v 5.6:
string(3272) "-----BEGIN PRIVATE KEY----- MIIJQgIBADANBggsdisdVUCJDSQCjqgl2XqzR+bSv//... -----END PRIVATE KEY----- " string(800) "-----BEGIN PUBLIC KEY----- MIICIjANBgkqhkiG9w0BsdvQEFAAOdfAg8AMIICFAgEAo6oJdl6s0fm0r7QlaN/U//... -----END PUBLIC KEY----- "
Thus, the title / trailer of the private key changes depending on which version of PHP you are using. This will not be a real problem, but as it turned out, a system that would create a key header with "RSA" would not be able to use a user key WITHOUT "RSA", for example, openssl_sign (): you will get that "the provided key cannot be forced to enter into the private key "... And here he becomes promiscuous.
According to https://tls.mbed.org/kb/cryptography/asn1-key-structures-in-der-and-pem there should be a difference between the private keys of the PEM formats with "RSA" in the header, and those PKCS # 1 and PKCS # 8, i.e. with additional information about the algorithm, etc. or not.
I am having serious problems because of this. The same software written for PHP5.6 cannot run on PHP5.5. On can use a workaround, replacing 5.5 headers with 5.6 compatible ones manually, but it will just be a dirty hack. Is there a “good” way to handle this?
When configured, this replacement code will attempt to create a private key, extract the header, and "remember it." Then all keys used at runtime will be checked. If the headers found do not match the "local" ones, they will need to be exchanged.
But I assume that there is some kind of configuration option (which I have not been able to find yet), where can I configure which format is used?
Next, a more interesting question: what format is created using openssl? PKCS # 1? PKCS # 8? Is it also customizable?