2009-01-21 7 views
14

Existe-t-il un moyen d'utiliser le DPAPI (Data Protection Application Programming Interface) sur Windows XP avec Python?Utilisation de DPAPI avec Python?

Je préférerais utiliser un module existant s'il y en a un qui peut le faire. Malheureusement, je n'ai pas réussi à trouver un moyen avec Google ou Stack Overflow.

EDIT: J'ai pris l'exemple de code pointé par « df » et peaufiné dans une bibliothèque autonome qui peut être utilisé simplement à un niveau élevé pour crypte et décrypter en utilisant DPAPI en mode utilisateur. Il suffit d'appeler dpapi.cryptData (text_to_encrypt) qui renvoie une chaîne chiffrée, ou le reverse decryptData (encrypted_data_string), qui renvoie le texte brut. Voici la bibliothèque:

# DPAPI access library 
# This file uses code originally created by Crusher Joe: 
# http://article.gmane.org/gmane.comp.python.ctypes/420 
# 

from ctypes import * 
from ctypes.wintypes import DWORD 

LocalFree = windll.kernel32.LocalFree 
memcpy = cdll.msvcrt.memcpy 
CryptProtectData = windll.crypt32.CryptProtectData 
CryptUnprotectData = windll.crypt32.CryptUnprotectData 
CRYPTPROTECT_UI_FORBIDDEN = 0x01 
extraEntropy = "cl;ad13 \0al;323kjd #(adl;k$#ajsd" 

class DATA_BLOB(Structure): 
    _fields_ = [("cbData", DWORD), ("pbData", POINTER(c_char))] 

def getData(blobOut): 
    cbData = int(blobOut.cbData) 
    pbData = blobOut.pbData 
    buffer = c_buffer(cbData) 
    memcpy(buffer, pbData, cbData) 
    LocalFree(pbData); 
    return buffer.raw 

def Win32CryptProtectData(plainText, entropy): 
    bufferIn = c_buffer(plainText, len(plainText)) 
    blobIn = DATA_BLOB(len(plainText), bufferIn) 
    bufferEntropy = c_buffer(entropy, len(entropy)) 
    blobEntropy = DATA_BLOB(len(entropy), bufferEntropy) 
    blobOut = DATA_BLOB() 

    if CryptProtectData(byref(blobIn), u"python_data", byref(blobEntropy), 
         None, None, CRYPTPROTECT_UI_FORBIDDEN, byref(blobOut)): 
     return getData(blobOut) 
    else: 
     return "" 

def Win32CryptUnprotectData(cipherText, entropy): 
    bufferIn = c_buffer(cipherText, len(cipherText)) 
    blobIn = DATA_BLOB(len(cipherText), bufferIn) 
    bufferEntropy = c_buffer(entropy, len(entropy)) 
    blobEntropy = DATA_BLOB(len(entropy), bufferEntropy) 
    blobOut = DATA_BLOB() 
    if CryptUnprotectData(byref(blobIn), None, byref(blobEntropy), None, None, 
           CRYPTPROTECT_UI_FORBIDDEN, byref(blobOut)): 
     return getData(blobOut) 
    else: 
     return "" 

def cryptData(text): 
    return Win32CryptProtectData(text, extraEntropy) 

def decryptData(cipher_text): 
    return Win32CryptUnprotectData(cipher_text, extraEntropy) 
+0

Sweet - super mise à jour. –

+0

Cela ne fonctionne pas sur Win7 64 bits, python 3.5.2. Il renvoie une chaîne binaire vide. –

Répondre

8

J'utilise CryptProtectData et CryptUnprotectData par ctypes, avec le code de

http://article.gmane.org/gmane.comp.python.ctypes/420

et il travaille bien.

+0

Fantastique, juste ce que je cherchais. Je vous remercie. –

+1

Merci pour le bon conseil. J'ai fait un peu de refactoring et j'ai ajouté cette fonctionnalité au projet jaraco.windows. Voir https://svn.jaraco.com/jaraco/python/jaraco.windows/jaraco/windows/dpapi.py pour plus de détails. –

+0

Ce code est-il compatible avec Python 3? –

2

La meilleure façon serait d'utiliser Iron Python.

+0

Merci, mais je préférerais vraiment quelque chose qui puisse être utilisé avec la distribution standard de python.org. –

4

De plus, pywin32 implémente CryptProtectData et CryptUnprotectData dans le module win32crypt.

+0

Merci pour le conseil, je vais probablement commencer à l'utiliser à partir de maintenant. –

Questions connexes