ensure that the output of modular multiplicative inverse is positive.
authorDaniel Kahn Gillmor <dkg@fifthhorseman.net>
Wed, 4 Feb 2009 05:27:35 +0000 (00:27 -0500)
committerDaniel Kahn Gillmor <dkg@fifthhorseman.net>
Wed, 4 Feb 2009 05:27:35 +0000 (00:27 -0500)
src/keytrans/pem2openpgp

index 9dead77c97f232b814cba86829cc1110e3cb42b5..7abe52c16cbda092f2aa990ec4beda7d4427612a 100755 (executable)
@@ -185,12 +185,18 @@ sub modular_multi_inverse {
   my $a = shift;
   my $b = shift;
 
+
+  my $origdivisor = $b->copy();
+
   my $ctx = Crypt::OpenSSL::Bignum::CTX->new();
   my $x = Crypt::OpenSSL::Bignum->zero();
   my $y = Crypt::OpenSSL::Bignum->one();
   my $lastx = Crypt::OpenSSL::Bignum->one();
   my $lasty = Crypt::OpenSSL::Bignum->zero();
 
+  my $finalquotient;
+  my $finalremainder;
+
   while (! $b->is_zero()) {
     my ($quotient, $remainder) = $a->div($b, $ctx);
 
@@ -210,7 +216,12 @@ sub modular_multi_inverse {
     die "did this math wrong.\n";
   }
 
-  return $lastx;
+  # let's make sure that we return a positive value because RFC 4880,
+  # section 3.2 only allows unsigned values:
+
+  ($finalquotient, $finalremainder) = $lastx->add($origdivisor)->div($origdivisor, $ctx);
+
+  return $finalremainder;
 }
 
 
@@ -287,10 +298,12 @@ sub make_rsa_sec_key_body {
   # we're not using $a and $b, but we need them to get to $c.
   my ($n, $e, $d, $p, $q) = $key->get_key_parameters();
 
+  my $c3 = modular_multi_inverse($p, $q);
+
   my $secret_material = mpi_pack($d).
     mpi_pack($p).
       mpi_pack($q).
-       mpi_pack(modular_multi_inverse($p, $q));
+       mpi_pack($c3);
 
   # according to Crypt::OpenSSL::RSA, the closest value we can get out
   # of get_key_parameters is 1/q mod p; but according to sec 5.5.3 of