我正在用我新买的笔记本电脑的公钥更新我服务器上的authorized_keys文件,惊讶地发现两个公钥的开头相同:
# key 1
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQ....
#
# key 2
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQ....
etc的故事是什么AAAAB3...
?在网上搜索后,我发现其他键的开头也一样。这能解释算法或版本之类的吗?
答案1
这实际上是一个标头,它定义了这是什么类型的密钥。如果你查看RFC 4253我们可以看到,对于 RSA 密钥
“ssh-rsa”密钥格式具有以下特定编码:
string "ssh-rsa" mpint e mpint n
这里的“e”和“n”参数构成了签名密钥 blob。
事实上,如果您使用 Base64 解码字符串“B3NzaC1yc2E”,您会看到它被转换为 ASCII 为“ssh-rsa”。据推测,“AAAA”代表某种标头,因此应用程序可以知道在数据流中的哪个位置开始处理密钥。
答案2
答案3
在点击 Scott 的链接后,我对该格式进行了深入研究。TLDR:
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQ...
| "ssh-rsa" |exponent| modulus
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIFKy...
| "ssh-ed25519" | 32 byte public key
RFC4231指定使用的两种数据类型:
string
:任意长度的二进制字符串。字符串可以包含任意二进制数据,包括空字符和 8 位字符。mpint
:表示二进制补码格式的多精度整数,以字符串形式存储,每字节 8 位,最高有效位 (MSB) 优先。[...]
两种数据类型都以uint32
定义即将到来的数据的长度开头。因为这通常是过度的,最终会得到很多 0(例如“abc”存储为\x00\x00\x00\x03abc
...),它们最终会以A
base64 编码的有效负载中的 s 结尾(... AAAAA2FiYwo
)
RFC4253 第 6.6 节表示密钥编码为:
“ssh-rsa”密钥格式具有以下特定编码:
string "ssh-rsa" mpint e mpint n
这里的“e”和“n”参数构成了签名密钥 blob。[编辑:但是 blob 似乎也包含字符串
"ssh-rsa"
......]
最终的签名编码如下:
string "ssh-rsa" string rsa_signature_blob
“rsa_signature_blob”的值被编码为包含 s 的字符串[编辑:不知道 s 是什么。](它是一个整数,没有长度或填充,无符号,并且按网络字节顺序排列)。
更现代的 Ed25519 和 Ed448 键定义在RFC-8709并有两个字段:
- 常量字符串“ssh-ed25519”(或“ssh-ed448”)
- 32 字节(或 57 字节)公钥作为字符串
"ssh-rsa"
该字符串ssh-rsa
被转换为\x00\x00\x00\x07ssh-rsa
,然后编码为AAAAB3NzaC1yc2E=
,因此所有 ssh-rsa 密钥都应以此开头。
e
,公共指数
通常是 3、17、257、65537 之类的数字。这些数字的编码如下所示(带有上面的尾随偏移量)
- 3 →
'\x00\x00\x00\x01\x03'
→AAAABAw
- 17 →
'\x00\x00\x00\x01\x11'
→AAAABEQ
- 257 →
'\x00\x00\x00\x02\x01\x01'
→AAAACAQE
- 65537/0x10001 →
'\x00\x00\x00\x03\x01\x00\x01'
→AAAADAQAB
因此,如果您看到“BAw”,则指数为 3,或“DAQAB”= 65537
n
,模数(两个秘密素数的乘积,分解这个因数!)
AAABAQ
上面的后面表示密钥长度为 2048 位(并且由于 base64 填充,指数与 DAQAB 类似)。其余的 base64 内容都是指数,后面什么都没有。
其他可能常见的模数前缀:
AAAAg
1024 位,e = 0x10001AAAQI
:2048 位,e = 3