如何在Python中提取x509证书

7

我有以下脚本。它连接到一个TLS服务器并提取一些X509数据,如有效期和公钥。我有以下脚本:

import socket, ssl
import OpenSSL

hostname='www.google.com'
port=443

context = ssl.SSLContext(ssl.PROTOCOL_TLSv1_2)

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
ssl_sock = context.wrap_socket(s, server_hostname=hostname)
ssl_sock.connect((hostname, port))
ssl_sock.close()
print("ssl connection Done")

cert = ssl.get_server_certificate((hostname, port))
# OpenSSL
x509 = OpenSSL.crypto.load_certificate(OpenSSL.crypto.FILETYPE_PEM, cert)
pk = x509.get_pubkey()
print(x509.get_notAfter())
print(x509.get_notBefore())
print(pk)

问题在于有效期和公钥以不可读的格式返回。如何解决这个问题?即获取日期格式的有效期和十六进制格式的公钥?
另外,我该如何将证书文件保存在本地磁盘上以供参考?
编辑:以下是我得到的输出:
b'20170223141600Z' 
b'20161201141600Z' 
<OpenSSL.crypto.PKey object at 0x0000019EBFDF73C8>

什么是不可读的? - Alastair McCormack
这个日期是不是以YYYYMMDDHHMM格式呈现的? - Alastair McCormack
你是什么意思:“十六进制格式的公钥”? - Alastair McCormack
我的意思是我需要将公钥以十六进制数的形式打印出来。 - user2192774
2个回答

18

返回的日期是YYYYMMDDHHMM格式的日期。您可以使用以下方式将其转换为datetime对象:

datetime.strptime(x509.get_notAfter().decode('ascii'), '%Y%m%d%H%M%SZ')

谢谢。但为了明确问题,告诉我如何获取公钥并将文件保存在本地。 - user2192774
服务器密钥就是公钥。只需将其写入文件即可。 - Alastair McCormack
就像我说的一样,保存服务器密钥。如果你愿意,可以将其转换为十六进制。 - Alastair McCormack
我假设日期时区是UTC?我的理解正确吗? - Luv33preet
1
@Luv33preet,末尾的Z表示它是Zulu时间,也就是UTC时间。根据https://datatracker.ietf.org/doc/html/rfc5280#section-4.1.2.5.2的说明,日期字段可能包含时区偏移量,因此最好预期一下。 - Alastair McCormack
显示剩余4条评论

0
如果你的目标是获得证书,为什么要使用get_pubkey方法?
公钥和证书并不相同。
要获得证书:
buffer = dump_certificate(OpenSSL.crypto.FILETYPE_PEM, x509)
print(buffer.decode())

这将为您提供证书的base64内容。
您需要手动添加头部。
-----BEGIN CERTIFICATE-----

和页脚
-----END CERTIFICATE-----

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