У меня были те же потребности, что и у вас, но в 2019 году (я полагаю, у нас теперь есть лучшие библиотеки;)
Как вы уже обнаружили, способ использует phpseclib , который сейчасв версии 2.0 в Debian Stretch.
Генерация подписи
Этот код я использовал для подписи некоторых двоичных данных, используя ключ 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, иначе у вас будет мучительно медленная подпись. Здесь есть некоторые тесты.
Проверка подписи с OpenSSL
openssl dgst -sha512 -sigopt rsa_padding_mode: pss -sigopt rsa_pss_saltlen: -1 -verify pubkey.pem -signature signature.bin plaintextdata.dat
Подробно, -sigopt rsa_pss_saltlen:-1
указывает openssl
использовать длину соли, соответствующую размеру алгоритма хеширования.( это то, что делают API-интерфейсы Microsoft, и нет способа изменить это поведение )
Проверка подписи с помощью C ++ / CLI (.NET)
.В состоянии использовать открытый ключ RSA в мире .NET, без использования какой-либо другой библиотеки, вам необходимо сначала экспортировать его в формате BLOB с помощью openssl:
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);