1
+ #!/usr/bin/env python2
2
+
3
+ from trezorlib .client import TrezorClient
4
+ from trezorlib .transport_hid import HidTransport
5
+ from binascii import hexlify , unhexlify
6
+ from cryptography .hazmat .primitives .ciphers import Cipher , algorithms , modes
7
+ from cryptography .hazmat .backends import default_backend
8
+ import hmac , hashlib , base58 , json , sys
9
+
10
+
11
+ #return path by BIP-32
12
+ def getPath ():
13
+ return client .expand_path ("10016'/0" );
14
+
15
+ #Deriving master key
16
+ def getMasterKey ():
17
+ bip32_path = getPath ()
18
+ ENC_KEY = "Activate TREZOR Password Manager?"
19
+ ENC_VALUE = unhexlify ("2d650551248d792eabf628f451200d7f51cb63e46aadcbb1038aacb05e8c8aee2d650551248d792eabf628f451200d7f51cb63e46aadcbb1038aacb05e8c8aee" )
20
+ key = hexlify (client .encrypt_keyvalue (
21
+ bip32_path ,
22
+ ENC_KEY ,
23
+ ENC_VALUE ,
24
+ True ,
25
+ True
26
+ ))
27
+ return key ;
28
+
29
+ #Deriving file name and encryption key
30
+ def getFileEncKey (key ):
31
+ filekey , enckey = key [:len (key )/ 2 ], key [len (key )/ 2 :]
32
+ FILENAME_MESS = "5f91add3fa1c3c76e90c90a3bd0999e2bd7833d06a483fe884ee60397aca277a"
33
+ digest = hmac .new (filekey , FILENAME_MESS , hashlib .sha256 ).hexdigest ()
34
+ filename = '' .join ((digest , '.pswd' ))
35
+ return [filename , filekey , enckey ];
36
+
37
+ #Path to locally stored file
38
+ def getFilePath ():
39
+ return '/home/chren/' ;
40
+
41
+ #File level decryption and file reading
42
+ def decryptStorage (path , key ):
43
+ cipherkey = unhexlify (key )
44
+ with open (path , "rb" ) as f :
45
+ iv = f .read (12 )
46
+ tag = f .read (16 )
47
+ cipher = Cipher (algorithms .AES (cipherkey ), modes .GCM (iv , tag ), backend = default_backend ())
48
+ decryptor = cipher .decryptor ()
49
+ data = "" ;
50
+ while True :
51
+ block = f .read (16 )
52
+ # data are not authenticated yet
53
+ if block :
54
+ data = data + decryptor .update (block )
55
+ else :
56
+ break
57
+ # throws exception when the tag is wrong
58
+ data = data + decryptor .finalize ()
59
+ return json .loads (data );
60
+
61
+ def decryptEntryValue (nonce , val ):
62
+ cipherkey = unhexlify (nonce )
63
+ iv = val [:12 ]
64
+ tag = val [12 :28 ]
65
+ cipher = Cipher (algorithms .AES (cipherkey ), modes .GCM (iv , tag ), backend = default_backend ())
66
+ decryptor = cipher .decryptor ()
67
+ data = "" ;
68
+ inputData = val [28 :]
69
+ while True :
70
+ block = inputData [:16 ]
71
+ inputData = inputData [16 :]
72
+ if block :
73
+ data = data + decryptor .update (block )
74
+ else :
75
+ break
76
+ # throws exception when the tag is wrong
77
+ data = data + decryptor .finalize ()
78
+ return json .loads (data );
79
+
80
+ #decrypt give entry nonce
81
+ def getDecryptedNonce (entry ):
82
+ print '\n Waiting for TREZOR input!\n '
83
+ ENC_KEY = '' .join (('Unlock ' , entry ['title' ], ' for user ' , entry ['username' ], '?' ))
84
+ ENC_VALUE = entry ['nonce' ]
85
+ decrypted_nonce = hexlify (client .decrypt_keyvalue (
86
+ getPath (),
87
+ ENC_KEY ,
88
+ unhexlify (ENC_VALUE ),
89
+ False ,
90
+ True
91
+ ))
92
+ return decrypted_nonce ;
93
+
94
+ #list whatever
95
+ def printList (obj , val ):
96
+ objList = obj [val ]
97
+ print '\n '
98
+ print 'Entry list:'
99
+ for x in xrange (len (objList )):
100
+ keys = objList [str (x )].keys ()
101
+ print 'Entry id ' , x
102
+ for y in xrange (len (keys )):
103
+ print keys [y ],': ' ,objList [str (x )][keys [y ]]
104
+ print '\n '
105
+ return ;
106
+
107
+
108
+ def main ():
109
+ masterKey = getMasterKey ()
110
+ #print 'master key: ', masterKey
111
+
112
+ fileName = getFileEncKey (masterKey )[0 ]
113
+ #print 'file name: ', fileName
114
+
115
+ path = getFilePath ()
116
+ #print 'path to file: ', path
117
+
118
+ encKey = getFileEncKey (masterKey )[2 ]
119
+ #print 'enckey: ', encKey
120
+
121
+ full_path = '' .join ((path , fileName ))
122
+ parsed_json = decryptStorage (full_path , encKey )
123
+
124
+ #list entries
125
+ printList (parsed_json , 'entries' )
126
+ entries = parsed_json ['entries' ]
127
+
128
+ entry_id = raw_input ('Select entry number to decrypt: ' )
129
+
130
+ plain_nonce = getDecryptedNonce (entries [str (entry_id )])
131
+
132
+
133
+ pwdArr = entries [str (entry_id )]['password' ]['data' ]
134
+ pwdHex = '' .join ([ hex (x )[2 :].zfill (2 ) for x in pwdArr ])
135
+ print 'password : ' , decryptEntryValue (plain_nonce , unhexlify (pwdHex ))
136
+
137
+ safeNoteArr = entries [str (entry_id )]['safe_note' ]['data' ]
138
+ safeNoteHex = '' .join ([ hex (x )[2 :].zfill (2 ) for x in safeNoteArr ])
139
+ print 'safe_note : ' , decryptEntryValue (plain_nonce , unhexlify (safeNoteHex ))
140
+ return ;
141
+
142
+ if __name__ == "__main__" :
143
+ try :
144
+ # init Trezor transport
145
+ client = TrezorClient (HidTransport (HidTransport .enumerate ()[0 ]))
146
+ except :
147
+ print 'TREZOR is not plugged in. Please, connect TREZOR and retry.'
148
+ else :
149
+ main ()
0 commit comments