Source code for windows.crypto.cryptmsg

import ctypes

from windows import winproxy
import windows.generated_def as gdef
import windows.crypto

[docs]class CryptMessage(gdef.HCRYPTMSG): """Represent a PKCS #7 message (see `Low-level Message Functions <https://msdn.microsoft.com/en-us/library/windows/desktop/aa380252(v=vs.85).aspx#low_level_message_functions>`_) """ MSG_PARAM_KNOW_TYPES = {gdef.CMSG_SIGNER_INFO_PARAM: gdef.CMSG_SIGNER_INFO, gdef.CMSG_SIGNER_COUNT_PARAM: gdef.DWORD, gdef.CMSG_CERT_COUNT_PARAM: gdef.DWORD, gdef.CMSG_ENVELOPE_ALGORITHM_PARAM: gdef.CRYPT_ALGORITHM_IDENTIFIER, gdef.CMSG_RECIPIENT_COUNT_PARAM: gdef.DWORD, gdef.CMSG_RECIPIENT_INFO_PARAM: gdef.CERT_INFO, } def get_param(self, param_type, index=0, raw=False): data_size = gdef.DWORD() # https://msdn.microsoft.com/en-us/library/windows/desktop/aa380227(v=vs.85).aspx winproxy.CryptMsgGetParam(self, param_type, index, None, data_size) buffer = ctypes.c_buffer(data_size.value) winproxy.CryptMsgGetParam(self, param_type, index, buffer, data_size) if raw: return (buffer, data_size) if param_type in self.MSG_PARAM_KNOW_TYPES: buffer = self.MSG_PARAM_KNOW_TYPES[param_type].from_buffer(buffer) if isinstance(buffer, gdef.DWORD): # DWORD -> return the Python int return buffer.value return buffer # Certificate accessors @property def nb_cert(self): """The number of certificate embded in the :class:`CryptObject` :type: :class:`int` """ return self.get_param(gdef.CMSG_CERT_COUNT_PARAM) def get_raw_cert(self, index=0): return self.get_param(gdef.CMSG_CERT_PARAM, index)
[docs] def get_cert(self, index=0): """Return embded :class:`Certificate` number ``index``. .. note:: Not all embded certificate are directly used to sign the :class:`CryptObject`. """ return windows.crypto.Certificate.from_buffer(self.get_raw_cert(index))
@property def certs(self): """The list of :class:`Certificate` embded in the message""" return [self.get_cert(i) for i in range(self.nb_cert)] # Signers accessors @property def nb_signer(self): """The number of signers for the CryptObject :type: :class:`int` """ try: return self.get_param(gdef.CMSG_SIGNER_COUNT_PARAM) except WindowsError as e: if (e.winerror & 0xffffffff) == gdef.CRYPT_E_INVALID_MSG_TYPE: return 0 raise
[docs] def get_signer_data(self, index=0): """Returns the signer informations for signer nb ``index`` :return: :class:`~windows.generated_def.winstructs.CMSG_SIGNER_INFO` """ return self.get_param(gdef.CMSG_SIGNER_INFO_PARAM, index)
@property def signers(self): """The list of :class:`~windows.generated_def.winstructs.CMSG_SIGNER_INFO` embed in the message""" return [self.get_signer_data(i) for i in range(self.nb_signer)] @property def nb_recipient(self): """TODO: DOC""" return self.get_param(gdef.CMSG_RECIPIENT_COUNT_PARAM)
[docs] def get_recipient_data(self, index=0): """TODO: DOC""" return self.get_param(gdef.CMSG_RECIPIENT_INFO_PARAM, index)
@property def recipients(self): """TODO: DOC""" return [self.get_recipient_data(i) for i in range(self.nb_recipient)] @property def content(self): return self.get_param(gdef.CMSG_CONTENT_PARAM)[:] @property def content_type(self): data = self.get_param(gdef.CMSG_INNER_CONTENT_TYPE_PARAM) assert data[-1] == "\x00", "CMSG_INNER_CONTENT_TYPE_PARAM not NULL TERMINATED" return data[:-1] def update(self, blob, final): # Test isinstance string ? if isinstance(blob, (windows.pycompat.anybuff, bytearray)): blob = windows.pycompat.raw_encode(blob) buffer = windows.utils.BUFFER(gdef.BYTE).from_buffer_copy(blob) return winproxy.CryptMsgUpdate(self, buffer, len(blob), final) return winproxy.CryptMsgUpdate(self, blob.pbData, blob.cbData, final) # constructor
[docs] @classmethod def from_buffer(self, data): hmsg = winproxy.CryptMsgOpenToDecode(windows.crypto.DEFAULT_ENCODING, 0, 0, None, None, None) newmsg = CryptMessage(hmsg) newmsg.update(data, final=True) return newmsg
def __del__(self): return winproxy.CryptMsgClose(self)