1

我无法使用 Crypt::RSA 和 Crypt::RSA::SS::PSS 在 Perl 中验证 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)。
我在吠叫错误的树吗?

谢谢…。

4

1 回答 1

0

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

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

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

分析系统调用答案的其他方法,如果您想阅读实际答案,请使用反引号:

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 的答案,但这至少应该可以帮助你暂时前进。

弗朗西斯科

于 2013-03-31T12:37:05.053 回答