def import_cert(self, cert_data, machine_keyset=True, store_name=STORE_NAME_MY): base64_cert_data = self._get_cert_base64(cert_data) cert_encoded = None store_handle = None cert_context_p = None try: cert_encoded_len = wintypes.DWORD() if not cryptoapi.CryptStringToBinaryW( base64_cert_data, len(base64_cert_data), cryptoapi.CRYPT_STRING_BASE64, None, ctypes.byref(cert_encoded_len), None, None): raise cryptoapi.CryptoAPIException() size = ctypes.c_size_t(cert_encoded_len.value) cert_encoded = ctypes.cast(malloc(size), ctypes.POINTER(wintypes.BYTE)) if not cryptoapi.CryptStringToBinaryW( base64_cert_data, len(base64_cert_data), cryptoapi.CRYPT_STRING_BASE64, cert_encoded, ctypes.byref(cert_encoded_len), None, None): raise cryptoapi.CryptoAPIException() if machine_keyset: flags = cryptoapi.CERT_SYSTEM_STORE_LOCAL_MACHINE else: flags = cryptoapi.CERT_SYSTEM_STORE_CURRENT_USER store_handle = cryptoapi.CertOpenStore( cryptoapi.CERT_STORE_PROV_SYSTEM, 0, 0, flags, six.text_type(store_name)) if not store_handle: raise cryptoapi.CryptoAPIException() cert_context_p = ctypes.POINTER(cryptoapi.CERT_CONTEXT)() if not cryptoapi.CertAddEncodedCertificateToStore( store_handle, cryptoapi.X509_ASN_ENCODING | cryptoapi.PKCS_7_ASN_ENCODING, cert_encoded, cert_encoded_len, cryptoapi.CERT_STORE_ADD_REPLACE_EXISTING, ctypes.byref(cert_context_p)): raise cryptoapi.CryptoAPIException() # Get the UPN (1.3.6.1.4.1.311.20.2.3 OID) from the # certificate subject alt name upn = None upn_len = cryptoapi.CertGetNameString( cert_context_p, cryptoapi.CERT_NAME_UPN_TYPE, 0, None, None, 0) if upn_len > 1: upn_ar = ctypes.create_unicode_buffer(upn_len) if cryptoapi.CertGetNameString( cert_context_p, cryptoapi.CERT_NAME_UPN_TYPE, 0, None, upn_ar, upn_len) != upn_len: raise cryptoapi.CryptoAPIException() upn = upn_ar.value thumbprint = self._get_cert_thumprint(cert_context_p) return thumbprint, upn finally: if cert_context_p: cryptoapi.CertFreeCertificateContext(cert_context_p) if store_handle: cryptoapi.CertCloseStore(store_handle, 0) if cert_encoded: free(cert_encoded)
def decode_pkcs7_base64_blob(self, data, thumbprint_str, machine_keyset=True, store_name=STORE_NAME_MY): base64_data = data.replace('\r', '').replace('\n', '') store_handle = None cert_context_p = None try: data_encoded_len = wintypes.DWORD() if not cryptoapi.CryptStringToBinaryW( base64_data, len(base64_data), cryptoapi.CRYPT_STRING_BASE64, None, ctypes.byref(data_encoded_len), None, None): raise cryptoapi.CryptoAPIException() data_encoded = ctypes.cast( ctypes.create_string_buffer(data_encoded_len.value), ctypes.POINTER(wintypes.BYTE)) if not cryptoapi.CryptStringToBinaryW( base64_data, len(base64_data), cryptoapi.CRYPT_STRING_BASE64, data_encoded, ctypes.byref(data_encoded_len), None, None): raise cryptoapi.CryptoAPIException() store_handle = cryptoapi.CertOpenStore( cryptoapi.CERT_STORE_PROV_MEMORY, cryptoapi.X509_ASN_ENCODING | cryptoapi.PKCS_7_ASN_ENCODING, None, cryptoapi.CERT_STORE_CREATE_NEW_FLAG, None) if not store_handle: raise cryptoapi.CryptoAPIException() cert_context_p = self._find_certificate_in_store( thumbprint_str, machine_keyset, store_name) if not cryptoapi.CertAddCertificateLinkToStore( store_handle, cert_context_p, cryptoapi.CERT_STORE_ADD_NEW, None): raise cryptoapi.CryptoAPIException() para = cryptoapi.CRYPT_DECRYPT_MESSAGE_PARA() para.cbSize = ctypes.sizeof(cryptoapi.CRYPT_DECRYPT_MESSAGE_PARA) para.dwMsgAndCertEncodingType = (cryptoapi.X509_ASN_ENCODING | cryptoapi.PKCS_7_ASN_ENCODING) para.cCertStore = 1 para.rghCertStore = ctypes.pointer(wintypes.HANDLE(store_handle)) para.dwFlags = cryptoapi.CRYPT_SILENT data_decoded_len = wintypes.DWORD() if not cryptoapi.CryptDecryptMessage( ctypes.byref(para), data_encoded, data_encoded_len, None, ctypes.byref(data_decoded_len), None): raise cryptoapi.CryptoAPIException() data_decoded_buf = ctypes.create_string_buffer( data_decoded_len.value) data_decoded = ctypes.cast(data_decoded_buf, ctypes.POINTER(wintypes.BYTE)) if not cryptoapi.CryptDecryptMessage( ctypes.pointer(para), data_encoded, data_encoded_len, data_decoded, ctypes.byref(data_decoded_len), None): raise cryptoapi.CryptoAPIException() return bytes(data_decoded_buf) finally: if cert_context_p: cryptoapi.CertFreeCertificateContext(cert_context_p) if store_handle: cryptoapi.CertCloseStore(store_handle, 0)