如何使用 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)