Represent a PKCS #7 message (see `Low-level Message Functions `_)
| 5 | import windows.crypto |
| 6 | |
| 7 | class CryptMessage(gdef.HCRYPTMSG): |
| 8 | """Represent a PKCS #7 message |
| 9 | (see `Low-level Message Functions <https://msdn.microsoft.com/en-us/library/windows/desktop/aa380252(v=vs.85).aspx#low_level_message_functions>`_) |
| 10 | """ |
| 11 | MSG_PARAM_KNOW_TYPES = {gdef.CMSG_SIGNER_INFO_PARAM: gdef.CMSG_SIGNER_INFO, |
| 12 | gdef.CMSG_SIGNER_COUNT_PARAM: gdef.DWORD, |
| 13 | gdef.CMSG_CERT_COUNT_PARAM: gdef.DWORD, |
| 14 | gdef.CMSG_ENVELOPE_ALGORITHM_PARAM: gdef.CRYPT_ALGORITHM_IDENTIFIER, |
| 15 | gdef.CMSG_RECIPIENT_COUNT_PARAM: gdef.DWORD, |
| 16 | gdef.CMSG_RECIPIENT_INFO_PARAM: gdef.CERT_INFO, |
| 17 | } |
| 18 | |
| 19 | |
| 20 | def get_param(self, param_type, index=0, raw=False): |
| 21 | data_size = gdef.DWORD() |
| 22 | # https://msdn.microsoft.com/en-us/library/windows/desktop/aa380227(v=vs.85).aspx |
| 23 | winproxy.CryptMsgGetParam(self, param_type, index, None, data_size) |
| 24 | buffer = ctypes.c_buffer(data_size.value) |
| 25 | winproxy.CryptMsgGetParam(self, param_type, index, buffer, data_size) |
| 26 | if raw: |
| 27 | return (buffer, data_size) |
| 28 | |
| 29 | if param_type in self.MSG_PARAM_KNOW_TYPES: |
| 30 | buffer = self.MSG_PARAM_KNOW_TYPES[param_type].from_buffer(buffer) |
| 31 | if isinstance(buffer, gdef.DWORD): # DWORD -> return the Python int |
| 32 | return buffer.value |
| 33 | return buffer |
| 34 | |
| 35 | # Certificate accessors |
| 36 | |
| 37 | @property |
| 38 | def nb_cert(self): |
| 39 | """The number of certificate embded in the :class:`CryptObject` |
| 40 | |
| 41 | :type: :class:`int` |
| 42 | """ |
| 43 | return self.get_param(gdef.CMSG_CERT_COUNT_PARAM) |
| 44 | |
| 45 | def get_raw_cert(self, index=0): |
| 46 | return self.get_param(gdef.CMSG_CERT_PARAM, index) |
| 47 | |
| 48 | def get_cert(self, index=0): |
| 49 | """Return embded :class:`Certificate` number ``index``. |
| 50 | |
| 51 | .. note:: |
| 52 | |
| 53 | Not all embded certificate are directly used to sign the :class:`CryptObject`. |
| 54 | """ |
| 55 | return windows.crypto.Certificate.from_buffer(self.get_raw_cert(index)) |
| 56 | |
| 57 | @property |
| 58 | def certs(self): |
| 59 | """The list of :class:`Certificate` embded in the message""" |
| 60 | return [self.get_cert(i) for i in range(self.nb_cert)] |
| 61 | |
| 62 | # Signers accessors |
| 63 | |
| 64 | @property |