wrote GnuPGKey_to_OpenSSH_pub
[monkeysphere-validation-agent.git] / Crypt / Monkeysphere / Keytrans.pm
1 package Crypt::Monkeysphere::Keytrans;
2
3 use strict;
4 use warnings;
5 use Math::BigInt;
6 use Carp;
7 use MIME::Base64;
8
9 use Exporter qw(import);
10 our @EXPORT_OK=qw();
11
12
13 # takes a Math::BigInt and returns it properly packed for openssh output.
14
15 sub openssh_mpi_pack {
16   my $num = shift;
17
18   my $val = $num->as_hex();
19   $val =~ s/^0x//;
20   # ensure we've got an even multiple of 2 nybbles here.
21   $val = '0'.$val
22     if (length($val) % 2);
23   $val = pack('H*', $val);
24   # packed binary ones-complement representation of the value.
25
26   my $mpilen = length($val);
27
28   my $ret = pack('N', $mpilen);
29
30   # if the first bit of the leading byte is high, we should include a
31   # 0 byte:
32   if (ord($val) & 0x80) {
33     $ret = pack('NC', $mpilen+1, 0);
34   }
35
36   return $ret.$val;
37 }
38
39 # this output is not base64-encoded yet.  Pass it through
40 # encode_base64($output, '') if you want to make a file.
41
42 sub openssh_rsa_pubkey_pack {
43   my ($modulus, $exponent) = @_;
44
45   return openssh_mpi_pack(Math::BigInt->new('0x'.unpack('H*', "ssh-rsa"))).
46       openssh_mpi_pack($exponent).
47         openssh_mpi_pack($modulus);
48 }
49
50
51 sub GnuPGKey_to_OpenSSH_pub {
52   my $key = shift;
53
54   croak("not a GnuPG::Key!")
55     unless($key->isa('GnuPG::Key'));
56
57   croak("Not an RSA key!")
58     unless $key->algo_num == 1;
59
60   use Data::Dumper;
61
62   return encode_base64(openssh_rsa_pubkey_pack(@{$key->pubkey_data}), '');
63 }
64
65 1;