Created
February 23, 2016 22:08
-
-
Save jessepeterson/52f66951608ff8471b12 to your computer and use it in GitHub Desktop.
Python PKCS#7 degenerate certificates (like `openssl crl2pkcs7`) using ctypes
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/python | |
from M2Crypto import X509, BIO, m2 | |
import os | |
from ctypes import CDLL | |
from ctypes import * | |
from ctypes.util import find_library | |
class PKCS7_SIGNED(Structure): | |
# no fields here to support a recursive structure | |
pass | |
class PKCS7_d(Union): | |
_fields_ = [ | |
('ptr', c_char_p), | |
('data', c_void_p), | |
('sign', POINTER(PKCS7_SIGNED)), | |
('enveloped', c_void_p), | |
('signed_and_enveloped', c_void_p), | |
('digest', c_void_p), | |
('encrypted', c_void_p), | |
('other', c_void_p), | |
] | |
class PKCS7(Structure): | |
_fields_ = [ | |
('asn1', c_char_p), | |
('length', c_long), | |
('state', c_int), | |
('detached', c_int), | |
('type', c_char_p), # | |
('d', PKCS7_d), | |
] | |
class X509_CRL(Structure): | |
_fields_ = [ | |
('crl', c_void_p), | |
('sig_alg', c_void_p), | |
('signature', c_void_p), | |
('references', c_int), | |
] | |
# assign fields after class definition due to recursive references | |
PKCS7_SIGNED._fields_ = [ | |
('version', c_void_p), | |
('md_algs', c_void_p), | |
('cert', c_void_p), | |
('crl', POINTER(X509_CRL)), | |
('signer_info', c_void_p), | |
('contents', POINTER(PKCS7)), | |
] | |
ossl = CDLL(find_library('crypto')) | |
PKCS7_new = ossl.PKCS7_new | |
PKCS7_new.argtypes = [] | |
PKCS7_new.restype = POINTER(PKCS7) | |
PKCS7_set_type = ossl.PKCS7_set_type | |
PKCS7_set_type.argtypes = [POINTER(PKCS7), c_int] | |
PKCS7_set_type.restype = c_int | |
i2d_PKCS7_bio = ossl.i2d_PKCS7_bio | |
i2d_PKCS7_bio.argtypes = [c_void_p, POINTER(PKCS7)] | |
i2d_PKCS7_bio.restype = c_int | |
X509_CRL_new = ossl.X509_CRL_new | |
X509_CRL_new.argtypes = [] | |
X509_CRL_new.restype = POINTER(X509_CRL) | |
def degenerate_pkcs7_der(stack): | |
# TODO: memory management! need to free some stuff here. (i.e. this code | |
# will leak as is) | |
p7 = PKCS7_new() | |
# memset(p7, 0, sizeof(PKCS7())) # didn't seem to be needed here | |
# set object type, ASN.1 defaults, and make included PKCS7_SIGNED struct | |
PKCS7_set_type(p7, m2.PKCS7_SIGNED) | |
crl = X509_CRL_new() | |
# seemed to be needed to prevent segfault (i.e. OpenSSL source has | |
# *_new_null() macros/functions that presuambly do this for us) | |
memset(crl, 0, sizeof(X509_CRL())) | |
# get pointer to M2Crypto X509_Stack | |
ct_ptr_x509stack = cast(stack.stack.__long__(), c_void_p) | |
# assign the inner PKCS7_SIGNED object our crl and cert. stack | |
p7.contents.d.sign.contents.crl = crl | |
p7.contents.d.sign.contents.cert = ct_ptr_x509stack | |
# new M2Crypto BIO MemoryBuffer | |
p7buf = BIO.MemoryBuffer() | |
ct_ptr_p7buf = cast(p7buf._ptr().__long__(), c_void_p) | |
i2d_PKCS7_bio(ct_ptr_p7buf, p7) | |
return p7buf.read() | |
if __name__ == '__main__': | |
stack = X509.X509_Stack() | |
if os.path.exists('s.crt'): | |
stack.push(X509.load_cert('s.crt')) | |
if os.path.exists('s2.crt'): | |
stack.push(X509.load_cert('s2.crt')) | |
dp7d = degenerate_pkcs7_der(stack) | |
# dump our base64 encoded DER-encoded PKCS#7 "degenerate" certificate | |
print '-----BEGIN PKCS7-----' | |
print dp7d.encode('base64').rstrip() | |
print '-----END PKCS7-----' | |
# should be able to do something like: | |
# ./crl2pkcs7.py | openssl pkcs7 -text -print_certs |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment