证书请求的指纹 (CSR)

Fingerprint of certificate request (CSR)

我有一个证书请求(见底部),我希望最好从命令行 (Unix) 获取指纹。如果我的目标只是验证两台机器上 PEM 文件的完整性,我可以使用例如sha256sum csr.pem 值,但我想获得与 Puppet 相同的指纹:

puppet:~# puppetserver ca list --all
Requested Certificates:
    testbox   (SHA256)  7C:8C:A2:2C:17:42:C1:B9:55:A0:1D:EE:0D:C1:B0:65:B0:B4:AF:83:68:77:A8:0D:C4:6C:B1:41:25:FF:E7:C2

引导 testbox 时,testboxpuppet 机器上都会打印此指纹值,它们唯一共享的是 CA 证书(其私钥存储在 puppet).所以该算法不应该要求输入任何私钥。

我认为该算法是标准的,但我对加密格式和 openssl 的了解不足以弄清楚如何获得它,我特别想使用 openssl 或一些其他广泛使用的命令行实用程序(即不是 Ruby)。

我的一次失败尝试:

testbox:~# openssl x509 -fingerprint -in /etc/puppetlabs/puppet/ssl/certificate_requests/testbox.pem 
unable to load certificate
139644407518336:error:0909006C:PEM routines:get_name:no start line:../crypto/pem/pem_lib.c:745:Expecting: TRUSTED CERTIFICATE

这是实际的证书请求:

testbox:~# cat /etc/puppetlabs/puppet/ssl/certificate_requests/testbox.pem 
-----BEGIN CERTIFICATE REQUEST-----
MIIEVzCCAj8CAQAwEjEQMA4GA1UEAwwHdGVzdGJveDCCAiIwDQYJKoZIhvcNAQEB
BQADggIPADCCAgoCggIBAKAT6FPs6RkT30lnNk0wpfhLtjrrAr/YdyDCUVTjV5jL
23iuLLSHes7yog/gACitGqCOnSz7J95OUtfGV+ACV8AEcyNpQazOqHhcLh15CYa7
8fDyVsoLzHWUKDMXhNllYrJFOoEDU/IP/y5hdS6e56pPZCVwYRxg9pjtvOX/FyUA
vXFA94IvqAgR2HdD7Vbr11mSmVNJuP9bWimhizvpzG4g3Xacvz7BhEZC5v/tIuH6
zaQtKCoBoxTFQhlFhY1F0iIMIjbTFTUuzPjCh5pMhXMxm0rgpH0SkvJp8bzesCGX
34JIDCOo6R197IttvbPh+6J91nMReOrYl4WAIMFHMz9L2dEClKbT0qWKjTHSUB6E
Pkia6d/gQzM4UcfP2NGAPnaWv3HZJPy6LnOHFoaxkfiMVGMlKISqF8cbkhGEneX0
V3Q8z60BAdr1q2i2rmPQkhp0MLwCoOzEcH13I43GhZuF/V6YbBcLt0UcEI0DC+VR
vP1sIFXj/BzQkITgzE9q067vRtgYVb85CtfESvSbLdci8noPz076wuaiRme8qzHM
SovvAcq6QGPKaB7K7veKAUW7riOaXHRzR6WAxE2t4WlZDmT/9liLPlxT38Mbl2LE
mVRPNvb1IUyWY5SoE4Dl/9ZNMlIReMrT/XVD/Udt5zOlKxica2wSHPIRyBDm5ah9
AgMBAAGgADANBgkqhkiG9w0BAQsFAAOCAgEAAkqLZQQGf8cHPqX+MWmMu42sHETv
CSqRvKM1oLcli4OCPF15axLNUAXg7+wSPOLfUkznkqukSs+ZZKoKex232ZesrDRn
IG1kkVrYRWAO6kgHHTnQJx0HOawny1OObfIlkbq/PSiprlPK5OfjyTgjK4oIDqIy
50Vifqv2akgW4/HirgUe54dILuXRlntFJtDXyanMHcRhg/Vy+I7hfIbimuBoIWuF
Z/ULNcj25+/m0VjAYNJ4gkV/TgIcWhmRLvq7AFeFo3tmEsmrbnXJnBnt1RCpAOY4
CF3T5etAsG+6JfQ/erY3Kh6sGK5XOvLSQ6SautW8DzSGCV8XKv9jQYlbM/4c3HwX
4vzIxYueW+u2MlfJZcYfkr8RK9bmk4mJCa63AK3VgRtQK21IJqNOR9lgiP202b+T
9o8CmT+rxAnEZHIr9j2nDjPlaR63lAWpSKsS/HxXr6wh2JS/34+YuhbvZlSrxYoR
D8Ta3fZYkIX7aCEziSNqRgZgz+VGroxrQCjdvTYRzr2G6LUVrr0D4dUJnBt1DhZO
klV+pv2tFl5q9szTuu0dkLNyPYFOTjCTD3GxpsuMwmONMAzsMUT+ouLVoklmXxim
Ah3ZrRv4O/hnjRZM0+tV498b4G8ZZmyp80K1CTQwLJNewpk9n2I2K7RVGFtyXa9M
irfOVbUQKaBTrqg=
-----END CERTIFICATE REQUEST-----

If my goal was only to verify integrity of a PEM file on two machines I could just use e.g. sha256sum csr.pem value but I'd like to get the same fingerprint as Puppet does

证书 fingerprint/thumbprint 的一般概念是证书的 DER 编码(二进制)表示形式的摘要。您可以直接使用 openssl x509 命令...或间接执行此操作:

$ openssl x509 -in test.cer -noout -sha256 -fingerprint
SHA256 Fingerprint=3E:A9:CB:54:36:DB:CF:23:50:D1:6B:D8:06:25:DC:0E:37:23:3E:A7:50:A5:D1:F3:05:0F:26:33:4E:F8:66:7C

