Beefy Boxes and Bandwidth Generously Provided by pair Networks
The stupid question is the question not asked
 
PerlMonks  

Help verifying RSA PSS signature in Perl with Crypt::RSA and Crypt::RSA::SS::PSS

by cryptques (Novice)
on Mar 31, 2013 at 02:52 UTC ( #1026320=perlquestion: print w/ replies, xml ) Need Help??
cryptques has asked for the wisdom of the Perl Monks concerning the following question:

I'm unable to verify a PSS-signed signature in Perl using Crypt::RSA and Crypt::RSA::SS::PSS.
Here's the situation:

I have a device that has a 1024-bit RSA key, and signs data using PSS, SHA1 and AES-128.

I extract the device's public key successfully, save it in a file with PEM_write_RSA_PUBKEY()

I am able to verify this in C/C++ using RSA_verify_PKCS1_PSS(), and also using openssl on the command line, like this:

echo -n hello | openssl dgst -verify pubkey.pem -signature hello.sig -sha1 \             -sigopt rsa_padding_mode:pss -sigopt rsa_pss_saltlen:20

Where:

  • The string "hello" is the buffer that's been signed by the device.
  • "pubkey.pem" is the device's RSA Public Key, exported from the device with PEM_write_RSA_PUBKEY().
  • "hello.sig" contains the binary (raw) signature generated by the device. (It's 128 bytes, because of the padding.)

I'm trying to do the above in Perl, using Crypt::RSA and Crypt::RSA::SS::PSS, and can't get it to work.

I've tested those two modules and I *am* able to generate and verify a PSS signature in Perl when generating my own key, like this:

#### use Crypt::RSA; use Crypt::RSA::SS::PSS; my ($message, $rsa, $pss, $signature, $verify); my ($public, $private); # The message to be encrypted # $message = "hello"; # Generate RSA key # $rsa = new Crypt::RSA; ($public, $private) = $rsa->keygen( Size => 1024, Filename => "key" ); # Generate PSS signature # $pss = new Crypt::RSA::SS::PSS; $signature = $pss->sign ( Message => $message, Key => $private ) || die $pss->errstr; $verify = $pss->verify ( Message => $message, Key => $public, Signature => $signature) || die $pss->errstr; # $verify returns true, it worked. ####
So, instead of creating my own RSA key I read in a public key using something like this:
#### $publicKey = new Crypt::RSA::Key::Public (Filename => "key.public"); …. # I pack the 256 character (128 byte) hex string of the signature # that's generated by the device. $signature = pack ("H*", '03808458…..73E92'); ####
Where "key.public" contains the device's public key, converted to a decimal string, inserted into the "n" field of the structure that is read/written by Crypt::RSA::Key::Public.

But I can't get it to verify :-(

Methinks I should be able to indicate that it should be using SHA1 and AES-128 (as opposed to, say, Blowfish). Am I barking up the wrong tree?

Thanks….

Comment on Help verifying RSA PSS signature in Perl with Crypt::RSA and Crypt::RSA::SS::PSS
Select or Download Code
Replies are listed 'Best First'.
Re: Help verifying RSA PSS signature in Perl with Crypt::RSA and Crypt::RSA::SS::PSS
by Athanasius (Abbot) on Mar 31, 2013 at 04:01 UTC

    Hello cryptques, and welcome to the Monastery!

    I've tested those two modules and I *am* able to generate and verify a PSS signature in Perl...

    Are you sure it’s working correctly? When I run your script with the line:

    print ($verify ? 'verified' : 'failed'), "\n";

    added at the end, I get an intermittent error:

    13:17 >perl 592_SoPW.pl verified 13:17 >perl 592_SoPW.pl verified 13:17 >perl 592_SoPW.pl verified 13:18 >perl 592_SoPW.pl PARI: *** forbidden division t_INT % t_REAL. at C:/Perl/Strawberry +/spp-spec-64int-5.16.0.1-beta3-32bit-portable/perl/vendor/lib/Crypt/R +SA/Key/Private.pm line 127. 13:18 >

    I’m running the latest version (1.99) of Crypt::RSA.

    With a little detective work using eval and Carp, it appears the error is generated by the line:

    $signature = $pss->sign ( Message => $message, Key => $private ) || die $pss->errstr;

    Maybe some other monk knows of a fix or workaround?

    Athanasius <°(((><contra mundum Iustus alius egestas vitae, eros Piratica,

      Yikes, you're right, Athanasius! It fails intermittently!

      When I run the script several times consecutively it sometimes fails with the same PARI "forbidden division" error that you point out. I hadn't seen that before.

      Sounds like a bug in Math::Pari, which I had to build in order to build Crypt::RSA :-(

      Thanks for your help and for taking time to try it out. I'll have to figure out some other way of doing this...

Re: Help verifying RSA PSS signature in Perl with Crypt::RSA and Crypt::RSA::SS::PSS
by Anonymous Monk on Mar 31, 2013 at 04:07 UTC

      The bug in Crypt::RSA::Key::Private:SSH that you mention is something I had been wondering about (i.e., how to indicate what cipher to use) so I see now that I'm not the only one.

      I don't believe I can use Crypt::OpenSSL::RSA because there's nothing there that explicitly indicates that it supports PSS. However, I'll keep looking.

      Thanks again!

Re: Help verifying RSA PSS signature in Perl with Crypt::RSA and Crypt::RSA::SS::PSS
by Khen1950fx (Canon) on Mar 31, 2013 at 20:22 UTC
    It verified for me by passing trial division:
    #!/usr/bin/perl -l use strict 'refs'; use warnings FATAL => 'syntax'; use Crypt::RSA::Key; use Crypt::RSA::Key::Public; use Crypt::RSA::Key::Private; use Crypt::RSA::SS::PSS; use Math::Pari qw(PARI); my ($message, $rsa, $pss, $signature, $verify); my ($public, $private); $message = "hello"; $rsa = new Crypt::RSA::Key; ($public, $private) = $rsa->generate( Size => 1024, Verbosity => 2, Filename => "key", ) or die $rsa->errstr(); $pss = new Crypt::RSA::SS::PSS; $signature = $pss->sign( Message => $message, Key => $private, ) || die $pss->errstr; $verify = $pss->verify( Message => $message, Key => $public, Signature => $signature, ) || die $pss->errstr; my $i = 0; foreach $verify(1 .. 10) { print $verify ? "ok" : "not ok"; print " ", ++$i; sleep 1; } my $key = new Crypt::RSA::Key::Public( Filename => "key.public", ); $signature = pack("H*", '03808458..73E92'); foreach $verify(1 .. 10) { print $key ? "ok" : "not ok"; print " ", ++$i; sleep 1; }

      Yes, Khen1950fx, I'm also able to verify most of the time with a key that I generate (as in your example. However, sometimes it fails with the error I posted above. Also, the problem is trying to verify with a public key that I've gotten from another device

      (By the way, my code snippet "$signature = pack("H*", '03808458..73E92'); " was just an example (so I wouldn't have to include the whole hex-string signature)).

        I didn't feel like writing the whole hex-string either:).

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://1026320]
Approved by Athanasius
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others cooling their heels in the Monastery: (9)
As of 2015-07-08 00:09 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    The top three priorities of my open tasks are (in descending order of likelihood to be worked on) ...









    Results (93 votes), past polls