Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to change the passphrase of a private key using PHP's OpenSSL module?

I'm using PHP's OpenSSL module for asymmetric encryption; openssl_pkey_new(), openssl_pkey_export(), and openssl_pkey_get_details() to create the keypair, and openssl_public_encrypt and openssl_private_decrypt() to encrypt and decrypt data.

How can I change the passphrase associated with the private key? Is this possible with the OpenSSL module, or do I have to create a new keypair? That would be extremely inconvenient and require the server to re-encrypt potentially thousands of files on a regular Basis.

Thanks!

like image 591
Sam Tuke Avatar asked Nov 27 '12 16:11

Sam Tuke


People also ask

How do you change a PEM pass phrase?

To change the passphrase you simply have to read it with the old pass-phrase and write it again, specifying the new pass-phrase. The first time you're asked for a PEM pass-phrase, you should enter the old pass-phrase. After that, you'll be asked again to enter a pass-phrase - this time, use the new pass-phrase.

What is passphrase for PGP key?

PGP uses a passphrase to encrypt your private key on your machine. Your private key is encrypted on your disk using a hash of your passphrase as the secret key. You use the passphrase to decrypt and use your private key. A passphrase should be hard for you to forget and difficult for others to guess.

What is PEM pass phrase?

Enter PEM pass phrase: You are about to be asked to enter information that will be incorporated into your certificate request. What you are about to enter is what is called a Distinguished Name or a DN.


1 Answers

I've needed to do this for a little project I've been building in the evenings.

We know the following creates a new key pair (public/private):

function newPair (&$private, &$public, $passphrase=null) {
    $res = openssl_pkey_new ();
    if ($res === false) {
        throw new Exception ("Key generation failed: ".openssl_error_string ());
        return false;
    }
    // Sets private by reference
    if (openssl_pkey_export ($res, $private, $passphrase) === false) {
        throw new Exception ("Private key export failed: ".openssl_error_string ());
        return false;
    }
    // Array returns, contains "key" element.
    $public = openssl_pkey_get_details($res);
    if ($public === false) {
        throw new Exception (openssl_error_string ());
        return false;
    }
    $public = $public["key"];
    return true;
}

open_ssl_pkey_export() does the passphrase magic. So we can change the passphrase as so:

function changePassphrase ($private, $old, $new=null) {
    $res = openssl_pkey_get_private ($private, $old);
    if ($res === false) {
        throw new Exception ("Loading private key failed: ".openssl_error_string ());
        return false;
    }
    if (openssl_pkey_export ($res, $result, $new) === false) {
        throw new Exception ("Passphrase change failed: ".openssl_error_string ());
        return false;
    }
    return $result;
}

I hope you can follow what we've done here ... ! (Obviously the exception throwing is purely optional ... I've just pulled the code verbatim from my codebase.)

changePassphrase() takes the private key as a string, along with the current and new passphrases. We use openssl_pkey_get_private() to retrieve a handle to the private key, unlocking it with the old passphrase.

(It's worth noting that the passphrase is literally used to encrypt the private key, which may sound a little double-dutch! [Encrypting the encryption key ... ?!] openssl_pkey_get_private() returns FALSE if it fails to interpret the key - i.e. if the passphrase is wrong, and the private key decrypts to an invalid value. Make sense?)

Having unlocked the private key with the old passphrase, we take the OpenSSL key handle and pass it to openssl_pkey_export() - just like we did after creating it in the first place (via openssl_pkey_new()) providing the new passphrase ... and hey-presto.

I hope my code example reads cleanly, I've tried to write it in a fashion that's easy to understand and follow, without unnecessary "compression" and short-cutting.

Good luck!

like image 155
wally Avatar answered Nov 01 '22 08:11

wally