RSA 签名验证 - OpenSSL 与 phpseclib

RSA Signature Verify - OpenSSL vs phpseclib

我有以下代码:

$publicKey = [
    "e" => new phpseclib\Math\BigInteger('65537'),
    "n" => new phpseclib\Math\BigInteger('e6d6ac718b38858e88878244b4b04e3c76dbba996ecde38be59476e6ccd8dbb52ee7f2b4524136fffc397a5c9181fc33fe84d2b82fe3a1a9edfec6584c3dba420bf93778d73b0f390b9d9879db22baaa38ed95ac47ad9fd6a8a187ac6e9cc7feb3d8438bdaf526f8386709ea5670eddb625a62c6e185ad8c6b0b3907918621c7a56d73d41385409e6533b5f62eda69aab2623ecd4880debe8ab686078b2a4c90332e8352216accc713075a0c66326479e28cb4c50b622dc1289ef037d22590613f27dd06d03454173bcde930bb0ffae9e0f02876a5ad382dffdd688e2bc3accca40911116ca14a158437095f5022aa578b59adf7c7c0d138ef57280077f12165', 16),
];
$signedData = hex2bin("49960de5880e8c687434170f6476605b8fe4aeb9a28632c7995cf3ba831d9763050000001a48efa635498753d349af3b7b7c19ad3162f599dac711a5408114d6e0077857c1");
$signature = hex2bin("a6b45e8f08daae55363ab0c6aef9a0d9a3912863997041350a9dc6590072abee3ea7cd11ff6e9bb6361c262d6520d5345af032d79d13f05ef15a9152ce2784be7fd85c9a4562062a2db066b06b5882532f5171a2d553b81fac209ac0a561a14c6e43ab221f1de6b86b03e8d2aeadf2b64ef176f4be7d5207fe22af988cb2d6b427fd0fc22ed2dcadad54c21cfca898774550381b0e1af6a0d7d9daee585c1d4678b969906c311ca38c0c328503a812d98ad03852e139483bf2acc50c322eb7b24128c58553b121932561053e4f1c8565e407631aa608154881f3fbb93ec3822084e6a2a2262873c424b5a9714d2a8b3e8eaeb70c057e1fcbaaee0f46b73b209d");


$rsa = new RSA();
$rsa->loadKey($publicKey);
$rsa->setHash("sha256");
$publickey = $rsa->getPublicKey();

$rsaVerify = $rsa->verify($signedData, $signature);
$opensslVerify = openssl_verify($signedData, $signature, $publickey, OPENSSL_ALGO_SHA256);

var_dump($rsaVerify, $opensslVerify);

输出结果如下:

/app/example/test.php:35:boolean false
/app/example/test.php:35:int 1

正如您从该示例中看到的,openssl_verify() 函数 returns 成功,而 seclib 验证 returns 失败。尽管 openssl_verify() 中使用的 PEM 是从 seclib RSA 对象派生的。

为什么 openssl_verify() 成功时 $rsa->verify() 失败?

您的示例不能是给定的 运行,因为 $key 未定义。出于可重现性目的,我建议创建一个虚拟密钥。

也就是说,问题很可能是正在使用的填充模式。默认情况下,phpseclib 使用不太常见但更安全的 PSS padding by default whereas OpenSSL uses the less secure but more common PKCS1 填充。

要让 phpseclib 像 OpenSSL 那样使用 PKCS1 填充,请执行以下操作:

$rsa->setSignatureMode(RSA::SIGNATURE_PKCS1);