简体   繁体   中英

How to properly encrypt a JS generated RSA private key with a passphrase?

I have a php back-end that previously generated RSA private/public keypairs on its own, encrypting the private part with a given passphrase.

Now I'm using this library: http://travistidwell.com/jsencrypt/ to generate a keypair on client side. But I didn't find how to encrypt the private key with a passphrase using this library. So I tried using this: http://www.movable-type.co.uk/scripts/aes.html but it seems that a key I get doesn't work, I can't encrypt/decrypt using it on my php back-end and different keys management apps don't recognize the key.

What am I doing wrong and how to successfully encrypt the original JSEncrypt'ed private key properly with a passphrase?

This is how the keypair was generated on PHP:

                $config = array(
                    "digest_alg" => "sha256",
                    "private_key_bits" => 2048,
                    "private_key_type" => OPENSSL_KEYTYPE_RSA,
                    "encrypt_key" => true
                );
                $keypair = openssl_pkey_new($config);

                $pkey_pass = '123';

                openssl_pkey_export($keypair, $privKey, $pkey_pass, $config);
                $fp = fopen($keys_folder . '/private.pem', 'w');
                fwrite($fp, $privKey);
                fclose($fp);

                $pubKey = openssl_pkey_get_details($keypair);
                $fp = fopen($keys_folder . '/public.pem', 'w');
                fwrite($fp, $pubKey);
                fclose($fp);

Maybe you could adapt code from phpseclib . Quoting it:

if (!empty($this->password) || is_string($this->password)) {
    $iv = Random::string(8);
    $symkey = pack('H*', md5($this->password . $iv)); // symkey is short for symmetric key
    $symkey.= substr(pack('H*', md5($symkey . $this->password . $iv)), 0, 8);
    $des = new TripleDES();
    $des->setKey($symkey);
    $des->setIV($iv);
    $iv = strtoupper(bin2hex($iv));
    $RSAPrivateKey = "-----BEGIN RSA PRIVATE KEY-----\r\n" .
                     "Proc-Type: 4,ENCRYPTED\r\n" .
                     "DEK-Info: DES-EDE3-CBC,$iv\r\n" .
                     "\r\n" .
                     chunk_split(base64_encode($des->encrypt($RSAPrivateKey)), 64) .
                     '-----END RSA PRIVATE KEY-----';
} else {
    $RSAPrivateKey = "-----BEGIN RSA PRIVATE KEY-----\r\n" .
                     chunk_split(base64_encode($RSAPrivateKey), 64) .
                     '-----END RSA PRIVATE KEY-----';
}

src: https://raw.githubusercontent.com/phpseclib/phpseclib/master/phpseclib/Crypt/RSA.php

How to encrypt a JS generated RSA private key with a passphrase?

You have one of two choices. First, encrypt the entire key beofre it reaches disk. Then decrypt it before you use it. In this case, you treat the key like a file you want to encrypt.

Second, use PKCS #8, aka RFC 5208, Public-Key Cryptography Standards (PKCS) #8: Private-Key Information Syntax Specification Version 1.2 . In particular, see section 6 of RFC 5208, EncryptedPrivateKeyInfo .

You have a third option, but its not advised. The third option is to use an encrypted PEM encoding. Its not advisable because its been superseded by PKCS #8.

In the future, you will have a fourth option, and that is to use WebCrypto to store your key. In this case, you moved the problem of secure storage to the platform.

Unfortunately, I don't know about the library you are using, so I don't know what it may (or may not offer). But the answers above cover the OpenSSL bits of your question.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM