我得到了一个PHP应用程序,该应用程序必须使用私钥加密字符串。我知道,使用私钥加密有点少见,但这就是这样。
使用非常旧版本的phpseclib,该应用程序是PHP5。现在,我们必须迁移到PHP8,需要升级Phpseclib。我整天都在Google-Google-ling,但我无法弄清楚如何迁移旧版代码。传统代码看起来像这样:
define('RSA_PRIV_KEY', "<base64 encoded key>);
$rsa = new Crypt_RSA();
$rsa->loadKey(RSA_PRIV_KEY);
$result = base64_encode($rsa->encrypt("my fancy string"));
我看了phpseclib3,但根本无法使其工作。对于Openssl.eDit用phpseclib3
进行的最佳尝试
// this works
$key = PublicKeyLoader::loadPrivateKey(RSA_PRIV_KEY);
// this works although my IDE claims that no method named getLoadedFormat() exists. It gives me 'PKCS1'
$this->log->info(">>>" . $key->getLoadedFormat());
// This does not work cause 'Call to undefined method phpseclib3\Crypt\RSA\PrivateKey::encrypt()'
$this->log->info(">>>" . $key->encrypt("my fancy string"));
define('RSA_PRIV_KEY', "<base64 encoded key>");
$privkey = openssl_pkey_get_private(RSA_PRIV_KEY);
$encrypted = "";
openssl_private_encrypt("my fancy string", $encrypted, $privkey);
$this->log->info(">>>" . base64_encode($encrypted));
encrypt()
decrypt()
功能。 但是,可以通过将公共和私人指数交换在钥匙中,然后使用公共密钥加密并照常使用私钥进行加密来将功能移植到V3。示例:通过已发布的V1代码生成的V3中的密文的解密:
$privateKeyPem = "-----BEGIN PRIVATE KEY-----
MIIEvg...
-----END PRIVATE KEY-----";
$privateKeySwapped = null;
$publicKeySwapped = null;
swapKeys($privateKeyPem, $privateKeySwapped, $publicKeySwapped);
$ciphertext = base64_decode('<Base64 encoded ciphertext generated with the posted v1 code>');
$decrypted = $privateKeySwapped->withHash('sha1')->withMGFHash('sha1')->decrypt($ciphertext);
print($decrypted . PHP_EOL); // my fancy string
function swapKeys($privateKeyPem, &$privateKeySwapped, &$publicKeySwapped) {
$privateKey = PublicKeyLoader::load($privateKeyPem);
$privateKeyParams = unserialize($privateKey->toString('Raw'));
$privateKeyParamsSwapped = [
'e' => $privateKeyParams['d'],
'n' => $privateKeyParams['n'],
'd' => $privateKeyParams['e'],
'p' => $privateKeyParams['primes'][1],
'q' => $privateKeyParams['primes'][2]
];
$privateKeySwapped = PublicKeyLoader::loadPrivateKey($privateKeyParamsSwapped);
$publicKeyParamsSwapped = [
'e' => $privateKeyParams['d'],
'n' => $privateKeyParams['n']
];
$publicKeySwapped = PublicKeyLoader::loadPublicKey($publicKeyParamsSwapped);
}
必须考虑到V1
默认使用SHA-1用于OAEP-和MGF1-二元,而V3则默认使用SHA-256,以便在V3中,必须将两个消化物明确设置为SHA-1.
。 注意,严格来说,“与私钥”的过程完全不是定义的(但仅(1)“与publicKey”/“与私有键
”和(2)“和(2)”“/”与public key键syperification the the the private键 通常“与私有键”的释义是指签名,在这里也可能是这种情况。因此,许多图书馆(如果它们完全支持这样的过程)在引擎盖下(并使用填充进行签名),并且与phpseclib/v1不同,如上所述,它确实加密了(用OAEP和交换了指数)! 还请注意,发布的PHP/OPENSL代码在您的答案中,PKCS#1 V1.5填充物生成了一个签名,其中(未解决的)消息直接签名(而不是digeStinfo值的DER编码,实际上应该在rfc 80171717
rfc8017)中遵守规范。 它甚至可能是您需要的,但是它与问题中发布的phpseclib/v1代码实现的逻辑不兼容。