user396243
user396243

Reputation:

Is there any way to generate PSS padded signatures in PHP?

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

Answers (2)

gog
gog

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.

Signature Generation

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.

Signature Verification with OpenSSL

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)

Signature Verification with C++/CLI (.NET)

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

user396243
user396243

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

Related Questions