Add new crypto definitions + function for PEM encoding/decoding

This commit is contained in:
hakril
2025-08-14 10:25:30 +02:00
parent d0e8443576
commit 6c00426815
12 changed files with 231 additions and 6 deletions
@@ -633,4 +633,28 @@
#define CERT_NCRYPT_KEY_SPEC 0xFFFFFFFF
#define CERT_REQUEST_V1 0
#define CERT_REQUEST_V1 0
// Include\10.0.10240.0\um\wincrypt.h
#define CRYPT_STRING_BASE64HEADER 0x00000000
#define CRYPT_STRING_BASE64 0x00000001
#define CRYPT_STRING_BINARY 0x00000002
#define CRYPT_STRING_BASE64REQUESTHEADER 0x00000003
#define CRYPT_STRING_HEX 0x00000004
#define CRYPT_STRING_HEXASCII 0x00000005
#define CRYPT_STRING_BASE64_ANY 0x00000006
#define CRYPT_STRING_ANY 0x00000007
#define CRYPT_STRING_HEX_ANY 0x00000008
#define CRYPT_STRING_BASE64X509CRLHEADER 0x00000009
#define CRYPT_STRING_HEXADDR 0x0000000a
#define CRYPT_STRING_HEXASCIIADDR 0x0000000b
#define CRYPT_STRING_HEXRAW 0x0000000c
#define CRYPT_STRING_BASE64URI 0x0000000d
#define CRYPT_STRING_PERCENTESCAPE 0x08000000 // base64 formats only
#define CRYPT_STRING_HASHDATA 0x10000000
#define CRYPT_STRING_STRICT 0x20000000
#define CRYPT_STRING_NOCRLF 0x40000000
#define CRYPT_STRING_NOCR 0x80000000
@@ -641,4 +641,40 @@ BOOL CryptSignCertificate(
[in] PVOID pvHashAuxInfo,
[out] BYTE *pbSignature,
[in, out] DWORD *pcbSignature
);
BOOL CryptBinaryToStringA(
[in] BYTE *pbBinary,
[in] DWORD cbBinary,
[in] DWORD dwFlags,
[out, optional] LPSTR pszString,
[in, out] DWORD *pcchString
);
BOOL CryptBinaryToStringW(
[in] BYTE *pbBinary,
[in] DWORD cbBinary,
[in] DWORD dwFlags,
[out, optional] LPWSTR pszString,
[in, out] DWORD *pcchString
);
BOOL CryptStringToBinaryA(
[in] LPCSTR pszString,
[in] DWORD cchString,
[in] DWORD dwFlags,
[in] BYTE *pbBinary,
[in, out] DWORD *pcbBinary,
[out] DWORD *pdwSkip,
[out] DWORD *pdwFlags
);
BOOL CryptStringToBinaryW(
[in] LPCWSTR pszString,
[in] DWORD cchString,
[in] DWORD dwFlags,
[in] BYTE *pbBinary,
[in, out] DWORD *pcbBinary,
[out] DWORD *pdwSkip,
[out] DWORD *pdwFlags
);
+19
View File
@@ -3517,6 +3517,25 @@ WinDef
.. autodata:: CERT_SET_KEY_CONTEXT_PROP_ID
.. autodata:: CERT_NCRYPT_KEY_SPEC
.. autodata:: CERT_REQUEST_V1
.. autodata:: CRYPT_STRING_BASE64HEADER
.. autodata:: CRYPT_STRING_BASE64
.. autodata:: CRYPT_STRING_BINARY
.. autodata:: CRYPT_STRING_BASE64REQUESTHEADER
.. autodata:: CRYPT_STRING_HEX
.. autodata:: CRYPT_STRING_HEXASCII
.. autodata:: CRYPT_STRING_BASE64_ANY
.. autodata:: CRYPT_STRING_ANY
.. autodata:: CRYPT_STRING_HEX_ANY
.. autodata:: CRYPT_STRING_BASE64X509CRLHEADER
.. autodata:: CRYPT_STRING_HEXADDR
.. autodata:: CRYPT_STRING_HEXASCIIADDR
.. autodata:: CRYPT_STRING_HEXRAW
.. autodata:: CRYPT_STRING_BASE64URI
.. autodata:: CRYPT_STRING_PERCENTESCAPE
.. autodata:: CRYPT_STRING_HASHDATA
.. autodata:: CRYPT_STRING_STRICT
.. autodata:: CRYPT_STRING_NOCRLF
.. autodata:: CRYPT_STRING_NOCR
.. autodata:: WSADESCRIPTION_LEN
.. autodata:: WSASYS_STATUS_LEN
.. autodata:: WSAPROTOCOL_LEN
+8
View File
@@ -330,6 +330,14 @@ Functions
.. function:: CryptSignCertificate(hBCryptKey, dwKeySpec, dwCertEncodingType, pbEncodedToBeSigned, cbEncodedToBeSigned, pSignatureAlgorithm, pvHashAuxInfo, pbSignature, pcbSignature)
.. function:: CryptBinaryToStringA(pbBinary, cbBinary, dwFlags, pszString, pcchString)
.. function:: CryptBinaryToStringW(pbBinary, cbBinary, dwFlags, pszString, pcchString)
.. function:: CryptStringToBinaryA(pszString, cchString, dwFlags, pbBinary, pcbBinary, pdwSkip, pdwFlags)
.. function:: CryptStringToBinaryW(pszString, cchString, dwFlags, pbBinary, pcbBinary, pdwSkip, pdwFlags)
.. function:: OpenVirtualDisk(VirtualStorageType, Path, VirtualDiskAccessMask, Flags, Parameters, Handle)
.. function:: AttachVirtualDisk(VirtualDiskHandle, SecurityDescriptor, Flags, ProviderSpecificFlags, Parameters, Overlapped)
+1
View File
@@ -7,3 +7,4 @@ from windows.crypto.encrypt_decrypt import *
from windows.crypto.sign_verify import *
from windows.crypto.dpapi import *
from windows.crypto.cryptmsg import CryptMessage
from windows.crypto.binary_string_conversion import string_to_binary, binary_to_string
@@ -0,0 +1,31 @@
import windows.winproxy as winproxy
import windows.generated_def as gdef
def binary_to_string(data, flags=gdef.CRYPT_STRING_BASE64, header=None):
if header is not None:
if flags != gdef.CRYPT_STRING_BASE64:
raise ValueError("custom_header parameter can only be used with flags==CRYPT_STRING_BASE64")
databuff = (gdef.BYTE * len(data))(*data)
buffsize = gdef.DWORD(0)
winproxy.CryptBinaryToStringW (databuff, len(databuff), flags, None, buffsize)
resbuff = (gdef.WCHAR * buffsize.value)()
winproxy.CryptBinaryToStringW(databuff, len(databuff), flags, resbuff, buffsize)
strres = resbuff[:buffsize.value]
if header:
strres = "-----BEGIN {header}-----\r\n{0}-----END {header}-----".format(strres, header=header)
return strres
def string_to_binary(data, flags=gdef.CRYPT_STRING_ANY):
# Get the buffer size
buffsize = gdef.DWORD(0)
winproxy.CryptStringToBinaryW(data, len(data), flags, None, buffsize, None, None)
# Decode
resbuff = (gdef.BYTE * buffsize.value)()
skipped = gdef.DWORD()
outflags = gdef.DWORD()
winproxy.CryptStringToBinaryW(data, len(data), flags, resbuff, buffsize, skipped, outflags)
return bytearray(resbuff[:buffsize.value])
+22 -4
View File
@@ -6,7 +6,7 @@ from windows import winproxy
import windows.generated_def as gdef
from windows.crypto import DEFAULT_ENCODING
from windows.pycompat import urepr_encode
from windows.pycompat import urepr_encode, unicode_type
import windows.crypto.cryptmsg
@@ -58,7 +58,8 @@ class CryptObject(object):
gdef.LPWSTR(filename),
# filename,
content_type,
gdef.CERT_QUERY_FORMAT_FLAG_BINARY,
# gdef.CERT_QUERY_FORMAT_FLAG_BINARY,
gdef.CERT_QUERY_FORMAT_FLAG_ALL,
0,
dwEncoding,
dwContentType,
@@ -149,7 +150,9 @@ class CertificateStore(gdef.HCERTSTORE):
"""Create a new :class:`CertificateStore` from system store ``store_name``
(see `System Store Locations <https://msdn.microsoft.com/en-us/library/windows/desktop/aa388136(v=vs.85).aspx>`_)
"""
res = winproxy.CertOpenStore(gdef.CERT_STORE_PROV_SYSTEM_A, DEFAULT_ENCODING, None, gdef.CERT_SYSTEM_STORE_LOCAL_MACHINE | gdef.CERT_STORE_READONLY_FLAG, store_name)
if not isinstance(store_name, unicode_type):
raise ValueError("store_name should be an unicode string not {0}".format(type(store_name)))
res = winproxy.CertOpenStore(gdef.CERT_STORE_PROV_SYSTEM_W, DEFAULT_ENCODING, None, gdef.CERT_SYSTEM_STORE_LOCAL_MACHINE | gdef.CERT_STORE_READONLY_FLAG, store_name)
return ctypes.cast(res, cls)
@classmethod
@@ -157,7 +160,9 @@ class CertificateStore(gdef.HCERTSTORE):
"""Create a new :class:`CertificateStore` from system store ``store_name``
(see `System Store Locations <https://msdn.microsoft.com/en-us/library/windows/desktop/aa388136(v=vs.85).aspx>`_)
"""
res = winproxy.CertOpenStore(gdef.CERT_STORE_PROV_SYSTEM_A, DEFAULT_ENCODING, None, gdef.CERT_SYSTEM_STORE_CURRENT_USER | gdef.CERT_STORE_READONLY_FLAG, store_name)
if not isinstance(store_name, unicode_type):
raise ValueError("store_name should be an unicode string not {0}".format(type(store_name)))
res = winproxy.CertOpenStore(gdef.CERT_STORE_PROV_SYSTEM_W, DEFAULT_ENCODING, None, gdef.CERT_SYSTEM_STORE_CURRENT_USER | gdef.CERT_STORE_READONLY_FLAG, store_name)
return ctypes.cast(res, cls)
@classmethod
@@ -442,6 +447,19 @@ class Certificate(gdef.CERT_CONTEXT):
windows.winproxy.CertGetCertificateContextProperty(self, prop, buf, datasize)
return bytearray(buf)
def get_private_key(self, flags):
"""Tmp API: return value will change"""
keyhandle = gdef.HCRYPTPROV_OR_NCRYPT_KEY_HANDLE()
keyspec = gdef.DWORD()
must_free_handle = gdef.BOOL()
windows.winproxy.CryptAcquireCertificatePrivateKey(self, flags, None, keyhandle, keyspec, must_free_handle)
return (keyhandle, keyspec, must_free_handle)
@property
def private_key(self):
"""Tmp API: return value will change"""
return self.get_private_key(flags=gdef.CRYPT_ACQUIRE_COMPARE_KEY_FLAG | gdef.CRYPT_ACQUIRE_ALLOW_NCRYPT_KEY_FLAG | gdef.CRYPT_ACQUIRE_USE_PROV_INFO_FLAG)
@property
def encoded(self):
+5 -1
View File
@@ -106,10 +106,14 @@ class CryptMessage(gdef.HCRYPTMSG):
def content(self):
return self.get_param(gdef.CMSG_CONTENT_PARAM)[:]
@property
def bare_content(self):
return self.get_param(gdef.CMSG_BARE_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"
assert data[-1] == b"\x00", "CMSG_INNER_CONTENT_TYPE_PARAM not NULL TERMINATED"
return data[:-1]
+23
View File
@@ -788,6 +788,25 @@ windef = {'ABOVE_NORMAL_PRIORITY_CLASS',
'CRYPT_SF',
'CRYPT_SGCKEY',
'CRYPT_SILENT',
'CRYPT_STRING_ANY',
'CRYPT_STRING_BASE64',
'CRYPT_STRING_BASE64HEADER',
'CRYPT_STRING_BASE64REQUESTHEADER',
'CRYPT_STRING_BASE64URI',
'CRYPT_STRING_BASE64X509CRLHEADER',
'CRYPT_STRING_BASE64_ANY',
'CRYPT_STRING_BINARY',
'CRYPT_STRING_HASHDATA',
'CRYPT_STRING_HEX',
'CRYPT_STRING_HEXADDR',
'CRYPT_STRING_HEXASCII',
'CRYPT_STRING_HEXASCIIADDR',
'CRYPT_STRING_HEXRAW',
'CRYPT_STRING_HEX_ANY',
'CRYPT_STRING_NOCR',
'CRYPT_STRING_NOCRLF',
'CRYPT_STRING_PERCENTESCAPE',
'CRYPT_STRING_STRICT',
'CRYPT_UNICODE_NAME_DECODE_DISABLE_IE4_UTF8_FLAG',
'CRYPT_UPDATE_KEY',
'CRYPT_USER_KEYSET',
@@ -14757,6 +14776,8 @@ functions = {'AccessCheck',
'CryptAcquireCertificatePrivateKey',
'CryptAcquireContextA',
'CryptAcquireContextW',
'CryptBinaryToStringA',
'CryptBinaryToStringW',
'CryptCATAdminAcquireContext',
'CryptCATAdminAcquireContext2',
'CryptCATAdminCalcHashFromFileHandle',
@@ -14806,6 +14827,8 @@ functions = {'AccessCheck',
'CryptSignHashA',
'CryptSignHashW',
'CryptSignMessage',
'CryptStringToBinaryA',
'CryptStringToBinaryW',
'CryptUIDlgViewContext',
'CryptUnprotectData',
'CryptUnprotectMemory',
+19
View File
@@ -3557,6 +3557,25 @@ CERT_SET_KEY_PROV_HANDLE_PROP_ID = make_flag("CERT_SET_KEY_PROV_HANDLE_PROP_ID",
CERT_SET_KEY_CONTEXT_PROP_ID = make_flag("CERT_SET_KEY_CONTEXT_PROP_ID", 0x00000001)
CERT_NCRYPT_KEY_SPEC = make_flag("CERT_NCRYPT_KEY_SPEC", 0xFFFFFFFF)
CERT_REQUEST_V1 = make_flag("CERT_REQUEST_V1", 0)
CRYPT_STRING_BASE64HEADER = make_flag("CRYPT_STRING_BASE64HEADER", 0x00000000)
CRYPT_STRING_BASE64 = make_flag("CRYPT_STRING_BASE64", 0x00000001)
CRYPT_STRING_BINARY = make_flag("CRYPT_STRING_BINARY", 0x00000002)
CRYPT_STRING_BASE64REQUESTHEADER = make_flag("CRYPT_STRING_BASE64REQUESTHEADER", 0x00000003)
CRYPT_STRING_HEX = make_flag("CRYPT_STRING_HEX", 0x00000004)
CRYPT_STRING_HEXASCII = make_flag("CRYPT_STRING_HEXASCII", 0x00000005)
CRYPT_STRING_BASE64_ANY = make_flag("CRYPT_STRING_BASE64_ANY", 0x00000006)
CRYPT_STRING_ANY = make_flag("CRYPT_STRING_ANY", 0x00000007)
CRYPT_STRING_HEX_ANY = make_flag("CRYPT_STRING_HEX_ANY", 0x00000008)
CRYPT_STRING_BASE64X509CRLHEADER = make_flag("CRYPT_STRING_BASE64X509CRLHEADER", 0x00000009)
CRYPT_STRING_HEXADDR = make_flag("CRYPT_STRING_HEXADDR", 0x0000000a)
CRYPT_STRING_HEXASCIIADDR = make_flag("CRYPT_STRING_HEXASCIIADDR", 0x0000000b)
CRYPT_STRING_HEXRAW = make_flag("CRYPT_STRING_HEXRAW", 0x0000000c)
CRYPT_STRING_BASE64URI = make_flag("CRYPT_STRING_BASE64URI", 0x0000000d)
CRYPT_STRING_PERCENTESCAPE = make_flag("CRYPT_STRING_PERCENTESCAPE", 0x08000000)
CRYPT_STRING_HASHDATA = make_flag("CRYPT_STRING_HASHDATA", 0x10000000)
CRYPT_STRING_STRICT = make_flag("CRYPT_STRING_STRICT", 0x20000000)
CRYPT_STRING_NOCRLF = make_flag("CRYPT_STRING_NOCRLF", 0x40000000)
CRYPT_STRING_NOCR = make_flag("CRYPT_STRING_NOCR", 0x80000000)
WSADESCRIPTION_LEN = make_flag("WSADESCRIPTION_LEN", 256)
WSASYS_STATUS_LEN = make_flag("WSASYS_STATUS_LEN", 128)
WSAPROTOCOL_LEN = make_flag("WSAPROTOCOL_LEN", 255)
+20
View File
@@ -820,6 +820,26 @@ CryptSignAndEncodeCertificateParams = ((1, 'hBCryptKey'), (1, 'dwKeySpec'), (1,
CryptSignCertificatePrototype = WINFUNCTYPE(BOOL, BCRYPT_KEY_HANDLE, DWORD, DWORD, POINTER(BYTE), DWORD, PCRYPT_ALGORITHM_IDENTIFIER, PVOID, POINTER(BYTE), POINTER(DWORD))
CryptSignCertificateParams = ((1, 'hBCryptKey'), (1, 'dwKeySpec'), (1, 'dwCertEncodingType'), (1, 'pbEncodedToBeSigned'), (1, 'cbEncodedToBeSigned'), (1, 'pSignatureAlgorithm'), (1, 'pvHashAuxInfo'), (1, 'pbSignature'), (1, 'pcbSignature'))
#def CryptBinaryToStringA(pbBinary, cbBinary, dwFlags, pszString, pcchString):
# return CryptBinaryToStringA.ctypes_function(pbBinary, cbBinary, dwFlags, pszString, pcchString)
CryptBinaryToStringAPrototype = WINFUNCTYPE(BOOL, POINTER(BYTE), DWORD, DWORD, LPSTR, POINTER(DWORD))
CryptBinaryToStringAParams = ((1, 'pbBinary'), (1, 'cbBinary'), (1, 'dwFlags'), (1, 'pszString'), (1, 'pcchString'))
#def CryptBinaryToStringW(pbBinary, cbBinary, dwFlags, pszString, pcchString):
# return CryptBinaryToStringW.ctypes_function(pbBinary, cbBinary, dwFlags, pszString, pcchString)
CryptBinaryToStringWPrototype = WINFUNCTYPE(BOOL, POINTER(BYTE), DWORD, DWORD, LPWSTR, POINTER(DWORD))
CryptBinaryToStringWParams = ((1, 'pbBinary'), (1, 'cbBinary'), (1, 'dwFlags'), (1, 'pszString'), (1, 'pcchString'))
#def CryptStringToBinaryA(pszString, cchString, dwFlags, pbBinary, pcbBinary, pdwSkip, pdwFlags):
# return CryptStringToBinaryA.ctypes_function(pszString, cchString, dwFlags, pbBinary, pcbBinary, pdwSkip, pdwFlags)
CryptStringToBinaryAPrototype = WINFUNCTYPE(BOOL, LPCSTR, DWORD, DWORD, POINTER(BYTE), POINTER(DWORD), POINTER(DWORD), POINTER(DWORD))
CryptStringToBinaryAParams = ((1, 'pszString'), (1, 'cchString'), (1, 'dwFlags'), (1, 'pbBinary'), (1, 'pcbBinary'), (1, 'pdwSkip'), (1, 'pdwFlags'))
#def CryptStringToBinaryW(pszString, cchString, dwFlags, pbBinary, pcbBinary, pdwSkip, pdwFlags):
# return CryptStringToBinaryW.ctypes_function(pszString, cchString, dwFlags, pbBinary, pcbBinary, pdwSkip, pdwFlags)
CryptStringToBinaryWPrototype = WINFUNCTYPE(BOOL, LPCWSTR, DWORD, DWORD, POINTER(BYTE), POINTER(DWORD), POINTER(DWORD), POINTER(DWORD))
CryptStringToBinaryWParams = ((1, 'pszString'), (1, 'cchString'), (1, 'dwFlags'), (1, 'pbBinary'), (1, 'pcbBinary'), (1, 'pdwSkip'), (1, 'pdwFlags'))
#def OpenVirtualDisk(VirtualStorageType, Path, VirtualDiskAccessMask, Flags, Parameters, Handle):
# return OpenVirtualDisk.ctypes_function(VirtualStorageType, Path, VirtualDiskAccessMask, Flags, Parameters, Handle)
OpenVirtualDiskPrototype = WINFUNCTYPE(DWORD, PVIRTUAL_STORAGE_TYPE, PCWSTR, VIRTUAL_DISK_ACCESS_MASK, OPEN_VIRTUAL_DISK_FLAG, POPEN_VIRTUAL_DISK_PARAMETERS, PHANDLE)
+22
View File
@@ -244,3 +244,25 @@ def CryptProtectMemory(pDataIn, cbDataIn, dwFlags):
@Crypt32Proxy()
def CryptUnprotectMemory(pDataIn, cbDataIn, dwFlags):
return CryptUnprotectMemory.ctypes_function(pDataIn, cbDataIn, dwFlags)
# Binary <-> String
@Crypt32Proxy()
def CryptBinaryToStringA(pbBinary, cbBinary=None, dwFlags=NeededParameter, pszString=NeededParameter, pcchString=NeededParameter):
if cbBinary is None:
cbBinary = len(pbBinary)
return CryptBinaryToStringA.ctypes_function(pbBinary, cbBinary, dwFlags, pszString, pcchString)
@Crypt32Proxy()
def CryptBinaryToStringW(pbBinary, cbBinary=None, dwFlags=NeededParameter, pszString=NeededParameter, pcchString=NeededParameter):
if cbBinary is None:
cbBinary = len(pbBinary)
return CryptBinaryToStringW.ctypes_function(pbBinary, cbBinary, dwFlags, pszString, pcchString)
@Crypt32Proxy()
def CryptStringToBinaryA(pszString, cchString, dwFlags, pbBinary, pcbBinary, pdwSkip, pdwFlags):
return CryptStringToBinaryA.ctypes_function(pszString, cchString, dwFlags, pbBinary, pcbBinary, pdwSkip, pdwFlags)
@Crypt32Proxy()
def CryptStringToBinaryW(pszString, cchString, dwFlags, pbBinary, pcbBinary, pdwSkip, pdwFlags):
return CryptStringToBinaryW.ctypes_function(pszString, cchString, dwFlags, pbBinary, pcbBinary, pdwSkip, pdwFlags)