Subject: | 1.06 Crypt::OpenPGP::encrypt hangs in OpenPGP/Key/Public/ElGamal.pm:gen_k() |
Date: | Sat, 7 May 2011 23:55:35 -0500 |
To: | bug-Crypt-OpenPGP [...] rt.cpan.org |
From: | Brian Robison <brobison [...] gmail.com> |
Here's a skeletal test case, with specific keys redacted:
-----
#!/usr/bin/perl -w
use Crypt::OpenPGP;
my $pub_key = <PUB_KEY>;
my $sec_key = <SEC_KEY>;
my $key_id = <KEY_ID>;
my $passphrase = shift;
die "Usage: $0 passphrase" if (! $passphrase);
my $data = "this is a test";
my $new_crypt = &encrypt($key_id, $pub_key, $data);
sub encrypt {
my ($key_id, $pub_key, $data) = @_;
my $pubring = Crypt::OpenPGP::KeyRing->new(Data => $pub_key);
my $pgp = Crypt::OpenPGP->new(PubRing => $pubring);
# This hangs!
return $pgp->encrypt(
KeyID => $key_id,
Data => $data,
Armour => 1,
);
}
-----
I found the problem in OpenPGP/Key/Public/ElGamal.pm:gen_k():
sub gen_k {
my($p) = @_;
## XXX choose bitsize based on bitsize of $p
my $bits = 198;
my $p_minus1 = $p - 1; # --- LINE 58: BUG! ---
require Crypt::Random;
my $k = Crypt::Random::makerandom( Size => $bits, Strength => 0 );
# We get back a Math::Pari object, but need a Math::BigInt
$k = Math::BigInt->new($k);
while (1) {
last if Math::BigInt::bgcd($k, $p_minus1) == 1;
$k++;
}
$k;
}
At line 58, $p_minus is actually an "inf" perl int, Math::BigInt::bgcd()
returns NaN, and the loop never exits.
Replacing line 58 with the following solved the problem (not necessarily the
best fix, but it shows the point):
my $p_minus1 = Math::BigInt->new($p);
$p_minus1->bsub(1);
Here're the additional details:
Distribution: Crypt-OpenPGP-1.06
Perl: v5.10.1
OS: FreeBSD 8.2-STABLE