5

OK、Python を使用して PKCS7 エンベロープからのデータを検証しようとしています。

私は Java で動作するコードを持っています: http://nyal.developpez.com/tutoriel/java/bouncycastle/#L4.2

私が欲しいのは、まず封筒から証明書を取得することです。

そのコマンドで開くことができます:

openssl pkcs7 -in pkcs7 -print_certs -text

次に、データが正常であることを確認します。

私はこれを試しました:

import base64
from M2Crypto import SMIME, X509, BIO

raw_sig = """base64 PKCS7 envelop"""
msg = "challenge message to verify"

sm_obj = SMIME.SMIME()
x509 = X509.load_cert('/etc/ssl/certs/ca-certificates.crt') # public key cert used by the remote
# client when signing the message
sk = X509.X509_Stack()
sk.push(x509)
sm_obj.set_x509_stack(sk)

st = X509.X509_Store()
st.load_info('/etc/ssl/certs/ca-certificates.crt') # Public cert for the CA which signed
# the above certificate
sm_obj.set_x509_store(st)

# re-wrap signature so that it fits base64 standards
cooked_sig = '\n'.join(raw_sig[pos:pos+76] for pos in xrange(0, len(raw_sig), 76))

# now, wrap the signature in a PKCS7 block
sig = """
-----BEGIN PKCS7-----
%s
-----END PKCS7-----
""" % cooked_sig

# print sig

# and load it into an SMIME p7 object through the BIO I/O buffer:
buf = BIO.MemoryBuffer(sig)
p7 = SMIME.load_pkcs7_bio(buf)

# do the same for the message text
data_bio = BIO.MemoryBuffer(msg)

cert = sm_obj.verify(p7, data_bio)

/etc/ssl/certs/ca-certificates.crt の 1 つが userCertificate であるべきだと思います。

証明書を取得した後、(有効期限を使用して) まだ有効であることを確認し、失効のために CRL および CPS に対して検証したいと考えています。

あなたが私を助けてくれることを願っています。

4

2 に答える 2

4

だから私はほとんどそこにいました:

import base64
from M2Crypto import SMIME, X509, BIO

raw_sig = """base64 PKCS7 envelop"""
msg = "challenge message to verify"

sm_obj = SMIME.SMIME()
x509 = X509.load_cert('ISSUER.crt') # public key cert used by the remote
                                             # client when signing the message
sk = X509.X509_Stack()
sk.push(x509)
sm_obj.set_x509_stack(sk)

st = X509.X509_Store()
st.load_info('ROOT.crt') # Public cert for the CA which signed
                                    # the above certificate
sm_obj.set_x509_store(st)

# re-wrap signature so that it fits base64 standards
cooked_sig = '\n'.join(raw_sig[pos:pos+76] for pos in xrange(0, len(raw_sig), 76))

# now, wrap the signature in a PKCS7 block
sig = """
-----BEGIN PKCS7-----
%s
-----END PKCS7-----
""" % cooked_sig

# print sig

# and load it into an SMIME p7 object through the BIO I/O buffer:
buf = BIO.MemoryBuffer(sig)
p7 = SMIME.load_pkcs7_bio(buf)

signers = p7.get0_signers(sk)
certificat = signers[0]

次に、CRL と OCSP の検証にも興味があるかもしれません。

from os.path import basename
import re
from tempfile import NamedTemporaryFile

try:
    from subprocess import check_output, CalledProcessError, STDOUT
except ImportError:  # check_output new in 2.7, so use a backport for <=2.6
    from subprocess32 import check_output, CalledProcessError, STDOUT

class OpenSSLError(Exception):
    pass

def info_extension_cert(cert):
    """
    This function take a certificate and return the extensions in dict.

    @type cert : M2Crypto.X509
    @param cert : Certificate
    """
    certificateExtensions = {}

    for index in range(cert.get_ext_count()):
        ext = cert.get_ext_at(index)
        certificateExtensions[ext.get_name()] = ext.get_value()
    return certificateExtensions


