forked from atessift/chrome-passwords-cli
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathpass
More file actions
executable file
·113 lines (96 loc) · 3.74 KB
/
pass
File metadata and controls
executable file
·113 lines (96 loc) · 3.74 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
#!/usr/bin/env python3
import argparse
import base64
import codecs
import os
import sqlite3
import tempfile
from urllib.parse import urlparse
import io
import percol
import percol.cli
import percol.action
import percol.actions
import pyperclip
from Crypto.Cipher import AES
import hashlib
import keyring
import collections
import getpass
HOME = os.path.expanduser('~')
CHROME = 'Library/Application Support/Google/Chrome'
PROFILE = 'Default'
LOGIN_DATA = 'Login Data'
CHROME_SERVICE = 'Chrome Safe Storage'
CHROME_USERNAME = 'Chrome'
def get_master_password():
app_name = os.path.splitext(os.path.basename(__file__))[0]
master = keyring.get_password(app_name, getpass.getuser())
if master is None:
master = str(keyring.get_password(CHROME_SERVICE, CHROME_USERNAME))
keyring.set_password(app_name, getpass.getuser(), master)
return master.encode('utf8')
def decrypt(password):
master_password = get_master_password()
key = hashlib.pbkdf2_hmac(hash_name='sha1', password=master_password,
salt=b'saltysalt', iterations=1003, dklen=16)
cipher = AES.new(key, AES.MODE_CBC, IV=b' ' * 16)
binary = cipher.decrypt(base64.b64decode(password))
return ''.join([chr(i) for i in binary if i >= 32])
def main(query, profile, out):
passwords = []
password2id = []
def candidates():
with tempfile.NamedTemporaryFile() as tmp:
with open(os.path.join(HOME, CHROME, profile, LOGIN_DATA), 'rb') as f:
tmp.write(f.read())
tmp.flush()
cursor = sqlite3.connect(tmp.name).cursor()
cursor.execute('''SELECT origin_url, username_value, password_value
FROM logins ORDER BY times_used desc''')
accounts = []
for i, (origin_url, account, password) in enumerate(cursor.fetchall()):
password = base64.b64encode(password[3:]).decode('utf8')
url = urlparse(origin_url)
title = codecs.decode(url.netloc.encode('utf8'), 'idna')
if title.lower().startswith('www.'):
title = title[4:]
if url.scheme == 'android':
title = '%s://%s' % (url.scheme, title.split('@')[1])
accounts.append((title, account))
passwords.append(password)
for key, _ in collections.Counter(passwords).most_common():
password2id.append(key)
for i, (title, account) in enumerate(accounts):
pass_id = password2id.index(passwords[i])
yield '{:>50} {:<40} {:0>3d} '.format(title, account, pass_id)
@percol.action.action()
def copy(lines, _):
pyperclip.copy(decrypt(password2id[int(lines[0].split()[-1])]))
if out:
# None-interactive, E.g. with --out
descriptors = {'stdin': io.StringIO(), 'stdout': io.StringIO(), 'stderr': io.StringIO()}
p = percol.Percol(actions=[], candidates=candidates(), query=query, descriptors=descriptors)
p.model.do_search(p.model.query)
results = p.model_candidate.get_selected_results_with_index()
if len(results) == 1:
print(decrypt(password2id[int(results[0][0].split()[-1])]), end='')
exit_code = 0
else:
exit_code = 1
exit(exit_code)
else:
# Interactive
with percol.Percol(actions=[copy], candidates=candidates(), query=query) as p:
percol.cli.load_rc(p)
p.view.PROMPT = "<bold><yellow>Search</yellow></bold> %q" # type: ignore
p.view.CANDIDATES_LINE_SELECTED = ("underline", "on_blue", "black") # type: ignore
exit_code = p.loop()
exit(exit_code)
if __name__ == '__main__':
parser = argparse.ArgumentParser()
parser.add_argument('query', default='', nargs='?')
parser.add_argument('--profile', default=PROFILE)
parser.add_argument('--out', default=False, action='store_true', help='None-interactive; Output password to stdout')
args = parser.parse_args()
main(args.query, args.profile, args.out)