+sub openpgp2ssh {
+ my $instr = shift;
+ my $fpr = shift;
+
+ if (defined $fpr) {
+ if (length($fpr) < 8) {
+ die "We need at least 8 hex digits of fingerprint.\n";
+ }
+ }
+
+ my $packettag;
+ my $dummy;
+ my $tag;
+
+ my $key;
+
+ while (! eof($instr)) {
+ read($instr, $packettag, 1);
+ $packettag = ord($packettag);
+
+ my $packetlen;
+ if ( ! (0x80 & $packettag)) {
+ die "This is not an OpenPGP packet\n";
+ }
+ if (0x40 & $packettag) {
+ $tag = (0x3f & $packettag);
+ my $nextlen = 0;
+ read($instr, $nextlen, 1);
+ $nextlen = ord($nextlen);
+ if ($nextlen < 192) {
+ $packetlen = $nextlen;
+ } elsif ($nextlen < 224) {
+ my $newoct;
+ read($instr, $newoct, 1);
+ $newoct = ord($newoct);
+ $packetlen = (($nextlen - 192) << 8) + ($newoct) + 192;
+ } elsif ($nextlen == 255) {
+ read($instr, $nextlen, 4);
+ $packetlen = unpack('N', $nextlen);
+ } else {
+ # packet length is undefined.
+ }
+ } else {
+ my $lentype;
+ $lentype = 0x03 & $packettag;
+ $tag = ( 0x3c & $packettag ) >> 2;
+ if ($lentype == 0) {
+ read($instr, $packetlen, 1) or die "could not read packet length\n";
+ $packetlen = unpack('C', $packetlen);
+ } elsif ($lentype == 1) {
+ read($instr, $packetlen, 2) or die "could not read packet length\n";
+ $packetlen = unpack('n', $packetlen);
+ } elsif ($lentype == 2) {
+ read($instr, $packetlen, 4) or die "could not read packet length\n";
+ $packetlen = unpack('N', $packetlen);
+ } else {
+ # packet length is undefined.
+ }
+ }
+
+ if (! defined($packetlen)) {
+ die "Undefined packet lengths are not supported.\n";
+ }
+
+ if ($tag == $packet_types->{pubkey} ||
+ $tag == $packet_types->{pub_subkey} ||
+ $tag == $packet_types->{seckey} ||
+ $tag == $packet_types->{sec_subkey}) {
+ my $ver;
+ read($instr, $ver, 1) or die "could not read key version\n";
+ $ver = ord($ver);
+ if ($ver != 4) {
+ printf(STDERR "We only work with version 4 keys. This key appears to be version $ver.\n");
+ read($instr, $dummy, $packetlen - 1) or die "Could not skip past this packet.\n";
+ } else {
+
+ my $timestamp;
+ read($instr, $timestamp, 4) or die "could not read key timestamp.\n";
+ $timestamp = unpack('N', $timestamp);
+
+ my $algo;
+ read($instr, $algo, 1) or die "could not read key algorithm.\n";
+ $algo = ord($algo);
+ if ($algo != $asym_algos->{rsa}) {
+ printf(STDERR "We only support RSA keys (this key used algorithm %d).\n", $algo);
+ read($instr, $dummy, $packetlen - 6) or die "Could not skip past this packet.\n";
+ } else {
+ ## we have an RSA key.
+ my $modulus = read_mpi($instr);
+ my $exponent = read_mpi($instr);
+
+ my $pubkey = Crypt::OpenSSL::RSA->new_key_from_parameters($modulus, $exponent);
+ my $foundfpr = fingerprint($pubkey, $timestamp);
+
+ my $foundfprstr = Crypt::OpenSSL::Bignum->new_from_bin($foundfpr)->to_hex();
+
+ # is this a match?
+ if ((!defined($fpr)) ||
+ (substr($foundfprstr, -1 * length($fpr)) eq $fpr)) {
+ if (defined($key)) {
+ die "Found two matching keys.\n";
+ }
+ $key = $pubkey;
+ }
+
+ if ($tag == $packet_types->{seckey} ||
+ $tag == $packet_types->{sec_subkey}) {
+ die "Cannot deal with secret keys yet!\n";
+ }
+
+ }
+ }
+ } else {
+ read($instr, $dummy, $packetlen) or die "Could not skip past this packet!\n";
+ }
+ }