Reputation:
In PHP, I want to sign some documents with a padding of PSS, and a digest of SHA512.
According to the docs, at http://www.php.net/manual/en/function.openssl-sign.php, I can set the digest however I need, by using a string, such as
openssl_sign($text-to-sign,$binary_signature,$privkey,"sha512");
I don't see any way to set the padding, however.
Can anyone please help me understand how I can sign text, using the RSA-PSS padding style, as seen in version 2.1 of PKCS #1?
Upvotes: 2
Views: 2420
Reputation: 1367
I had the same needs as you, but in 2019 (I assume we got better libraries now ;)
As you already discovered, the way is using phpseclib, which is now at version 2.0 in Debian Stretch.
This is the code I used to sign some binary data, using a 8192 RSA key, with PSS padding and a SHA512 hash function:
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
is a binary string (or an array of bytes, as you call it in C/C++/C#). It doesn't have any encoding, and may contain NULL bytes. This is your wanted signature.
Side note: it's nearly required to insall php-gmp, or you'll get painfully slow signing times. Here there are some benchmarks.
openssl dgst -sha512 -sigopt rsa_padding_mode:pss -sigopt rsa_pss_saltlen:-1 -verify pubkey.pem -signature signature.bin plaintextdata.dat
In detail, the -sigopt rsa_pss_saltlen:-1
tells openssl
to use a salt length that matches the hashing algorithm size. (this is what the Microsoft APIs do, and there's no way to change that behavior)
In order to be able to use the RSA public key in the .NET world, without using any other library, you need first to export it in BLOB format using openssl:
openssl rsa -pubin -inform PEM -in pubkey.pem -outform "MS PUBLICKEYBLOB" -out pubkey.blob
Then, you need .NET 4.6, with the new RSACng
CryptoProvider.
And that's the code:
// 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);
Upvotes: 2
Reputation:
In order not to be "That Guy", I thought I'd leave an answer to the question, given how this does show up in Google and all ;)
I am able to get the PSS padding via http://phpseclib.sourceforge.net/ So far, I haven't gotten it to interop with OpenSSL or LibTomCrypt, but.. I'm probably just configuring it wrong.
I'm sure you'll have better luck, future person!
-CPD
Upvotes: 1