Как сделать файл CRL и отозвать сертификат, используя pyOpenSSL? - PullRequest
0 голосов
/ 26 июня 2019

У меня есть скрипт Python, который ищет все самозаверяющие сертификаты x509 в каталоге, проверяет их и записывает информацию о них в таблицу (действительная дата, дата истечения срока действия, тема, издатель). Есть ли способ создать список отозванных сертификатов .crl с помощью библиотеки pyOpenSSL и отозвать один из них? Или это делается только с помощью команд терминала и библиотеки os?

Я не нашел таких вопросов с ответом на форуме.

1 Ответ

0 голосов
/ 27 июня 2019

Рассматривая ваш вопрос, я заметил, что вы говорите самозаверяющие сертификаты. Отзыв самозаверяющего сертификата обычно не работает. Чтобы отозвать самозаверяющие сертификаты, вы должны включить его в CRL, подписанный самим самоподписанным сертификатом. Поскольку отзыв сертификата подразумевает, что ключ сертификата может быть скомпрометирован, злоумышленник, владеющий ключом, может легко сгенерировать более новый CRL, который не включает самозаверяющий сертификат. Чтобы решить эту проблему, вам нужна доверенная третья сторона для выдачи CRL. Тем не менее, это очень трудно достичь.

Я приведу пример ниже, но он не решит вашу проблему.

-

Да, можно создать CRL с помощью pyopenssl, вы можете увидеть пример ниже (на основе этот пример ).

Однако, функция CRL.set_nextUpdate pyopenssl имеет ошибку и не устанавливает указанную дату. Поэтому вам нужно подождать исправления, чтобы действительно использовать его.

# -*- 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)
...