在开发运维平台的时候,都有绕不过的一个需求,那就是对网站证书的管理。
我们需要对证书进行集中化管理,包括颁发证书、解析证书,甚至要定时分析是否有证书过期需要即时续费等,给管理人员一个直观的展示。
首先安装依赖模块,pyopenssl
用于证书解析和python-dateutil
模块用于日期解析,使用pip直接安装即可。
pip install pyopenssl python-dateutil
生成证书脚本
from OpenSSL import crypto
k = crypto.PKey()
k.generate_key(crypto.TYPE_RSA, 2048) # generate RSA key-pair
cert = crypto.X509()
cert.get_subject().C = "CN"
cert.get_subject().O = "XWL, Inc."
cert.get_subject().OU = "XWL"
cert.get_subject().CN = "xwl.io"
cert.set_serial_number(1000)
cert.gmtime_adj_notBefore(0)
cert.gmtime_adj_notAfter(10*365*24*60*60)
cert.set_issuer(cert.get_subject())
cert.set_pubkey(k)
cert.sign(k, 'sha256')
open("selfsign.crt", 'wb').write(crypto.dump_certificate(crypto.FILETYPE_PEM, cert))
open("private.key", 'wb').write(crypto.dump_privatekey(crypto.FILETYPE_PEM, k))
直接使用刚刚生成的证书进行解析,具体注释下脚本输出内容中已有说明。
import OpenSSL
import time
from dateutil import parser
cert = OpenSSL.crypto.load_certificate(OpenSSL.crypto.FILETYPE_PEM, open("selfsign.crt").read())
certIssue = cert.get_issuer()
print ("证书版本: ",cert.get_version() + 1)
print ("证书序列号: ",hex(cert.get_serial_number()))
print ("证书中使用的签名算法: ",cert.get_signature_algorithm().decode("UTF-8"))
print ("颁发者: ",certIssue.commonName)
datetime_struct = parser.parse(cert.get_notBefore().decode("UTF-8"))
print ("有效期从: ",datetime_struct.strftime('%Y-%m-%d %H:%M:%S'))
datetime_struct = parser.parse(cert.get_notAfter().decode("UTF-8"))
print ("到: ",datetime_struct.strftime('%Y-%m-%d %H:%M:%S'))
print ("证书是否已经过期: ",cert.has_expired())
print("公钥长度" ,cert.get_pubkey().bits())
print("公钥:\n" ,OpenSSL.crypto.dump_publickey(OpenSSL.crypto.FILETYPE_PEM, cert.get_pubkey()).decode("utf-8"))
print("主体信息:")
print("CN : 通用名称 OU : 机构单元名称")
print("O : 机构名 L : 地理位置")
print("S : 州/省名 C : 国名")
for item in certIssue.get_components():
print(item[0].decode("utf-8"), " —— ",item[1].decode("utf-8"))
print(cert.get_extension_count())
subject = cert.get_subject()
print("域名:\n" ,subject.CN)
通常在接收到用户上传的证书之后,也会对其进行可用性校验,防止误传。
import OpenSSL
with open("selfsign.crt") as f:
crt = f.read()
with open("private.key") as f:
key = f.read()
try:
private_key_obj = OpenSSL.crypto.load_privatekey(OpenSSL.crypto.FILETYPE_PEM, private_key)
except OpenSSL.crypto.Error:
raise Exception('private key is not correct: %s' % private_key)
try:
cert_obj = OpenSSL.crypto.load_certificate(OpenSSL.crypto.FILETYPE_PEM, cert)
except OpenSSL.crypto.Error:
raise Exception('certificate is not correct: %s' % cert)
context = OpenSSL.SSL.Context(OpenSSL.SSL.TLSv1_METHOD)
context.use_privatekey(private_key_obj)
context.use_certificate(cert_obj)
try:
context.check_privatekey()
print("ok")
except OpenSSL.SSL.Error:
print("error")
以上就是我们常用的证书管理的操作,以及获取常用证书信息的方法。