Data::SSHPubkey - utility function to parse SSH public keys with
use Data::SSHPubkey qw(pubkeys); # a Mojo app might accept public keys from clients, e.g. # cat /etc/ssh/*.pub | curl ... --data-urlencode pk@- http... # this case is supported via a scalar reference my @keylist = pubkeys( \$c->param('pk') ); for my $ref ( @keylist ) { my ($type, $pubkey) = @$ref; ... } # a key collection host could instead wrap ssh-keyscan(1) and # pass in a file handle open( my $fh, '-|', qw(ssh-keyscan --), $host ) or die ... binmode $fh; @keylist = pubkeys($fh); # a string will be treated as a file to open and read my @keylist = pubkeys( "/etc/ssh/ssh_host_ed25519_key.pub" ); # if you do not care about the key types, extract only the pub # keys with something like ... = map { $_->[1] } @keylist;
Data::SSHPubkey parses SSH public keys, or at least some of those supported by ssh-keygen(1). It may be prudent to check any uploaded data against ssh-keygen. Currently supported public key types (the possible values that $type above may contain):
Data::SSHPubkey
ssh-keygen
$type
ecdsa ed25519 rsa PEM PKCS8 RFC4716
Neither SSH1 keys nor SSH2 DSA keys are supported.
The data will not include any tailing comments; those are stripped. The data will not end with a newline; that must be added by your software as necessary when writing out the public keys. Inner newlines for the multiline SSH public key types (PEM, PKCS8, and RFC4716) will be standardized to the $/ variable. This may cause problems if ssh-keygen(1) or equivalent on some platform demands a specific newline sequence that is not $/.
PEM
PKCS8
RFC4716
$/
ssh-keygen(1)
The types PEM, PKCS8, and RFC4716 will need conversion for use with OpenSSH; use convert_pubkeys or these types could be excluded with something like:
my @pubkeys = grep { $_->[0] =~ m/^(?:ecdsa|ed25519|rsa)$/ } Data::SSHPubkey::pubkeys( ... );
or
... = map { $_->[0] =~ m/^(?:ecdsa|ed25519|rsa)$/ ? $_->[1] : () } Data::SSHPubkey::pubkeys( ... );
to obtain only the public key material.
This subroutine converts the output of pubkeys into a list of just the public keys, with the PEM, PKCS8, and RFC4716 types converted into a form suitable for use with OpenSSH, using the external tool ssh-keygen(1) that is hopefully installed.
A filename (scalar) will be opened and the public keys therein parsed; a scalar reference will be treated as an in-memory file and will likewise be opened and parsed.
This routine will croak on error as, in theory, all the errors should be due to the data passed in by the caller, or possibly the system has just run out of memory, or something.
The return format is a list of [ $type, $pubkey ] sublists.
[ $type, $pubkey ]
$Data::SSHPubkey::max_keys specifies the maximum number of keys to parse, 3 by default. An exception is thrown if more than 3 keys are seen in the input.
$Data::SSHPubkey::max_keys
3
$Data::SSHPubkey::max_lines specifies the maximum number of input lines this module will process before throwing an exception, 100 by default. An attacker still might supply too much data with very long lines; webserver or other configuration to limit that may be necessary.
$Data::SSHPubkey::max_lines
100
The %Data::SSHPubkey::ssh_pubkey_types hash contains as its keys the SSH public key types supported by this module.
%Data::SSHPubkey::ssh_pubkey_types
Patches might best be applied towards:
https://github.com/thrig/Data-SSHPubkey
Probably not enough guards or checks against hostile input.
Support for the PEM and especially PKCS8 formats is a bit sloppy, and the base64 matching is done by a regex that may accept data that is not valid base64.
Support for various RFC 4253 formats is likely lacking (see below or the comments in the code).
More tests are necessary for more edge cases.
If the input uses fancy encodings (where fancy is anything not ASCII) lines longer than 72 8-bit bytes may be accepted. read_binary from File::Slurper or a traditional binmode $fh should avoid this case as the key data looked for is only a subset of ASCII (header values or comments that are ignored by this module could be UTF-8 or possibly anything else).
read_binary
binmode $fh
convert_pubkeys calls out to (modern versions of) ssh-keygen(1); ideally this might instead be done via suitable CPAN modules.
https://github.com/thrig/web_irulan
ssh-keygen(1), ssh-keyscan(1)
Config::OpenSSH::Authkey - older module more aimed at management of ~/.ssh/authorized_keys data and not specifically public keys. It does have support for SSH2 DSA or SSH1 keys, though.
~/.ssh/authorized_keys
Definition of white space used in various formats [ \t].
[ \t]
PEM format details.
Mentioned by RFC 4716 but it is unclear to me what the section 6.6 "Public Key Algorithms" formats exactly are.
Secure Shell (SSH) public key file format.
thrig - Jeremy Mates (cpan:JMATES) <jmates at cpan.org>
<jmates at cpan.org>
Copyright (C) 2019 by Jeremy Mates
This program is distributed under the (Revised) BSD License: http://www.opensource.org/licenses/BSD-3-Clause
To install Data::SSHPubkey, copy and paste the appropriate command in to your terminal.
cpanm
cpanm Data::SSHPubkey
CPAN shell
perl -MCPAN -e shell install Data::SSHPubkey
For more information on module installation, please visit the detailed CPAN module installation guide.