$ openssl x509 -in test.cer -outform der | sha256sum
3ea9cb5436dbcf2350d16bd80625dc0e37233ea750a5d1f3050f26334ef8667c  -

So the algorithm shouldn't require any private keys on input.

没错。

One of my failed attempts:

testbox:~# openssl x509 -fingerprint -in /etc/puppetlabs/puppet/ssl/certificate_requests/testbox.pem 

因为fingerprint/thumbprint是签名证书的摘要,无法从请求中确定。 (该证书具有其有效性信息、CA 标识符和 CA 的签名......并且可能在请求中不存在扩展名。)


如果您尝试将证书与证书请求相匹配,那么它们唯一真正保证的共同点是 public 密钥。如果 -pubkey 输出匹配,它们是相同的。

$ openssl req -in test.csr -pubkey -noout
-----BEGIN PUBLIC KEY-----
MIIBJDANBgkqhkiG9w0BAQEFAAOCAREAMIIBDAKCAQEAr4HBy9ggP2JKU57WYIF1
NyOTooN9SJDkihne02lzEVYglo1r4NPao4qnd74C7gtrk7ck6NzBK2MrT6gLvJJb
zmJPTKfMYGMGs5QD4oyTLSTdVG/+TvajfxB3CyIV6oy7W/Qn6MTYm3nrM4N1EAxf
g+Vd6bRGbd++7kJTmu8z7xh7d2DDsaGyEDwtgURWSgwQOaCchc9rWXTrUW/I1mI8
lK46WguztMeSlX1DI5FWbPPipSr7DBQrngaBuJcmca8rgt05Cjm5Oc9xlWhofkmQ
pjBQyndo3NazeIQvGP2x9tn/CWuve+uY3Pkw1m/P1QP1jUG/9GIS4k46/EXqQr2I
RwIFAgAABEE=
-----END PUBLIC KEY-----

$ openssl x509 -in test.cer -pubkey -noout
-----BEGIN PUBLIC KEY-----
MIIBJDANBgkqhkiG9w0BAQEFAAOCAREAMIIBDAKCAQEAr4HBy9ggP2JKU57WYIF1
NyOTooN9SJDkihne02lzEVYglo1r4NPao4qnd74C7gtrk7ck6NzBK2MrT6gLvJJb
zmJPTKfMYGMGs5QD4oyTLSTdVG/+TvajfxB3CyIV6oy7W/Qn6MTYm3nrM4N1EAxf
g+Vd6bRGbd++7kJTmu8z7xh7d2DDsaGyEDwtgURWSgwQOaCchc9rWXTrUW/I1mI8
lK46WguztMeSlX1DI5FWbPPipSr7DBQrngaBuJcmca8rgt05Cjm5Oc9xlWhofkmQ
pjBQyndo3NazeIQvGP2x9tn/CWuve+uY3Pkw1m/P1QP1jUG/9GIS4k46/EXqQr2I
RwIFAgAABEE=
-----END PUBLIC KEY-----

虽然我手边没有示例,但仅仅因为它们不匹配并不意味着它们不同。这是因为一些算法,比如RSA,SubjectPublicKeyInfo中的密钥有多种不同的合法编码,CA在签发证书时可以重新规范化。

对于RSA,你可以用openssl rsa命令打开它,然后让OpenSSL重新规范化它(当写回它时,它不会记得使用了两种表示中的哪一种)

$ openssl req -in test.csr -pubkey -noout | openssl rsa -pubin -outform der | sha256sum
writing RSA key
3305c9f5c37cb13c152d087eea65ce1af3f0f846b309cb0426f1f42ae5fcbae0  -

$ openssl x509 -in test.cer -pubkey -noout | openssl rsa -pubin -outform der | sha256sum
writing RSA key
3305c9f5c37cb13c152d087eea65ce1af3f0f846b309cb0426f1f42ae5fcbae0  -

恕我直言,bartonjs 的回答并没有真正回答 woky 的原始问题:

I've a certificate request (see bottom) of which I'd like get fingerprint preferably from command-line (Unix). [...] I'd like to get the same fingerprint as Puppet does

所以问题是,如何获得与 Puppet 内部相同的 CSR 指纹。

此命令应执行 "magic" 生成相同的指纹。

openssl req -in /etc/puppetlabs/puppet/ssl/certificate_requests/testbox.pem -outform der | sha256sum | awk '{ print  }' | sed 's/\(..\)/:/g; s/:$//; s/./\U&/g;'

awk 将输出限制为 sha256 字符串,并且 sed 重新格式化该字符串(插入冒号,所有字母大写,删除结束冒号)。这将为您展示 Puppet 如何输出 CSR 指纹。

注意:我无法使用他的 CSR 生成与 woky 在他最初的问题中提供的指纹相同的指纹。但是我能够用我自己生成的任何 CSR 重建正确的指纹,所以我猜 woky 的 CSR 与问题中提供的指纹不匹配。

这是对 lars 答案的修改:

openssl req -in ./kontrollant.ca.csr.pem -outform DER|openssl dgst -sha256 -c

虽然这给出了小写的校验和,所以 awk 或 tr 是可能的

openssl req -in ./kontrollant.ca.csr.pem -outform DER|openssl dgst -sha256 -c|tr '[:lower:]' '[:upper:]'

这就是我现在的做法(我对 openssl dgst 的 sha256 使用“-c”参数)

另一种方法可以是:

openssl req -in ./kontrollant.ca.csr.pem -outform DER|openssl dgst -sha256|awk '{ gsub(/../,"&:", ); gsub(/:$/,"", ); print upper() }'