phpseclib RSA解密与openssl

phpseclib RSA Decryption with openssl

我使用 phpseclib 进行加密,openssl 解密有一些问题

//generate keys
extract($rsa->createKey(1024));
file_put_contents("public.pem",$publickey);
file_put_contents("private.pem",$privatekey);

加密文本

    $rsa->loadKey($public_key); // public key
    $plaintext = '...';
    $ciphertext = $rsa->encrypt($plaintext);
    file_put_contents("ciphertext.txt",$ciphertext);

所以在 linux 我正在解密 :

xxd -p ciphertext.txt | tr -d '\n' 

最后点赞下面的命令

openssl rsautl -decrypt -inkey private.pem

得到这个错误:

error:0407106B:rsa routines:RSA_padding_check_PKCS1_type_2:block type is not 02:rsa_pk1.c:190:
error:04065072:rsa routines:RSA_EAY_PRIVATE_DECRYPT:padding check failed:rsa_eay.c:674:

我正在为 phpseclib 做这些设置:

define('CRYPT_RSA_PKCS15_COMPAT', true);

现在在 openssl 上出现此错误:

error:04065084:rsa routines:RSA_EAY_PRIVATE_DECRYPT:data too large for modulus:rsa_eay.c:590:

public键:

-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDGCglgIcCG5a8xlZHEDRtQQTc4
kfxENNBtVN8bE4errA06mJ10WavP2Hg+k11NQip71IQPfIF9jlk1CsqT5ZHXOrOq
RmufHFLa3fiuPvFiMB1NjK4F28Gk4LwyZrfTWc2V6S0xpL5XkFeWRW6I69xckOXj
GqkC5dsWv/IlvPeVbwIDAQAB
-----END PUBLIC KEY-----

私钥:

-----BEGIN RSA PRIVATE KEY-----
MIICXQIBAAKBgQDGCglgIcCG5a8xlZHEDRtQQTc4kfxENNBtVN8bE4errA06mJ10
WavP2Hg+k11NQip71IQPfIF9jlk1CsqT5ZHXOrOqRmufHFLa3fiuPvFiMB1NjK4F
28Gk4LwyZrfTWc2V6S0xpL5XkFeWRW6I69xckOXjGqkC5dsWv/IlvPeVbwIDAQAB
AoGBAJj1yZYJm8XVg8Kdjs/Je846AOfdweYAkPfRNN2Z8RFEu5cFp5/lXtITlZRn
iAoTT/MDCtlXRkDvALH6Wstu5nvk+Xz5dFlZ6OUmK04YakHc0N5NABMygvCmGdnr
BoTJx70dPVFXqiq/ft5KRLEdxVWvex+odgWunqSJXMperrhxAkEA89/A7jadwCjA
iyaTmGEMqerN4XdTtQj4NpKorTv9FlmU9U9XWmv0wk5ExmUzjo9gs71a06/ecaHc
xJUj3X1O5wJBAM/i2zmAg1vhR/s23b70LPf4O1/d5GdQTJwHhZp4OMzW6qt7qmRR
vIzHHPbljOwvUzNtoXhez3TNsgtWg9XaXDkCQQDujYJgwoYfEP3/X9XiqZREpg2M
LjhwjvyWDXH4OwT/ltNR/rF5Hr8GTp+R3i7HldLHH0O4bIFQcD/PAABcSZYjAkAZ
QxwY1MEhvTKeGIDB37JHP+cXM0O6OkvU+iUGLG3alpNV22VNY5FiGiAu8J47ZVTa
/wuMMRlMvGJSdmT2694hAkBjqYMwpYg+MXhY9zKYM8lGISpirz+pKSpKwB90FASY
4AIuFBFHV5F5iqrSKNU39Rv+alYAKP/UuqPVH84GlWjl
-----END RSA PRIVATE KEY-----

首先,phpseclib默认做OAEP padding。它更安全但不太常见。尝试做 $rsa->setEncryptionMode(CRYPT_RSA_ENCRYPTION_PKCS1);.

其次,RSA 确实对可以加密的数据大小有上限。对于 PKCS1,它是模数的大小 - 11(例如 ($rsa->getSize() >> 3) - 11)。我知道您要加密的数据有多大,但我猜它比那更大。所以 phpseclib 在这种情况下所做的是它会对其执行 str_split 然后连接每个连续的密文。我的猜测是你的情况就是这样。因此,您要么需要加密较少的数据,要么想出一种不同的方法。例如。加密对称密钥,然后使用对称密钥加密数据。

一些评论。

  1. 您可能会发现此页面有帮助:

    http://phpseclib.sourceforge.net/interop.html#rsaencpkcs1,p1phpseclib,p2openssl

  2. 我在之前的回答中建议您 $rsa->setEncryptionMode(CRYPT_RSA_ENCRYPTION_PKCS1);。你最近编辑的post仍然没有你这样做:

    $rsa->loadKey($public_key); // public key
    $plaintext = '...';
    $ciphertext = $rsa->encrypt($plaintext);
    file_put_contents("ciphertext.txt",$ciphertext);
    

    仅当您处于 PKCS1 模式而您未处于 PKCS1 模式时,执行 define('CRYPT_RSA_PKCS15_COMPAT', true); 才有效。

  3. 你 post 说你正在做 openssl rsautl -decrypt -inkey private.pem。我知道整个 xxd 命令应该如何工作,但通常情况下,使用 OpenSSL,您需要通过执行 -in ciphertext.txt 来指定输入文件,而您没有这样做。

工作代码

使用你的 public 和私钥这对我有用:

<?php
include('Crypt/RSA.php');

$rsa = new Crypt_RSA();

$public_key = '-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDGCglgIcCG5a8xlZHEDRtQQTc4
kfxENNBtVN8bE4errA06mJ10WavP2Hg+k11NQip71IQPfIF9jlk1CsqT5ZHXOrOq
RmufHFLa3fiuPvFiMB1NjK4F28Gk4LwyZrfTWc2V6S0xpL5XkFeWRW6I69xckOXj
GqkC5dsWv/IlvPeVbwIDAQAB
-----END PUBLIC KEY-----';
$rsa->loadKey($public_key); // public key
$rsa->setEncryptionMode(CRYPT_RSA_ENCRYPTION_PKCS1);
$plaintext = '...';
$ciphertext = $rsa->encrypt($plaintext);
file_put_contents("ciphertext.txt",$ciphertext);

...在 CLI 上:

openssl rsautl -decrypt -inkey private.pem -in ciphertext.txt

这是我得到的输出:

...