forked from trezor/python-trezor
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathencfs_aes_getpass.py
executable file
·138 lines (103 loc) · 3.6 KB
/
encfs_aes_getpass.py
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
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
#!/usr/bin/env python3
"""
Use TREZOR as a hardware key for opening EncFS filesystem!
Usage:
encfs --standard --extpass=./encfs_aes_getpass.py ~/.crypt ~/crypt
"""
import os
import sys
import json
import hashlib
import trezorlib
version_tuple = tuple(map(int, trezorlib.__version__.split(".")))
if not (0, 11) <= version_tuple < (0, 12):
raise RuntimeError("trezorlib version mismatch (0.11.x is required)")
from trezorlib.client import TrezorClient
from trezorlib.transport import enumerate_devices
from trezorlib.ui import ClickUI
import trezorlib.misc
def wait_for_devices():
devices = enumerate_devices()
while not len(devices):
sys.stderr.write("Please connect TREZOR to computer and press Enter...")
input()
devices = enumerate_devices()
return devices
def choose_device(devices):
if not len(devices):
raise RuntimeError("No TREZOR connected!")
if len(devices) == 1:
try:
return devices[0]
except IOError:
raise RuntimeError("Device is currently in use")
i = 0
sys.stderr.write("----------------------------\n")
sys.stderr.write("Available devices:\n")
for d in devices:
try:
client = TrezorClient(d, ui=ClickUI())
except IOError:
sys.stderr.write("[-] <device is currently in use>\n")
continue
if client.features.label:
sys.stderr.write("[%d] %s\n" % (i, client.features.label))
else:
sys.stderr.write("[%d] <no label>\n" % i)
client.close()
i += 1
sys.stderr.write("----------------------------\n")
sys.stderr.write("Please choose device to use:")
try:
device_id = int(input())
return devices[device_id]
except Exception:
raise ValueError("Invalid choice, exiting...")
def main():
if "encfs_root" not in os.environ:
sys.stderr.write(
"\nThis is not a standalone script and is not meant to be run independently.\n"
)
sys.stderr.write(
"\nUsage: encfs --standard --extpass=./encfs_aes_getpass.py ~/.crypt ~/crypt\n"
)
sys.exit(1)
devices = wait_for_devices()
transport = choose_device(devices)
client = TrezorClient(transport, ui=ClickUI())
rootdir = os.environ["encfs_root"] # Read "man encfs" for more
passw_file = os.path.join(rootdir, "password.dat")
if not os.path.exists(passw_file):
# New encfs drive, let's generate password
sys.stderr.write("Please provide label for new drive: ")
label = input()
sys.stderr.write("Computer asked TREZOR for new strong password.\n")
# 32 bytes, good for AES
trezor_entropy = trezorlib.misc.get_entropy(client, 32)
urandom_entropy = os.urandom(32)
passw = hashlib.sha256(trezor_entropy + urandom_entropy).digest()
if len(passw) != 32:
raise ValueError("32 bytes password expected")
bip32_path = [10, 0]
passw_encrypted = trezorlib.misc.encrypt_keyvalue(
client, bip32_path, label, passw, False, True
)
data = {
"label": label,
"bip32_path": bip32_path,
"password_encrypted_hex": passw_encrypted.hex(),
}
json.dump(data, open(passw_file, "w"))
# Let's load password
data = json.load(open(passw_file, "r"))
passw = trezorlib.misc.decrypt_keyvalue(
client,
data["bip32_path"],
data["label"],
bytes.fromhex(data["password_encrypted_hex"]),
False,
True,
)
print(passw)
if __name__ == "__main__":
main()