From c2da43d48e1d8c54c089081d7f316bb925f426d9 Mon Sep 17 00:00:00 2001 From: Daniel Kahn Gillmor Date: Wed, 7 Jan 2009 12:31:37 -0500 Subject: [PATCH] clean up a bit of pem2openpgp and remove some of the hardcoded data. --- src/keytrans/pem2openpgp | 102 +++++++++++++++++++++++++-------------- 1 file changed, 65 insertions(+), 37 deletions(-) diff --git a/src/keytrans/pem2openpgp b/src/keytrans/pem2openpgp index 59f9bb0..38baa95 100755 --- a/src/keytrans/pem2openpgp +++ b/src/keytrans/pem2openpgp @@ -20,6 +20,58 @@ use Crypt::OpenSSL::Bignum; use Digest::SHA1; use MIME::Base64; + +# make an old-style packet out of the given packet type and body. +# old-style (see RFC 4880 section 4.2) +sub make_packet { + my $type = shift; + my $body = shift; + +# FIXME: yet another length(): + my $len = length($body); + + my $lenbytes; + my $lencode; + + if ($len < 2**8) { + $lenbytes = 0; + $lencode = 'C'; + } elsif ($len < 2**16) { + $lenbytes = 1; + $lencode = 'n'; + } elsif ($len < 2**31) { + ## not testing against full 32 bits because i don't want to deal + ## with potential overflow. + $lenbytes = 2; + $lencode = 'N'; + } else { + ## what the hell do we do here? + $lenbytes = 3; + $lencode = ''; + } + + return pack('C'.$lencode, 0x80 + ($type * 4) + $lenbytes, $len). + $body; +} + + +# takes a Crypt::OpenSSL::Bignum +sub mpi_pack { + my $num = shift; + + my $hex = $num->to_hex(); + + my $mpilen = length($hex)*4; + +# this is a kludgy way to get the number of bits in the first byte: + my $bitsinfirstbyte = length(sprintf("%b", hex(substr $hex, 0, 2))); + + $mpilen -= (8 - $bitsinfirstbyte); + + return pack('n', $mpilen).$num->to_bin(); +} + + my $holdTerminator = $/; undef $/; my $buf = ; @@ -103,8 +155,14 @@ my $sig_data_to_be_hashed = my ($n, $e, $d, $p, $q) = $rsa->get_key_parameters(); -open(KEYFILE, "; +my $pubkey = + pack('CN', 4, $timestamp). + $pubkey_algo. + mpi_pack($n). + mpi_pack($e); + +#open(KEYFILE, "sign($datatosign); - -my $bigsig = Crypt::OpenSSL::Bignum->new_from_bin($sig); - - -my $hex = $bigsig->to_hex(); - -my $mpilen = length($hex)*4; - -# this is a kludgy way to get the number of bits in the first byte: -my $bitsinfirstbyte = length(sprintf("%b", hex(substr $hex, 0, 2))); - -$mpilen -= (8 - $bitsinfirstbyte); - -# emit two octets representing $mpilen, followed by the signature itself: - +my $sig = Crypt::OpenSSL::Bignum->new_from_bin($rsa->sign($datatosign)); my $sig_body = $sig_data_to_be_hashed. @@ -156,25 +199,10 @@ my $sig_body = pack('n', length($issuer_packet)). $issuer_packet. pack('n', hex(substr($data_hash, 0, 4))). - pack("n" , $mpilen). - $sig; - -# FIXME: yet another length(): -my $len = length($sig_body); - -my $header; - -if ($len < 2**8) { - $header = pack('CC', 0x88, $len); -} elsif ($len < 2**16) { - $header = pack('Cn', 0x89, $len); -} elsif ($len < 2**31) { - $header = pack('CN', 0x8a, $len); -} else { - # what the hell do we do here? - $header = pack('C', 0x8b); -} + mpi_pack($sig); -print $header.$sig_body; +print make_packet(6, $pubkey); +print make_packet(13, $uid); +print make_packet(2, $sig_body); $/ = $holdTerminator; -- 2.26.2