The docs for OpenSSH say
The format of authorized_keys is described in the sshd(8) manual page.
The sshd(8) manual page says
AuthorizedKeysFile specifies the files containing public keys […] Each
line of the file contains one key (empty lines and lines starting with
a ‘#’ are ignored as comments). Public keys consist of the following
space-separated fields: options, keytype, base64-encoded key,
comment. The options field is optional.
The keytype is “ecdsa-sha2-nistp256”, “ecdsa-sha2-nistp384”, “ecdsa-sha2-nistp521”, “ssh-ed25519”, “ssh-dss” or “ssh-rsa”; the
comment field is not used for anything (but may be convenient for the
user to identify the key). […] The options (if present) consist of
comma-separated option specifications. No spaces are permitted, except
within double quotes.
If I rely on this documentation and take the possible keytypes literal, then I
get the following solution:
#!/usr/bin/env perl
use strict;
use warnings;
my $possible_types = join('|', qw(ecdsa-sha2-nistp256
ecdsa-sha2-nistp384
ecdsa-sha2-nistp521
ssh-ed25519
ssh-dss
ssh-rsa));
my $pattern = qr/^(?:(.*)\s+)? # optional options
($possible_types) \s+ (\S+) # mandatory type and key
(?:\s+(.*))?$/x; # optional comment
while( <DATA> ) {
if (/$pattern/) {
my ($options, $type, $key, $comment) = ($1 // 'NONE', $2, $3, $4);
print "options: '$options'\n";
print "type: '$type'\n";
print "key: '$key'\n";
print "comment: '$comment'\n";
} else {
print "unrecognized line: $_";
}
print '-' x 30, "\n";
}
__DATA__
from="*.sales.example.net,!pc.sales.example.net" ssh-rsa AAAAB2...19Q== john@example.net
ssh-ed25519 AAA3Nzsdfsfsd...fdsXhsdfsfWqfw this is a comment
command="dump /home",no-pty,no-port-forwarding ssh-dss AAAAC3...51R== example.net
permitopen="192.0.2.1:80",permitopen="192.0.2.2:25" ssh-dss AAAAB5...21S==
tunnel="0",command="sh /etc/netstart tun0" ssh-rsa AAAA...== jane@example.net
restrict,command="uptime" ecdsa-sha2-nistp521 AAAA1C8...32Tv==
restrict,pty,command="nethack" ssh-rsa AAAA1f8...IrrC5== user@example.net
This works because it takes the six possible keytypes for granted and then searches around: The options (if any) must be the string before the keytype; the keytype is followed by the key (always), and optionally a comment follows.
I don't like this approach, though, because it has the possible keytypes hardcoded. For your input it prints:
options: 'from="*.sales.example.net,!pc.sales.example.net"'
type: 'ssh-rsa'
key: 'AAAAB2...19Q=='
comment: 'john@example.net'
------------------------------
options: 'NONE'
type: 'ssh-ed25519'
key: 'AAA3Nzsdfsfsd...fdsXhsdfsfWqfw'
comment: 'this is a comment'
------------------------------
options: 'command="dump /home",no-pty,no-port-forwarding'
type: 'ssh-dss'
key: 'AAAAC3...51R=='
comment: 'example.net'
------------------------------
options: 'permitopen="192.0.2.1:80",permitopen="192.0.2.2:25"'
type: 'ssh-dss'
key: 'AAAAB5...21S=='
comment: ''
------------------------------
options: 'tunnel="0",command="sh /etc/netstart tun0"'
type: 'ssh-rsa'
key: 'AAAA...=='
comment: 'jane@example.net'
------------------------------
options: 'restrict,command="uptime"'
type: 'ecdsa-sha2-nistp521'
key: 'AAAA1C8...32Tv=='
comment: ''
------------------------------
options: 'restrict,pty,command="nethack"'
type: 'ssh-rsa'
key: 'AAAA1f8...IrrC5=='
comment: 'user@example.net'
------------------------------