【问题标题】:Trouble verifying RSA PSS signature in Perl with Crypt::RSA and Crypt::RSA::SS::PSS使用 Crypt::RSA 和 Crypt::RSA::SS::PSS 在 Perl 中验证 RSA PSS 签名时遇到问题
【发布时间】:2013-03-31 03:02:18
【问题描述】:

我无法在 Perl 中使用 Crypt::RSA 和 Crypt::RSA::SS::PSS 验证 PSS 签名的签名。

情况如下:

我的设备具有 1024 位 RSA 密钥,并使用 PSS、SHA1 和 AES-128 对数据进行签名。

我成功提取了设备的公钥,用 PEM_write_RSA_PUBKEY() 将它保存在一个文件中

能够使用 RSA_verify_PKCS1_PSS() 在 C/C++ 中验证这一点,并且还可以在命令行上使用 openssl,如下所示:

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

地点:

  • 字符串“hello”是设备签名的缓冲区。
  • “pubkey.pem”是设备的 RSA 公钥,从设备导出 使用 PEM_write_RSA_PUBKEY()。
  • “hello.sig”包含设备生成的二进制(原始)签名。 (由于填充,它是 128 字节。)

我正在尝试在 Perl 中使用 Crypt::RSA 和 Crypt::RSA::SS::PSS 执行上述操作,但无法正常工作。

我已经测试了这两个模块,并且我能够在生成我自己的密钥时在 Perl 中生成和验证 PSS 签名,如下所示:

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.

因此,我没有创建自己的 RSA 密钥,而是使用如下方式读取公钥:

  $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'); 

其中“key.public”包含设备的公钥,转换为十进制字符串,插入到由 Crypt::RSA::Key::Public 读取/写入的变量的“n”字段中。

但我无法验证:-(

我认为我应该能够指出它应该使用 SHA1 和 AES-128(而不是 Blowfish)。
我是不是找错树了?

谢谢……

【问题讨论】:

    标签: perl rsa digital-signature public-key-encryption


    【解决方案1】:

    如果无法对文件和代码进行测试以进行调试,则不确定如何帮助您。但是,虽然不是最好的解决方案,但一个很好的解决办法是在 Perl 中使用系统调用。如果您能够在命令提示符下验证它,那么您可以通过一些选项来检查它。第一个是system

    my $return_code = system("some command");
    # or...
    my $return_code = system("command", "some", "args");
    

    执行此操作时,您会在 $return_code 中收到返回的退出代码。如果您在命令提示符上执行的任何验证操作在验证失败时退出并显示错误代码,那么您知道当一切顺利时您会收到一个0,而当它出错时会收到另一个数字。

    分析系统调用的答案的其他方式,如果你想读取实际的答案,id使用反引号:

    my $answer = `some system call`;
    # or...
    my $answer = qx[some system call];
    

    通过这样做,您将捕获系统调用发送到 STDOUT 的任何内容。如果您还想捕获 STDERR,那么您可以在同一个调用中使用 2>&1 或类似的东西重定向它。在这种情况下,您不会得到返回的退出代码。

    根据您使用的方法,您可以使用这样的答案:

    if ($return_code == 0) {
        print "Verified!";
    }
    # or...
    if ($answer =~ /OpenSSL.*?Verification sucess.*?Signature code:(\d+)/) {
        # I'm just making up stuff here, I don't know the answer of your command!
        print "Verification succesful. Signature code was $1";
    }
    

    我希望这会有所帮助。我希望我可以测试你实际的脚本和文件,我可以给你一个纯 Perl 的答案,但这至少应该可以帮助你暂时前进。

    弗朗西斯科

    【讨论】:

    • 谢谢,弗朗西斯科。作为外部程序运行“openssl”工作正常(因为我能够使用“openssl dgst”从命令行验证签名)。与此同时,我发现其中一个模块存在某种错误,无论是 Math::Pari 还是 Crypt::RSA,因为当我运行我的脚本(如上所示)时,有时我会收到以下错误: PARI: *** 禁止除法 t_INT % t_REAL。在 /usr/local/share/perl/5.14.2/Crypt/RSA/Key/Private.pm 第 127 行。所以我必须继续寻找。
    猜你喜欢
    • 2021-01-12
    • 2023-02-16
    • 2015-02-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-09-07
    • 2012-01-16
    相关资源
    最近更新 更多