diff options
author | David Robillard <d@drobilla.net> | 2019-03-17 17:31:05 +0100 |
---|---|---|
committer | David Robillard <d@drobilla.net> | 2019-03-17 17:31:05 +0100 |
commit | 406f89271452fdb573c7e28113b1ed08ff2b4eda (patch) | |
tree | d2dcbaf61f3749f73dc7a5e10d3fc6cd5e6e129a /extras/dpapi.py | |
parent | 7983a5aae615290d04fd43cbc2752f8cf4a46d10 (diff) | |
download | suil-406f89271452fdb573c7e28113b1ed08ff2b4eda.tar.gz suil-406f89271452fdb573c7e28113b1ed08ff2b4eda.tar.bz2 suil-406f89271452fdb573c7e28113b1ed08ff2b4eda.zip |
Squashed 'waflib/' changes from 915dcb1..e7a29b6
e7a29b6 Upgrade to waf 2.0.15
8280f9d Add command for running executables from the build directory
8073c1a Make make_simple_dox() safe in case of exception
70d03b8 Avoid use of global counter hacks for configuration display
b7d689a Rewrite test framework
94deadf Automatically add options and move add_flags() to options context
f4259ee Reduce system include path noise
927b608 Automatically display configuration header
c44b8f3 Set line justification from a constant in the wscript
a48e26f Automatically detect if wscript has a test hook
ef66724 Save runtime variables in the environment
63bcbcd Clean up TestContext
b1d9505 Add ExecutionContext for setting runtime environment
387c1df Add show_diff() and test_file_equals() utilities
29d4d29 Fix in-tree library paths
9fde01f Add custom configuration context
6d3612f Add lib_path_name constant
git-subtree-dir: waflib
git-subtree-split: e7a29b6b9b2f842314244c23c14d8f8f560904e1
Diffstat (limited to 'extras/dpapi.py')
-rw-r--r-- | extras/dpapi.py | 87 |
1 files changed, 87 insertions, 0 deletions
diff --git a/extras/dpapi.py b/extras/dpapi.py new file mode 100644 index 0000000..b94d482 --- /dev/null +++ b/extras/dpapi.py @@ -0,0 +1,87 @@ +#! /usr/bin/env python +# encoding: utf-8 +# Matt Clarkson, 2012 + +''' +DPAPI access library (http://msdn.microsoft.com/en-us/library/ms995355.aspx) +This file uses code originally created by Crusher Joe: +http://article.gmane.org/gmane.comp.python.ctypes/420 +And modified by Wayne Koorts: +http://stackoverflow.com/questions/463832/using-dpapi-with-python +''' + +from ctypes import windll, byref, cdll, Structure, POINTER, c_char, c_buffer +from ctypes.wintypes import DWORD +from waflib.Configure import conf + +LocalFree = windll.kernel32.LocalFree +memcpy = cdll.msvcrt.memcpy +CryptProtectData = windll.crypt32.CryptProtectData +CryptUnprotectData = windll.crypt32.CryptUnprotectData +CRYPTPROTECT_UI_FORBIDDEN = 0x01 +try: + extra_entropy = 'cl;ad13 \0al;323kjd #(adl;k$#ajsd'.encode('ascii') +except AttributeError: + extra_entropy = 'cl;ad13 \0al;323kjd #(adl;k$#ajsd' + +class DATA_BLOB(Structure): + _fields_ = [ + ('cbData', DWORD), + ('pbData', POINTER(c_char)) + ] + +def get_data(blob_out): + cbData = int(blob_out.cbData) + pbData = blob_out.pbData + buffer = c_buffer(cbData) + memcpy(buffer, pbData, cbData) + LocalFree(pbData) + return buffer.raw + +@conf +def dpapi_encrypt_data(self, input_bytes, entropy = extra_entropy): + ''' + Encrypts data and returns byte string + + :param input_bytes: The data to be encrypted + :type input_bytes: String or Bytes + :param entropy: Extra entropy to add to the encryption process (optional) + :type entropy: String or Bytes + ''' + if not isinstance(input_bytes, bytes) or not isinstance(entropy, bytes): + self.fatal('The inputs to dpapi must be bytes') + buffer_in = c_buffer(input_bytes, len(input_bytes)) + buffer_entropy = c_buffer(entropy, len(entropy)) + blob_in = DATA_BLOB(len(input_bytes), buffer_in) + blob_entropy = DATA_BLOB(len(entropy), buffer_entropy) + blob_out = DATA_BLOB() + + if CryptProtectData(byref(blob_in), 'python_data', byref(blob_entropy), + None, None, CRYPTPROTECT_UI_FORBIDDEN, byref(blob_out)): + return get_data(blob_out) + else: + self.fatal('Failed to decrypt data') + +@conf +def dpapi_decrypt_data(self, encrypted_bytes, entropy = extra_entropy): + ''' + Decrypts data and returns byte string + + :param encrypted_bytes: The encrypted data + :type encrypted_bytes: Bytes + :param entropy: Extra entropy to add to the encryption process (optional) + :type entropy: String or Bytes + ''' + if not isinstance(encrypted_bytes, bytes) or not isinstance(entropy, bytes): + self.fatal('The inputs to dpapi must be bytes') + buffer_in = c_buffer(encrypted_bytes, len(encrypted_bytes)) + buffer_entropy = c_buffer(entropy, len(entropy)) + blob_in = DATA_BLOB(len(encrypted_bytes), buffer_in) + blob_entropy = DATA_BLOB(len(entropy), buffer_entropy) + blob_out = DATA_BLOB() + if CryptUnprotectData(byref(blob_in), None, byref(blob_entropy), None, + None, CRYPTPROTECT_UI_FORBIDDEN, byref(blob_out)): + return get_data(blob_out) + else: + self.fatal('Failed to decrypt data') + |