Playing with future windows.crypto API / class

This commit is contained in:
hakril
2016-12-30 10:03:52 +01:00
committed by Clement Rouault
parent 28b2596483
commit d5b70d829f
2 changed files with 58 additions and 7 deletions
+4 -1
View File
@@ -1 +1,4 @@
from windows.crypto.certificate import *
from windows.generated_def import X509_ASN_ENCODING, PKCS_7_ASN_ENCODING
from windows.crypto.certificate import *
DEFAULT_ENCODING = X509_ASN_ENCODING | PKCS_7_ASN_ENCODING
+54 -6
View File
@@ -1,29 +1,67 @@
import itertools
import windows
from windows import winproxy
from windows.generated_def import *
class EHCERTSTORE(HCERTSTORE):
# def __str__(self):
# return "CertStore()"
@property
def certs(self):
res = []
last = None
while True:
try:
cert = winproxy.CertEnumCertificatesInStore(self, last)
except winproxy.Kernel32Error as e:
if (e.winerror & 0xffffffff) in (CRYPT_E_NOT_FOUND,):
return tuple(res)
raise
# Need to duplicate as CertEnumCertificatesInStore will free the context 'last'
ecert = windows.crypto.CertificatContext(cert[0])
res.append(ecert.duplicate())
last = ecert
raise RuntimeError("Out of infinit loop")
# Why PCCERT_CONTEXT (pointer type) and not _CERT_CONTEXT ?
class CertificatContext(PCCERT_CONTEXT):
_type_ = PCCERT_CONTEXT._type_ # Not herited from PCCERT_CONTEXT
def __repr__(self):
return '<{0} "{1}" serial="{2}">'.format(type(self).__name__, self.name, self.serial)
@property
def raw_serial(self):
serial_number = self[0].pCertInfo[0].SerialNumber
return [(c & 0xff) for c in serial_number.pbData[:serial_number.cbData][::-1]]
def serial_string(self):
@property
def serial(self):
serial_number = self[0].pCertInfo[0].SerialNumber
serial_bytes = [(c & 0xff) for c in serial_number.pbData[:serial_number.cbData][::-1]]
serial_bytes = self.raw_serial
return " ".join("{:02x}".format(x) for x in serial_bytes)
def get_name(self, flags=0):
size = winproxy.CertGetNameStringA(self, CERT_NAME_SIMPLE_DISPLAY_TYPE, flags, None, None, 0)
namebuff = ctypes.c_buffer(size)
size = winproxy.CertGetNameStringA(self, CERT_NAME_SIMPLE_DISPLAY_TYPE, flags, None, namebuff, size)
return namebuff[:-1]
def get_issuer_name(self):
name = property(get_name)
@property
def issuer_name(self):
return self.get_name(flags=CERT_NAME_ISSUER_FLAG)
@property
def store(self):
return EHCERTSTORE(self[0].hCertStore)
def get_raw_chain(self):
chain_context = PCCERT_CHAIN_CONTEXT()
@@ -39,9 +77,9 @@ class CertificatContext(PCCERT_CONTEXT):
chain_para.cbSize = sizeof(chain_para)
chain_para.RequestedUsage = cert_usage
winproxy.CertGetCertificateChain(None, self.cert, None, self.cert.hCertStore, byref(chain_para), 0, None, byref(chain_context))
winproxy.CertGetCertificateChain(None, self, None, self[0].hCertStore, byref(chain_para), 0, None, byref(chain_context))
return CertficateChain(chain_context)
def duplicate(self):
res = winproxy.CertDuplicateCertificateContext(self)
# Check what the doc says: the pointer returned is actually the PCERT in parameter
@@ -51,7 +89,17 @@ class CertificatContext(PCCERT_CONTEXT):
if not ctypes.cast(res, PVOID).value == ctypes.cast(self, PVOID).value:
raise ValueError("CertDuplicateCertificateContext did not returned the argument (check doc)")
return self
def enum_properties(self):
prop = 0
res = []
while True:
prop = winproxy.CertEnumCertificateContextProperties(self, prop)
if not prop:
return res
res.append(prop)
raise RuntimeError("Unreachable code")
class CertficateChain(object):