[英]Encrypt large inputs in PHP using OpenSSL and a password-protected SSH key?
我有一个 CLI 工具,可以将加密数据写入本地文件系统,这些数据永远不会通过 .network 传输。
我可以使用受密码保护的 SSH 密钥加密数据,但由于生成的密钥是不对称的 (RSA),它只能加密/解密比密钥短的数据,这对我的用例来说并不理想:
我生成 SSH 密钥:
$config = [
"private_key_bits" => 4096,
"private_key_type" => OPENSSL_KEYTYPE_RSA,
"encrypt_key" => true,
"encrypt_key_cipher" => OPENSSL_CIPHER_AES_256_CBC
];
openssl_pkey_export( openssl_pkey_new( $config ), $privateKeyOut, $password );
if ( ! file_put_contents( $_SERVER['HOME'] . '/.ssh/fookey.pem', $privateKeyOut ) ) {
throw new \RuntimeException( 'Could not write private key.' );
}
然后我加密/解密如下:
public function encrypt( string $plain_text ): string {
$key = openssl_pkey_get_private( file_get_contents( $_SERVER['HOME'] . '/.ssh/fookey.pem' ), App::getVar( 'enc_password' ) );
$success = openssl_private_encrypt( $plain_text, $cipher_text, $key );
if ( ! $success ) {
throw new \RuntimeException( 'Encrypt failed.' );
}
return base64_encode( $cipher_text );
}
public function decrypt( string $cipher_text ): string {
$key = openssl_pkey_get_private( file_get_contents( $_SERVER['HOME'] . '/.ssh/fookey.pem' ), App::getVar( 'enc_password' ) );
$success = openssl_private_decrypt( base64_decode( $cipher_text ), $plain_text, $key );
if ( ! $success ) {
throw new \RuntimeException( 'Decrypt failed.' );
}
return $plain_text;
}
PS: App::getVar( 'enc_password' )
的值由用户在运行脚本时通过交互式输入提供。
是否可以调整此脚本以改为使用可以加密/解密大输入的对称加密密钥?
回答我自己的问题,我最终弄明白了。 感谢@TimWolla 为我指明了正确的方向。
我正在使用 laminas /crypt package( zend/crypt的后继者)。 它支持混合 RSA 加密:
加密:
random_bytes(32)
的东西生成随机对称密钥解密:
这是可行的,因为 RSA 不能加密长数据,但我们可以使用随机字符串来加密大数据并加密随机字符串。
根据 laminas/crypt 混合示例:
use Laminas\Crypt\Hybrid;
use Laminas\Crypt\PublicKey\RsaOptions;
// Generate public and private key
$rsaOptions = new RsaOptions([
'pass_phrase' => 'test'
]);
$rsaOptions->generateKeys([
'private_key_bits' => 4096
]);
// Get keys as strings. This can be saved to file, etc.
$publicKey = $rsaOptions->getPublicKey()->toString();
$privateKey = $rsaOptions->getPrivateKey()->toString();
// Encrypt / Decrypt.
$hybrid = new Hybrid();
$ciphertext = $hybrid->encrypt('message', $publicKey);
$plaintext = $hybrid->decrypt($ciphertext, $privateKey, 'test'); // pass-phrase
printf($plaintext === 'message' ? "Success\n" : "Error\n");
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.