如何使用 pyOpenSSL 制作文件 CRL 和吊销证书?
How to make file CRL and revoke certificate using pyOpenSSL?
我有一个 Python 脚本,它在目录中查找所有 x509 自签名证书,验证它们并将有关它们的信息写入 table(有效日期、到期日期、主题、发行人)。
有什么方法可以使用 pyOpenSSL 库创建已撤销的 .crl 证书列表并撤销其中一个?
还是仅在终端命令和 os 库的帮助下完成?
我在论坛上没有找到有答案的此类问题。
查看你的问题,我注意到你说 self-signed 证书。撤销 self-signed 证书通常不起作用。要撤销 self-signed 证书,您必须将其包含在由 self-signed 证书本身签名的 CRL 中。由于吊销证书意味着证书的密钥可能被泄露,拥有密钥的攻击者可以轻松生成不包含 self-signed 证书的更新的 CRL。要解决这个问题,您需要一个受信任的第三方来发布 CRL。然而,这很难实现。
我会保留下面的示例,但这并不能解决您的问题。
--
是的,可以使用 pyopenssl 创建 CRL,您可以查看下面的示例(基于 this example)。
然而,pyopenssl 的 CRL.set_nextUpdate 函数有一个 bug 并且没有设置指定的日期。所以你必须等待修复才能真正使用它。
# -*- coding: latin-1 -*-
#
# Copyright (C) AB Strakt
# Copyright (C) Jean-Paul Calderone
# See LICENSE for details.
"""
Certificate generation module.
"""
from OpenSSL import crypto
TYPE_RSA = crypto.TYPE_RSA
TYPE_DSA = crypto.TYPE_DSA
def createKeyPair(type, bits):
"""
Create a public/private key pair.
Arguments: type - Key type, must be one of TYPE_RSA and TYPE_DSA
bits - Number of bits to use in the key
Returns: The public/private key pair in a PKey object
"""
pkey = crypto.PKey()
pkey.generate_key(type, bits)
return pkey
def createCertRequest(pkey, digest="sha256", **name):
"""
Create a certificate request.
Arguments: pkey - The key to associate with the request
digest - Digestion method to use for signing, default is md5
**name - The name of the subject of the request, possible
arguments are:
C - Country name
ST - State or province name
L - Locality name
O - Organization name
OU - Organizational unit name
CN - Common name
emailAddress - E-mail address
Returns: The certificate request in an X509Req object
"""
req = crypto.X509Req()
subj = req.get_subject()
for (key,value) in name.items():
setattr(subj, key, value)
req.set_pubkey(pkey)
req.sign(pkey, digest)
return req
def createCertificate(req, issuerCert, issuerKey, serial, notBefore, notAfter, digest="sha256"):
"""
Generate a certificate given a certificate request.
Arguments: req - Certificate reqeust to use
issuerCert - The certificate of the issuer
issuerKey - The private key of the issuer
serial - Serial number for the certificate
notBefore - Timestamp (relative to now) when the certificate
starts being valid
notAfter - Timestamp (relative to now) when the certificate
stops being valid
digest - Digest method to use for signing, default is md5
Returns: The signed certificate in an X509 object
"""
cert = crypto.X509()
cert.set_serial_number(serial)
cert.gmtime_adj_notBefore(notBefore)
cert.gmtime_adj_notAfter(notAfter)
cert.set_issuer(issuerCert.get_subject())
cert.set_subject(req.get_subject())
cert.set_pubkey(req.get_pubkey())
cert.sign(issuerKey, digest)
return cert
def createCrl(issuerCert, issuerKey, serial, lastUpdate, nextUpdate, revokedList, digest="sha256"):
"""
Generate a certificate revocation list (CRL).
Arguments: issuerCert - The certificate of the issuer
issuerKey - The private key of the issuer
serial - Serial number for the crl
lastUpdate - ASN1 timestamp ("YYYMMDDhhmmssZ") of the last crl update
nextUpdate - ASN1 timestamp ("YYYMMDDhhmmssZ") of the next crl update
revokedList - A list of Revoked objects.
digest - Digest method to use for signing, default is sha256
Returns: The signed crl in a CRL object
"""
crl = crypto.CRL()
crl.set_lastUpdate(lastUpdate)
crl.set_nextUpdate(nextUpdate) # BUG: this line doesn't set the next update
for revoked in revokedList:
crl.add_revoked(revoked)
crl.sign(issuerCert, issuerKey, digest)
return crl
# Creates a self signed certificate
pkey = createKeyPair(TYPE_RSA, 2048)
req = createCertRequest(pkey, "sha256", C="BR", CN="Teste")
cert = createCertificate(req, req, pkey, 1, 0, 60*60*24*365*5, "sha256")
# Creates the revoked objects
revoked1 = crypto.Revoked()
revoked1.set_serial(b"1") # certificate's serial number
revoked1.set_rev_date(b"20190601010101Z") # certificate's revocation date
revoked1.set_reason(b'keyCompromise') # certificate's revocation reason
revoked2 = crypto.Revoked()
revoked2.set_serial(b"2")
revoked2.set_rev_date(b"20190601010101Z")
revoked2.set_reason(None)
# Creates the CRL using the revoked objects
crl = createCrl(cert, pkey, 1, b"20190101010101Z", b"20190101010101Z", [revoked1, revoked2, ], b"sha256")
# Prints the CRL as PEM and TEXT
crl_pem = crypto.dump_crl(crypto.FILETYPE_PEM, crl)
print(crl_pem)
print()
crl_str = crypto.dump_crl(crypto.FILETYPE_TEXT, crl)
print(crl_str)
我有一个 Python 脚本,它在目录中查找所有 x509 自签名证书,验证它们并将有关它们的信息写入 table(有效日期、到期日期、主题、发行人)。 有什么方法可以使用 pyOpenSSL 库创建已撤销的 .crl 证书列表并撤销其中一个? 还是仅在终端命令和 os 库的帮助下完成?
我在论坛上没有找到有答案的此类问题。
查看你的问题,我注意到你说 self-signed 证书。撤销 self-signed 证书通常不起作用。要撤销 self-signed 证书,您必须将其包含在由 self-signed 证书本身签名的 CRL 中。由于吊销证书意味着证书的密钥可能被泄露,拥有密钥的攻击者可以轻松生成不包含 self-signed 证书的更新的 CRL。要解决这个问题,您需要一个受信任的第三方来发布 CRL。然而,这很难实现。
我会保留下面的示例,但这并不能解决您的问题。
--
是的,可以使用 pyopenssl 创建 CRL,您可以查看下面的示例(基于 this example)。
然而,pyopenssl 的 CRL.set_nextUpdate 函数有一个 bug 并且没有设置指定的日期。所以你必须等待修复才能真正使用它。
# -*- coding: latin-1 -*-
#
# Copyright (C) AB Strakt
# Copyright (C) Jean-Paul Calderone
# See LICENSE for details.
"""
Certificate generation module.
"""
from OpenSSL import crypto
TYPE_RSA = crypto.TYPE_RSA
TYPE_DSA = crypto.TYPE_DSA
def createKeyPair(type, bits):
"""
Create a public/private key pair.
Arguments: type - Key type, must be one of TYPE_RSA and TYPE_DSA
bits - Number of bits to use in the key
Returns: The public/private key pair in a PKey object
"""
pkey = crypto.PKey()
pkey.generate_key(type, bits)
return pkey
def createCertRequest(pkey, digest="sha256", **name):
"""
Create a certificate request.
Arguments: pkey - The key to associate with the request
digest - Digestion method to use for signing, default is md5
**name - The name of the subject of the request, possible
arguments are:
C - Country name
ST - State or province name
L - Locality name
O - Organization name
OU - Organizational unit name
CN - Common name
emailAddress - E-mail address
Returns: The certificate request in an X509Req object
"""
req = crypto.X509Req()
subj = req.get_subject()
for (key,value) in name.items():
setattr(subj, key, value)
req.set_pubkey(pkey)
req.sign(pkey, digest)
return req
def createCertificate(req, issuerCert, issuerKey, serial, notBefore, notAfter, digest="sha256"):
"""
Generate a certificate given a certificate request.
Arguments: req - Certificate reqeust to use
issuerCert - The certificate of the issuer
issuerKey - The private key of the issuer
serial - Serial number for the certificate
notBefore - Timestamp (relative to now) when the certificate
starts being valid
notAfter - Timestamp (relative to now) when the certificate
stops being valid
digest - Digest method to use for signing, default is md5
Returns: The signed certificate in an X509 object
"""
cert = crypto.X509()
cert.set_serial_number(serial)
cert.gmtime_adj_notBefore(notBefore)
cert.gmtime_adj_notAfter(notAfter)
cert.set_issuer(issuerCert.get_subject())
cert.set_subject(req.get_subject())
cert.set_pubkey(req.get_pubkey())
cert.sign(issuerKey, digest)
return cert
def createCrl(issuerCert, issuerKey, serial, lastUpdate, nextUpdate, revokedList, digest="sha256"):
"""
Generate a certificate revocation list (CRL).
Arguments: issuerCert - The certificate of the issuer
issuerKey - The private key of the issuer
serial - Serial number for the crl
lastUpdate - ASN1 timestamp ("YYYMMDDhhmmssZ") of the last crl update
nextUpdate - ASN1 timestamp ("YYYMMDDhhmmssZ") of the next crl update
revokedList - A list of Revoked objects.
digest - Digest method to use for signing, default is sha256
Returns: The signed crl in a CRL object
"""
crl = crypto.CRL()
crl.set_lastUpdate(lastUpdate)
crl.set_nextUpdate(nextUpdate) # BUG: this line doesn't set the next update
for revoked in revokedList:
crl.add_revoked(revoked)
crl.sign(issuerCert, issuerKey, digest)
return crl
# Creates a self signed certificate
pkey = createKeyPair(TYPE_RSA, 2048)
req = createCertRequest(pkey, "sha256", C="BR", CN="Teste")
cert = createCertificate(req, req, pkey, 1, 0, 60*60*24*365*5, "sha256")
# Creates the revoked objects
revoked1 = crypto.Revoked()
revoked1.set_serial(b"1") # certificate's serial number
revoked1.set_rev_date(b"20190601010101Z") # certificate's revocation date
revoked1.set_reason(b'keyCompromise') # certificate's revocation reason
revoked2 = crypto.Revoked()
revoked2.set_serial(b"2")
revoked2.set_rev_date(b"20190601010101Z")
revoked2.set_reason(None)
# Creates the CRL using the revoked objects
crl = createCrl(cert, pkey, 1, b"20190101010101Z", b"20190101010101Z", [revoked1, revoked2, ], b"sha256")
# Prints the CRL as PEM and TEXT
crl_pem = crypto.dump_crl(crypto.FILETYPE_PEM, crl)
print(crl_pem)
print()
crl_str = crypto.dump_crl(crypto.FILETYPE_TEXT, crl)
print(crl_str)