我在perl中编写了一个小程序,用于解析包含由OpenSSH的ssh-keygen创建的公钥的授权文件。
公钥由以下空格分隔的字段组成,依次为:
注意,我在实际程序中验证正则表达式之外的keytype和base64编码键,以便在将来从OpenSSH中添加或删除关键算法时更容易进行维护。正则表达式只是解析行。
答案 0 :(得分:2)
OpenSSH的docs说
authorized_keys的格式在sshd(8)手册页中有描述。
AuthorizedKeysFile指定包含公钥[...]每个的文件 该文件的行包含一个键(空行和以。开头的行) 一个'#'被忽略为评论)。 公钥包含以下内容 以空格分隔的字段:options,keytype,base64-encoded key, 评论。选项字段是可选的。 密钥类型为“ecdsa-sha2-nistp256”,“ecdsa-sha2-nistp384”,“ecdsa-sha2-nistp521”,“ssh-ed25519”,“ssh-dss”或“ssh-rsa”; 强> 注释字段不用于任何东西(但可能很方便 用户识别密钥)。 [...]选项(如果存在)包括 逗号分隔的选项规范。除了以外,不允许有空格 在双引号内。
如果我依赖这个文档并采用可能的关键类型,那么我 得到以下解决方案:
#!/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
这是有效的,因为它需要六种可能的关键类型,然后在周围搜索:选项(如果有的话)必须是keytype之前的字符串;密钥类型后跟密钥(始终),并且可选择后跟注释。
但是,我并不喜欢这种方法,因为它具有硬编码的可能关键类型。对于您的输入,它打印: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'
------------------------------
答案 1 :(得分:0)
这就是我提出的,它适用于我的测试数据。
if (my ($koptions, $ktype, $kbase64, $kcomment) =$_ !~
/^(?:((?:[!-~]|\s(?=.*"))+)\s+)? # optional key options
([a-z0-9_-]+)\s+ # key type followed by a space
([\.=a-z0-9\/+_-]+) # RFC4253 base64 encoded key
(?:\s+(.*))?$ # optional comment
/xxia) { # ASCII, Case Insensitive, and exploded
$koptions //= "NONE";
$kcomment //= "NONE";
print "\nkoptions are $koptions\n";
print "ktype is $ktype\n";
print "kbase64 is $kbase64\n";
print "kcomment is $kcomment\n";
} else {
print "Incomprehensible line in ~/.ssh/authorized_keys!\n"
}
示例文件:
ssh-rsa AAAAB3Nza...LiPk== user@example.net
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
我对风格或缺乏风格表示歉意。
有没有人有更优雅的东西?