Convert-SSH2
view release on metacpan or search on metacpan
lib/Convert/SSH2.pm view on Meta::CPAN
package Convert::SSH2;
use 5.010;
use strict;
use warnings;
use Moo;
use MIME::Base64 qw(decode_base64);
use File::Slurp qw(read_file write_file);
use Carp qw(confess);
use Try::Tiny;
use Class::Load qw(load_class);
use Math::BigInt try => 'GMP';
=head1 NAME
Convert::SSH2 - Convert SSH2 RSA keys to other formats
=head1 VERSION
Version 0.01
=cut
our $VERSION = '0.01';
=head1 SYNOPSIS
use 5.010;
use Convert::SSH2;
my $converter = Convert::SSH2->new('~/.ssh/id_rsa.pub');
# Automatically calls parse()
# Use default PKCS#1 format
say $converter->format_output();
$converter->write('/my/pub/key.pem');
=head1 PURPOSE
This library converts SSH2 style RSA public keys to other representations like PKCS#1.
This is useful if you want to use these public keys with other Perl cryptography
libraries like L<Crypt::RSA> or L<Crypt::OpenSSL::RSA>.
=head1 ATTRIBUTES
=over
=item key
Required. Read-only. The key material. Attempts to be DWIMish. If this is a file path,
it will be used to load the file contents into memory. If it's a buffer, it will use
the buffer contents.
=back
=cut
has 'key' => (
is => 'ro',
required => 1,
);
=over
=item format
Read-only. The output format. Current supports:
=over
=item * pkcs1
This format looks like
-----BEGIN RSA PUBLIC KEY-----
...
-----END RSA PUBLIC KEY-----
=item * pkcs8
This format looks like
-----BEGIN PUBLIC KEY-----
...
-----END PUBLIC KEY-----
=back
You can add your own format by implementing a L<Convert::SSH2::Format::Base> module.
=back
=cut
has 'format' => (
is => 'ro',
isa => sub {
my $n = shift;
confess "$n is not a supported format." unless
grep { $n eq $_ } qw(
pkcs1
pkcs8
);
},
default => sub { 'pkcs1' },
);
has '_buffer' => (
is => 'rw',
);
has '_output' => (
is => 'rw',
predicate => '_has_output',
);
has '_e' => (
is => 'rw',
);
has '_n' => (
is => 'rw',
);
=head1 METHODS
Generally, errors are fatal. Use L<Try::Tiny> if you want more graceful error handling.
=over
=item new()
Constructor. Takes any of the attributes as arguments. You may optionally call new
with either a buffer or a path, and the class will assume that it is the C<key>
material.
The object automatically attempts to parse C<key> data after instantiation.
=back
=cut
# Support single caller argument
around BUILDARGS => sub {
my $orig = shift;
my $class = shift;
if ( @_ == 1 ) {
unshift @_, "key";
}
$class->$orig(@_);
};
sub BUILD {
my $self = shift;
my $buf;
unless ( $self->key =~ /\n/ ) {
if ( -e $self->key ) {
$buf = read_file($self->key, { binmode => ':raw' });
}
else {
$buf = $self->key;
}
}
else {
$buf = $self->key;
}
$buf =~ s/\n//g;
$self->_buffer( (split / /, $buf)[1] );
$self->parse();
}
=over
=item parse()
This method takes the Base64 encoded portion of the SSH key, decodes it, and then converts the
data inside of it into three components: the id string ('ssh-rsa'), the public exponent ('e'),
and the modulus ('n'). By default it looks for the Base64 data inside the instantiated object,
but you can optionally pass in a Base64 string.
It uses L<Math::BigInt> to hold large integers such as 'n' or 'e'. If you don't have
C<libgmp> installed, it will fall back to pure perl automatically, but there will be a speed
( run in 0.574 second using v1.01-cache-2.11-cpan-39bf76dae61 )