1 package Crypt::Monkeysphere::Keytrans;
9 use Exporter qw(import);
10 our @EXPORT_OK=qw(GnuPGKey_to_OpenSSH_pub GnuPGKey_to_OpenSSH_fpr);
13 # takes a Math::BigInt and returns it properly packed for openssh output.
15 sub openssh_mpi_pack {
18 my $val = $num->as_hex();
20 # ensure we've got an even multiple of 2 nybbles here.
22 if (length($val) % 2);
23 $val = pack('H*', $val);
24 # packed binary ones-complement representation of the value.
26 my $mpilen = length($val);
28 my $ret = pack('N', $mpilen);
30 # if the first bit of the leading byte is high, we should include a
32 if (ord($val) & 0x80) {
33 $ret = pack('NC', $mpilen+1, 0);
39 # this output is not base64-encoded yet. Pass it through
40 # encode_base64($output, '') if you want to make a file.
42 sub openssh_rsa_pubkey_pack {
43 my ($modulus, $exponent) = @_;
45 return openssh_mpi_pack(Math::BigInt->new('0x'.unpack('H*', "ssh-rsa"))).
46 openssh_mpi_pack($exponent).
47 openssh_mpi_pack($modulus);
50 # calculate/print the fingerprint of an openssh-style keyblob:
55 return join(':', map({unpack("H*", $_)} split(//, Digest::MD5::md5($keyblob))));
60 =head2 GnuPGKey_to_OpenSSH_fpr
62 Find the openssh compatible fingerprint of an (RSA) GnuPG::Key
64 B<Note> you will need to add add bits and (RSA) to the string to
65 exactly match the output of ssh-keygen -l.
69 key - GnuPG::Key object
73 sub GnuPGKey_to_OpenSSH_fpr {
76 croak("not a GnuPG::Key!")
77 unless($key->isa('GnuPG::Key'));
79 croak("Not an RSA key!")
80 unless $key->algo_num == 1;
82 return sshfpr(openssh_rsa_pubkey_pack(@{$key->pubkey_data}), '');
87 =head2 GnuPGKey_to_OpenSSH_pub
89 Translate a GnuPG::Key to a string suitable for an OpenSSH .pub file
91 B<Note> you will need to add "ssh-rsa " to the front to make OpenSSH
96 key - GnuPG::Key object
100 sub GnuPGKey_to_OpenSSH_pub {
103 croak("not a GnuPG::Key!")
104 unless($key->isa('GnuPG::Key'));
106 croak("Not an RSA key!")
107 unless $key->algo_num == 1;
109 return encode_base64(openssh_rsa_pubkey_pack(@{$key->pubkey_data}), '');