我和你有同样的需求,但在 2019 年(我想我们现在有了更好的库;)
正如您已经发现的那样,方法是使用phpseclib,它现在在 Debian Stretch 中是 2.0 版。
签名生成
这是我用来签署一些二进制数据的代码,使用 8192 RSA 密钥,带有 PSS 填充和 SHA512 哈希函数:
require "/usr/share/php/phpseclib/autoload.php";
use phpseclib\Crypt\RSA;
// INPUT DATA
$privkey = "..."; // I used a RSA private key in PEM format, generated by openssl, but phpseclib supports many formats...
$mydata = "..."; // I generated some binary bytes here...
// SIGNING
$rsa = new RSA();
if ($rsa->loadKey($privkey) != TRUE) {
echo "Error loading private key";
return;
}
$rsa->setHash("sha512");
$rsa->setMGFHash("sha512"); // This NEEDS to be set, or the default will be used
$rsa->setSignatureMode(RSA::SIGNATURE_PSS); // This doesn't need to be set, as it is already the default value
$signatureBytes = $rsa->sign($mydata);
$signatureBytes 是一个 二进制 字符串(或字节数组,正如您在 C/C++/C# 中所称的那样)。它没有任何编码,并且可能包含 NULL 字节。这是你想要的签名。
旁注:安装 php-gmp 几乎是必需的,否则签名时间会非常缓慢。 Here 有一些基准测试。
使用 OpenSSL 进行签名验证
openssl dgst -sha512 -sigopt rsa_padding_mode:pss -sigopt
rsa_pss_saltlen:-1 -verify pubkey.pem -signature signature.bin
明文数据.dat
详细地说,-sigopt rsa_pss_saltlen:-1 告诉openssl 使用与散列算法大小相匹配的盐长度。 (this is what the Microsoft APIs do, and there's no way to change that behavior)
使用 C++/CLI (.NET) 进行签名验证
为了能够在 .NET 世界中使用 RSA 公钥,而不使用任何其他库,您需要首先使用 openssl 将其导出为 BLOB 格式:
openssl rsa -pubin -inform PEM -in pubkey.pem -outform "MS PUBLICKEYBLOB" -out pubkey.blob
然后,您需要 .NET 4.6,以及新的 RSACng CryptoProvider。
这就是代码:
// Import the public key (as BLOBDATA)
RSACryptoServiceProvider^ rsaCsp = gcnew RSACryptoServiceProvider();
rsaCsp->ImportCspBlob(pubkey);
RSAParameters rsaParams = rsaCsp->ExportParameters(false);
RSA^ rsa = gcnew RSACng();
rsa->ImportParameters(rsaParams);
array<Byte>^ dataBytes = ...;
array<Byte>^ signatureBytes = ...;
bool signIsValid = rsa->VerifyData(dataBytes, signatureBytes, HashAlgorithmName::SHA512, RSASignaturePadding::Pss);