waf

FORK: waf with some random patches
git clone https://git.neptards.moe/neptards/waf.git
Log | Files | Refs | README

dpapi.py (2934B)


      1 #! /usr/bin/env python
      2 # encoding: utf-8
      3 # Matt Clarkson, 2012
      4 
      5 '''
      6 DPAPI access library (http://msdn.microsoft.com/en-us/library/ms995355.aspx)
      7 This file uses code originally created by Crusher Joe:
      8 http://article.gmane.org/gmane.comp.python.ctypes/420
      9 And modified by Wayne Koorts:
     10 http://stackoverflow.com/questions/463832/using-dpapi-with-python
     11 '''
     12 
     13 from ctypes import windll, byref, cdll, Structure, POINTER, c_char, c_buffer
     14 from ctypes.wintypes import DWORD
     15 from waflib.Configure import conf
     16 
     17 LocalFree = windll.kernel32.LocalFree
     18 memcpy = cdll.msvcrt.memcpy
     19 CryptProtectData = windll.crypt32.CryptProtectData
     20 CryptUnprotectData = windll.crypt32.CryptUnprotectData
     21 CRYPTPROTECT_UI_FORBIDDEN = 0x01
     22 try:
     23 	extra_entropy = 'cl;ad13 \0al;323kjd #(adl;k$#ajsd'.encode('ascii')
     24 except AttributeError:
     25 	extra_entropy = 'cl;ad13 \0al;323kjd #(adl;k$#ajsd'
     26 
     27 class DATA_BLOB(Structure):
     28 	_fields_ = [
     29 		('cbData', DWORD),
     30 		('pbData', POINTER(c_char))
     31 	]
     32 
     33 def get_data(blob_out):
     34 	cbData = int(blob_out.cbData)
     35 	pbData = blob_out.pbData
     36 	buffer = c_buffer(cbData)
     37 	memcpy(buffer, pbData, cbData)
     38 	LocalFree(pbData)
     39 	return buffer.raw
     40 
     41 @conf
     42 def dpapi_encrypt_data(self, input_bytes, entropy = extra_entropy):
     43 	'''
     44 	Encrypts data and returns byte string
     45 
     46 	:param input_bytes: The data to be encrypted
     47 	:type input_bytes: String or Bytes
     48 	:param entropy: Extra entropy to add to the encryption process (optional)
     49 	:type entropy: String or Bytes
     50 	'''
     51 	if not isinstance(input_bytes, bytes) or not isinstance(entropy, bytes):
     52 		self.fatal('The inputs to dpapi must be bytes')
     53 	buffer_in      = c_buffer(input_bytes, len(input_bytes))
     54 	buffer_entropy = c_buffer(entropy, len(entropy))
     55 	blob_in        = DATA_BLOB(len(input_bytes), buffer_in)
     56 	blob_entropy   = DATA_BLOB(len(entropy), buffer_entropy)
     57 	blob_out       = DATA_BLOB()
     58 
     59 	if CryptProtectData(byref(blob_in), 'python_data', byref(blob_entropy), 
     60 		None, None, CRYPTPROTECT_UI_FORBIDDEN, byref(blob_out)):
     61 		return get_data(blob_out)
     62 	else:
     63 		self.fatal('Failed to decrypt data')
     64 
     65 @conf
     66 def dpapi_decrypt_data(self, encrypted_bytes, entropy = extra_entropy):
     67 	'''
     68 	Decrypts data and returns byte string
     69 
     70 	:param encrypted_bytes: The encrypted data
     71 	:type encrypted_bytes: Bytes
     72 	:param entropy: Extra entropy to add to the encryption process (optional)
     73 	:type entropy: String or Bytes
     74 	'''
     75 	if not isinstance(encrypted_bytes, bytes) or not isinstance(entropy, bytes):
     76 		self.fatal('The inputs to dpapi must be bytes')
     77 	buffer_in      = c_buffer(encrypted_bytes, len(encrypted_bytes))
     78 	buffer_entropy = c_buffer(entropy, len(entropy))
     79 	blob_in        = DATA_BLOB(len(encrypted_bytes), buffer_in)
     80 	blob_entropy   = DATA_BLOB(len(entropy), buffer_entropy)
     81 	blob_out       = DATA_BLOB()
     82 	if CryptUnprotectData(byref(blob_in), None, byref(blob_entropy), None,
     83 		None, CRYPTPROTECT_UI_FORBIDDEN, byref(blob_out)):
     84 		return get_data(blob_out)
     85 	else:
     86 		self.fatal('Failed to decrypt data')
     87