繁体   English   中英

使用 OpenSSL 和受密码保护的 SSH 密钥加密 PHP 中的大量输入?

[英]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加密对称密钥

解密:

  • 使用 RSA 解密对称密钥(RSA 密钥可以受密码保护)
  • 使用对称密钥解密大数据,它可以解密的大小没有限制。

这是可行的,因为 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.

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