mirror of
https://github.com/hakril/PythonForWindows
synced 2026-06-08 14:31:45 +00:00
Working on windows.crypto object + API + test
This commit is contained in:
committed by
Clement Rouault
parent
d5b70d829f
commit
68e809728a
@@ -0,0 +1,83 @@
|
||||
from os import urandom
|
||||
|
||||
from windows import winproxy
|
||||
from windows.crypto import DEFAULT_ENCODING
|
||||
from windows.crypto.helper import ECRYPT_DATA_BLOB
|
||||
from windows.generated_def import *
|
||||
|
||||
def encode_init_vector(data):
|
||||
blob = ECRYPT_DATA_BLOB.from_string(data)
|
||||
size = DWORD()
|
||||
buf = None
|
||||
winproxy.CryptEncodeObjectEx(DEFAULT_ENCODING, X509_OCTET_STRING, ctypes.byref(blob), 0, None, buf, size)
|
||||
buf = (BYTE * size.value)()
|
||||
winproxy.CryptEncodeObjectEx(DEFAULT_ENCODING, X509_OCTET_STRING, ctypes.byref(blob), 0, None, buf, size)
|
||||
return buf[:]
|
||||
|
||||
|
||||
class GenerateInitVector(object):
|
||||
def __repr__(self):
|
||||
return "GenerateInitVector()"
|
||||
|
||||
def generate_init_vector(self, algo):
|
||||
if algo in [szOID_OIWSEC_desCBC, szOID_RSA_DES_EDE3_CBC]:
|
||||
return urandom(8)
|
||||
if algo in [szOID_NIST_AES128_CBC, szOID_NIST_AES192_CBC, szOID_NIST_AES256_CBC]:
|
||||
return urandom(16)
|
||||
return None
|
||||
geninitvector = GenerateInitVector()
|
||||
|
||||
|
||||
def encrypt(cert, msg, algo=szOID_RSA_DES_EDE3_CBC, initvector=geninitvector):
|
||||
alg_ident = CRYPT_ALGORITHM_IDENTIFIER()
|
||||
alg_ident.pszObjId = algo
|
||||
# Set (compute if needed) the IV
|
||||
if initvector is None:
|
||||
alg_ident.Parameters.cbData = 0
|
||||
elif initvector is geninitvector:
|
||||
initvector = initvector.generate_init_vector(algo)
|
||||
if initvector is None:
|
||||
raise ValueError("I Don't know how to generate an <initvector> for <{0}> please provide one (or None)".format(algo))
|
||||
initvector_encoded = encode_init_vector(initvector)
|
||||
alg_ident.Parameters = ECRYPT_DATA_BLOB.from_string(initvector_encoded)
|
||||
else:
|
||||
initvector_encoded = encode_init_vector(initvector)
|
||||
alg_ident.Parameters = ECRYPT_DATA_BLOB.from_string(initvector_encoded)
|
||||
|
||||
# Setup encryption parameters
|
||||
param = CRYPT_ENCRYPT_MESSAGE_PARA()
|
||||
param.cbSize = ctypes.sizeof(param)
|
||||
param.dwMsgEncodingType = DEFAULT_ENCODING
|
||||
param.hCryptProv = None
|
||||
param.ContentEncryptionAlgorithm = alg_ident
|
||||
param.pvEncryptionAuxInfo = None
|
||||
param.dwFlags = 0
|
||||
param.dwInnerContentType = 0
|
||||
|
||||
certs = (PCERT_CONTEXT * 1)(cert)
|
||||
#Ask the output buffer size
|
||||
size = DWORD()
|
||||
winproxy.CryptEncryptMessage(param, len(certs), certs, msg, len(msg), None, size)
|
||||
#Encrypt the msg
|
||||
buf = (BYTE * size.value)()
|
||||
winproxy.CryptEncryptMessage(param, len(certs), certs, msg, len(msg), buf, size)
|
||||
return bytearray(buf[:size.value])
|
||||
|
||||
|
||||
def decrypt(cert_store, encrypted):
|
||||
# Setup decryption parameters
|
||||
dparam = CRYPT_DECRYPT_MESSAGE_PARA()
|
||||
dparam.cbSize = ctypes.sizeof(dparam)
|
||||
dparam.dwMsgAndCertEncodingType = DEFAULT_ENCODING
|
||||
dparam.cCertStore = 1
|
||||
dparam.rghCertStore = (cert_store,)
|
||||
dparam.dwFlags = 0
|
||||
|
||||
#Ask the output buffer size
|
||||
buf = (BYTE * len(encrypted)).from_buffer_copy(encrypted)
|
||||
dcryptsize = DWORD()
|
||||
winproxy.CryptDecryptMessage(dparam, buf, ctypes.sizeof(buf), None, dcryptsize, None)
|
||||
#Decrypt the msg
|
||||
dcryptbuff = (BYTE * dcryptsize.value)()
|
||||
winproxy.CryptDecryptMessage(dparam, buf, ctypes.sizeof(buf), dcryptbuff, dcryptsize, None)
|
||||
return str(bytearray(dcryptbuff[:dcryptsize.value]))
|
||||
@@ -0,0 +1,40 @@
|
||||
from windows import winproxy
|
||||
from windows.generated_def import *
|
||||
|
||||
from windows.crypto.helper import ECRYPT_DATA_BLOB
|
||||
from windows.crypto import DEFAULT_ENCODING, EHCERTSTORE
|
||||
|
||||
|
||||
def generate_selfsigned_certificate(name="CN=Testing", prov=None, key_info=None, flags=0, signature_algo=None):
|
||||
size = ULONG(len(name) + 0x100)
|
||||
buffer = (ctypes.c_ubyte * size.value)()
|
||||
winproxy.CertStrToNameA(X509_ASN_ENCODING, name, CERT_OID_NAME_STR, None, buffer, size, None)
|
||||
blobname = ECRYPT_DATA_BLOB(size.value, buffer)
|
||||
cert = winproxy.CertCreateSelfSignCertificate(prov, blobname, flags, key_info, signature_algo, None, None, None)
|
||||
return windows.crypto.CertificatContext(cert[0])
|
||||
|
||||
|
||||
def generate_key(prov, keytype=AT_KEYEXCHANGE, flags=CRYPT_EXPORTABLE):
|
||||
key = HCRYPTKEY()
|
||||
winproxy.CryptGenKey(prov, keytype, flags , key)
|
||||
return key
|
||||
# print(key[0])
|
||||
# print("[OK] Key created")
|
||||
# size = DWORD()
|
||||
# winproxy.CryptExportKey(key, None, PRIVATEKEYBLOB, 0, None, size)
|
||||
# buffer = (BYTE * size.value)()
|
||||
# print("needed size = {0}".format(size))
|
||||
# winproxy.CryptExportKey(key, None, PRIVATEKEYBLOB, 0, buffer, size)
|
||||
# print("[OK] Key in buffer")
|
||||
# keyraw = bytearray(buffer)
|
||||
# # openssl.exe rsa -in key.out -inform MS\PRIVATEKEYBLOB -text
|
||||
# save_as(keyraw, "key.out")
|
||||
# #res = ctypes.WinDLL("advapi32").CryptReleaseContext(prov, 0)
|
||||
# return key
|
||||
|
||||
def generate_pfx(hstore, password=None):
|
||||
blob = ECRYPT_DATA_BLOB(0, None)
|
||||
winproxy.PFXExportCertStoreEx(hstore, blob, password, None, EXPORT_PRIVATE_KEYS | REPORT_NO_PRIVATE_KEY | REPORT_NOT_ABLE_TO_EXPORT_PRIVATE_KEY)
|
||||
blob.pbData = (ctypes.c_ubyte * blob.cbData)()
|
||||
winproxy.PFXExportCertStoreEx(hstore, blob, password, None, EXPORT_PRIVATE_KEYS | REPORT_NO_PRIVATE_KEY | REPORT_NOT_ABLE_TO_EXPORT_PRIVATE_KEY)
|
||||
return blob.data
|
||||
@@ -0,0 +1,13 @@
|
||||
from windows.generated_def import CRYPT_DATA_BLOB, BYTE
|
||||
|
||||
class ECRYPT_DATA_BLOB(CRYPT_DATA_BLOB):
|
||||
@classmethod
|
||||
def from_string(cls, buf):
|
||||
self = cls()
|
||||
self.cbData = len(buf)
|
||||
self.pbData = (BYTE * self.cbData)(*bytearray(buf))
|
||||
return self
|
||||
|
||||
@property
|
||||
def data(self):
|
||||
return bytearray(self.pbData[:self.cbData])
|
||||
Reference in New Issue
Block a user