如何在pyOpenSSL中验证证书签名?

7

我有两个证书,一个是用来签署client.crtroot.crt

我想要验证client.crt是否确实是由root.key签署的。

在终端上使用openssl,操作如下:

$ openssl verify -CAfile root.crt client.crt  
> client.crt: OK  

然而,使用pyOpenSSL - 遵循文档这篇博客文章 - 我尝试了以下代码:

client_cert = OpenSSL.crypto.load_certificate(OpenSSL.crypto.FILETYPE_PEM, file('client.crt').read())

root_cert = OpenSSL.crypto.load_certificate(OpenSSL.crypto.FILETYPE_PEM, file('root.crt').read())  

store = OpenSSL.crypto.X509Store()  
store.add_cert(root_cert)  

ctx = OpenSSL.crypto.X509StoreContext(store, client_cert)
ctx.verify_certificate()  

我遇到了这个错误:
    > X509StoreContextError: [2, 1, 'unable to get issuer certificate']

我错过了什么吗?
1个回答

4
问题在于我的root.crt不是真正的根证书,而是一系列证书的链:
-----BEGIN CERTIFICATE----- 
...
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE----- 
...
-----END CERTIFICATE-----

OpenSSL.crypto.load_certificate 只会加载第一个证书。

解决方法是从证书链文件中提取所有证书,并将它们添加到 X509Store 中。

代码解决方案如下:

_PEM_RE = re.compile(b'-----BEGIN CERTIFICATE-----\r?.+?\r?-----END CERTIFICATE-----\r?\n?', re.DOTALL)


def parse_chain(chain):
    # returns a list of certificates
    return [c.group() for c in _PEM_RE.finditer(chain)]


client_cert = OpenSSL.crypto.load_certificate(OpenSSL.crypto.FILETYPE_PEM, file('server.crt').read())

store = OpenSSL.crypto.X509Store()
for cert in parse_chain(file('root.crt').read()):
    store.add_cert(OpenSSL.crypto.load_certificate(OpenSSL.crypto.FILETYPE_PEM, cert))

ctx = OpenSSL.crypto.X509StoreContext(store, client_cert)
ctx.verify_certificate()

翻译自https://github.com/hynek/pem/blob/master/src/pem/_core.py#L115


1
请问在store.add_cert命令中,cr是什么意思? - Bogota
1
更新了代码示例,原来是个打字错误。感谢您的注意! - joaoricardo000

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接