def get_cert_url_ocsp(cert):
    """
    Get the OCSP url of a certificate

    @type cert : M2Crypto.X509
    @parm cert : Certificat

    @rtype : string
    @return : The OSCP url
    """

    infos = [x.strip() for x in info_extension_cert(cert)["authorityInfoAccess"].split('\n')]
    ocsp_url = None
    for info in infos:
        if re.match(r"^OCSP - URI:", info):
            ocsp_url = info.replace("OCSP - URI:","")
            break
    return ocsp_url.strip()


def is_revoked(cert, cert_parent):
    """
    Check if the certificate has been revoked.

    @type cert : M2Crypto.X509
    @param cert : The certificate

    @type cert_parent : string
    @param cert_parent : Issuer certificate file path

    @rtype : boolean
    @return : True if revoked or False
    """
    ocsp_url = get_cert_url_ocsp(cert)
    if re.match(r"^http", ocsp_url) is None:
        return False

    data = {'cert_parent': cert_parent,
            'ocsp_url': ocsp_url,
            'serial': cert.get_serial_number()}

    cmd = "openssl ocsp -issuer %(cert_parent)s -CAfile %(cert_parent)s -url %(ocsp_url)s -serial %(serial)s" % data
    print cmd
    try:
        output = check_output(cmd, shell=True, stderr=STDOUT).lower()
    except CalledProcessError, e:
        msg = u"[OpenSSL] Error while checking ocsp %s: %s. Output: %r" % (
                    cmd, e, e.output)
        raise OpenSSLError(msg)
    return not ('response verify ok' in output and '%s: good' % data['serial'] in output)


def is_revoked_crl(cert, cert_parent_with_crl):
    """
    Check if the certificate as been revoked with the crl.

    @type cert : M2Crypto.X509
    @param cert : The certificate

    @type cert_parent : string
    @param cert_parent : Issuer certificate file path

    @rtype : boolean
    @return : True if revoked or False
    """
    tmp_file = NamedTemporaryFile(prefix='cert')
    cert.save(tmp_file.name)
    data = {'cert': tmp_file.name,
            'cert_parent_with_crl': cert_parent_with_crl}
    cmd = "openssl verify -crl_check -CAfile %(cert_parent_with_crl)s %(cert)s" % data
    print cmd
    try:
        output = check_output(cmd, shell=True, stderr=STDOUT).lower()
    except CalledProcessError, e:
        msg = u"[OpenSSL] Error while checking ocsp %s: %s. Output: %r" % (
                    cmd, e, e.output)
        raise OpenSSLError(msg)
    print output
    return '%s: ok' % data['cert'] not in output


def get_cert_url_crl(cert):
    """
    Return the crl url from the certificate

    @type cert : M2Crypto.X509
    @parm cert : Certificate

    @rtype : string
    @return : CRL url
    """

    infos = [x.strip() for x in info_extension_cert(cert)["crlDistributionPoints"].split('\n')]
    crl_url = None
    for info in infos:
        print info
        if re.match(r"^URI:", info):
            crl_url = info.replace("URI:","")
            break
    return crl_url.strip()

cert_parentROOT.crt と ISSUER.crt が連結されたファイルです。 cert_parent_crlROOT.crt、ISSUER.crt、CRL が連結されたファイルです。

私が使用する他の証明書と CRL を連結するには:

rm FILE.crl
wget http://URL/FILE.crl
cat ROOT_ISSUER.crt > ROOT_ISSUER_CRL.crt
echo "-----BEGIN X509 CRL-----" >> ROOT_ISSUER_CRL.crt
openssl enc -base64 -in FILE.crl >> ROOT_ISSUER_CRL.crt
echo "-----END X509 CRL-----" >> ROOT_ISSUER_CRL.crt
于 2012-11-16T15:09:48.113 に答える