【问题标题】:How to properly encrypt a JS generated RSA private key with a passphrase?如何使用密码正确加密 JS 生成的 RSA 私钥?
【发布时间】:2015-05-13 05:32:15
【问题描述】:

我有一个 php 后端,它以前自己生成 RSA 私钥/公钥对,用给定的密码加密私有部分。

现在我正在使用这个库:http://travistidwell.com/jsencrypt/ 在客户端生成密钥对。但是我没有找到如何使用这个库使用密码来加密私钥。所以我尝试使用这个:http://www.movable-type.co.uk/scripts/aes.html 但似乎我得到的密钥不起作用,我无法在我的 php 后端使用它进行加密/解密,并且不同的密钥管理应用程序无法识别密钥。

我做错了什么以及如何使用密码正确地加密原始 JSEncrypt 的私钥?

这是在 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);

【问题讨论】:

  • 我只是使用 JSEncrypt 生成一个密钥,并使用密码将其放入第二个脚本的演示文本区域,结果密钥无法被任何东西识别为私钥......我将更新关于 PHP 之前如何生成密钥对的问题。

标签: php encryption openssl private-key


【解决方案1】:

如何使用密码加密 JS 生成的 RSA 私钥?

您有两个选择之一。首先,在整个密钥到达磁盘之前对其进行加密。然后在使用之前对其进行解密。在这种情况下,您将密钥视为要加密的文件。

其次,使用 PKCS #8,也就是 RFC 5208, Public-Key Cryptography Standards (PKCS) #8: Private-Key Information Syntax Specification Version 1.2。特别是,请参阅 RFC 5208 的第 6 节,EncryptedPrivateKeyInfo

您有第三种选择,但不建议这样做。第三种选择是使用加密的 PEM 编码。不建议这样做,因为它已被 PKCS #8 取代。

将来,您将有第四种选择,那就是使用WebCrypto 来存储您的密钥。在这种情况下,您将安全存储的问题转移到了平台上。

不幸的是,我不知道您正在使用的图书馆,所以我不知道它可能(或可能不提供)。但上面的答案涵盖了您问题的 OpenSSL 位。

【讨论】:

    【解决方案2】:

    也许您可以修改代码from phpseclib。引用它:

    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

    【讨论】: