Skip to content

Commit 6aaffb4

Browse files
author
8go
authored
Merge pull request #4 from 8go/pythonv3-port
tiny step towards future port to Py3.4
2 parents 14ac368 + 11305d2 commit 6aaffb4

8 files changed

Lines changed: 104 additions & 49 deletions

File tree

README.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ Below a sample screenshot. More screenshots [here](screenshots).
4646
# Build and runtime requirements
4747

4848
* Use of passphrases must have been already enabled on your [Trezor](https://www.trezor.io) device.
49-
* [Python](https://www.python.org/)
49+
* [Python](https://www.python.org/) v2.7
5050
* PyCrypto
5151
* PyQt4
5252
* [trezorlib from python-trezor](https://github.com/trezor/python-trezor)
@@ -73,7 +73,7 @@ Run-time command line options are
7373

7474
```
7575
TrezorSymmetricFileEncryption.py [-v] [-h] [-l <level>] [-t] [-e | -o | -d | -m | -n] [-2] [-s] [-w] [-p <passphrase>] [-r] [-R] <files>
76-
-v, --verion
76+
-v, --version
7777
print the version number
7878
-h, --help
7979
print short help text
@@ -266,7 +266,7 @@ single-file-executablefile.
266266
- - -
267267
**Question:** In which language is TrezorSymmetricFileEncryption written?
268268

269-
**Answer:** [Python](https://www.python.org/).
269+
**Answer:** [Python](https://www.python.org/) 2.7. It wil currently not run on Python 3.
270270
- - -
271271
**Question:** Do I need to have a [Trezor](https://www.trezor.io/) in
272272
order to use TrezorSymmetricFileEncryption?

TrezorSymmetricFileEncryption.py

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,10 @@
1010
1111
'''
1212

13+
from __future__ import absolute_import
14+
from __future__ import division
15+
from __future__ import print_function
16+
1317
import sys
1418
import logging
1519
import getpass
@@ -46,17 +50,17 @@ def callback_ButtonRequest(self, msg):
4650

4751
def callback_PassphraseRequest(self, msg):
4852
if self.passphrase is not None:
49-
return proto.PassphraseAck(passphrase=unicode(self.passphrase))
53+
return proto.PassphraseAck(passphrase=str(self.passphrase))
5054

5155
if self.readpassphrasefromstdin:
5256
# read passphrase from stdin
5357
try:
5458
passphrase = getpass.getpass("Please enter passphrase: ")
55-
passphrase = unicode(passphrase)
59+
passphrase = str(passphrase)
5660
except KeyboardInterrupt:
5761
sys.stderr.write("\nKeyboard interrupt: passphrase not read. Aborting.\n")
5862
sys.exit(3)
59-
except Exception, e:
63+
except Exception as e:
6064
sys.stderr.write("Critical error: Passphrase not read. Aborting. (%s)" % e)
6165
sys.exit(3)
6266
else:
@@ -65,22 +69,22 @@ def callback_PassphraseRequest(self, msg):
6569
sys.exit(3)
6670
else:
6771
passphrase = dialog.passphraseEdit.text()
68-
passphrase = unicode(passphrase)
72+
passphrase = str(passphrase)
6973

7074
return proto.PassphraseAck(passphrase=passphrase)
7175

7276
def callback_PinMatrixRequest(self, msg):
7377
if self.readpinfromstdin:
7478
# read PIN from stdin
75-
print " 7 8 9"
76-
print " 4 5 6"
77-
print " 1 2 3"
79+
print(" 7 8 9")
80+
print(" 4 5 6")
81+
print(" 1 2 3")
7882
try:
7983
pin = getpass.getpass("Please enter PIN: ")
8084
except KeyboardInterrupt:
8185
sys.stderr.write("\nKeyboard interrupt: PIN not read. Aborting.\n")
8286
sys.exit(7)
83-
except Exception, e:
87+
except Exception as e:
8488
sys.stderr.write("Critical error: PIN not read. Aborting. (%s)" % e)
8589
sys.exit(7)
8690
else:
@@ -234,7 +238,7 @@ def showGui(trezor, settings, fileMap, logger):
234238
try:
235239
trezorChooser = TrezorChooser()
236240
trezor = trezorChooser.getDevice()
237-
except (ConnectionError, RuntimeError), e:
241+
except (ConnectionError, RuntimeError) as e:
238242
processing.reportLogging("Connection to Trezor failed: %s" % e.message,
239243
logging.CRITICAL, "Trezor Error", settings, logger)
240244
sys.exit(1)

basics.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
from __future__ import absolute_import
2+
from __future__ import division
3+
from __future__ import print_function
4+
15
import logging
26

37
# file extension for encrypted files with plaintext filename
@@ -7,7 +11,7 @@
711
TSFEFILEFORMATVERSION = 1
812

913
# Name of software version, must be less than 16 long
10-
TSFEVERSION = "v0.4.3"
14+
TSFEVERSION = "v0.5.0"
1115

1216
# Date of software version, only used in GUI
1317
TSFEVERSIONTEXT = "May 2017"

comments.md

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,3 +72,35 @@ The Trezor chip is slow. It takes the Trezor (model 1) device about 75 seconds
7272
- [x] make the image smaller on main window
7373
- [x] more Testing
7474
- [ ] get help with getting the word out, anyone wants to spread the word on Twitter, Reddit, with Trezor, Facebook, etc.?
75+
76+
# Migrating to Python3
77+
78+
Doing only Python 2.7 or only 3.4 is okay, but making both work on the same code base is cumbersome.
79+
The combination would be Py2.7 | Py3.4 + PyQt4.11.
80+
81+
* Basic description of the problem is [here](https://docs.python.org/3/howto/pyporting.html) with some pointers as how to start.
82+
* [2to3](https://docs.python.org/3/library/2to3.html) has been done. It was trivial. Only a few lines of code changed.
83+
* [modernize](https://python-modernize.readthedocs.io/en/latest/) has been done. Again, it was just suggesting a few new lines related to the `range` operator.
84+
* [futurize](http://python-future.org/automatic_conversion.html) was also done. It suggested only a few `import` lines. The 3 lines were added to all .py files.
85+
```
86+
from __future__ import absolute_import
87+
from __future__ import division
88+
from __future__ import print_function
89+
```
90+
* Changes related to GUI are:
91+
PyQt4.11 for Py3.4 does not have class QString. It expects unicode objects. Simple hacks like
92+
the folowing are not likely to work.
93+
```
94+
try:
95+
from PyQt4.QtCore import QString
96+
except ImportError:
97+
# we are using Python3 so QString is not defined
98+
QString = type("")
99+
```
100+
* Since Py2.7 does not have bytes and handles everything as strings. A common layer would have to be introduced
101+
that simulates bytes on Py2.7. Some good code starting points can be found at
102+
[python3porting.com](http://python3porting.com/problems.html#bytes-strings-and-unicode).
103+
* In Debian 9 Py2 will remain the default Py version, so Py2.7 does not seem to be going away.
104+
105+
In short, for the time being it does not seem worth it to add code to make it run on both 2.7 and 3.4.
106+
It seems one can wait until 2.7 becomes outdated and then port to 3.5, breaking and leaving 2.7 behind.

dialogs.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
from __future__ import absolute_import
2+
from __future__ import division
3+
from __future__ import print_function
4+
15
import os
26
import os.path
37
import logging

encoding.py

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,18 @@
1-
import struct
2-
3-
from PyQt4 import QtCore
1+
from __future__ import absolute_import
2+
from __future__ import division
3+
from __future__ import print_function
44

55
import os
66
import os.path
77
import random
8+
import struct
9+
10+
from PyQt4 import QtCore
811

912

10-
def q2s(s):
13+
def q2s(q):
1114
"""Convert QString to UTF-8 string object"""
12-
return str(s.toUtf8())
15+
return str(q.toUtf8())
1316

1417

1518
def s2q(s):
@@ -33,21 +36,21 @@ class Magic(object):
3336
for keys.
3437
"""
3538

36-
headerStr = "TSFE"
39+
headerStr = b'TSFE'
3740
hdr = u("!I", headerStr)
3841

3942
# first level encryption
4043
# unlock key for first level AES encryption, key from Trezor, en/decryption on PC
41-
levelOneNode = [hdr, u("!I", "DEC1")]
44+
levelOneNode = [hdr, u("!I", b'DEC1')]
4245
levelOneKey = "Decrypt file for first time?" # string to derive wrapping key from
4346

4447
# second level encryption
4548
# second level AES encryption, de/encryption on trezor device
46-
levelTwoNode = [hdr, u("!I", "DEC2")]
49+
levelTwoNode = [hdr, u("!I", b'DEC2')]
4750
levelTwoKey = "Decrypt file for second time?"
4851

4952
# only used for filename encryption (no confirm button click desired)
50-
fileNameNode = [hdr, u("!I", "FLNM")] # filename encryption for filename obfuscation
53+
fileNameNode = [hdr, u("!I", b'FLNM')] # filename encryption for filename obfuscation
5154
fileNameKey = "Decrypt filename only?"
5255

5356

file_map.py

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
from __future__ import absolute_import
2+
from __future__ import division
3+
from __future__ import print_function
4+
15
import os
26
import os.path
37
import sys
@@ -80,7 +84,7 @@ def createDecFile(self, fname):
8084
"Change file permissions and try again." % (fname))
8185

8286
self.loadBlobFromEncFile(originalFilename)
83-
with open(fname, 'w+b') as f:
87+
with open(fname, "wb") as f:
8488
s = len(self.blob)
8589
f.write(self.blob)
8690
if f.tell() != s:
@@ -118,7 +122,7 @@ def loadBlobFromEncFile(self, fname):
118122
119123
@throws IOError: if reading file failed
120124
"""
121-
with open(fname, 'rb') as f:
125+
with open(fname, "rb") as f:
122126
header = f.read(len(Magic.headerStr))
123127
if header != Magic.headerStr:
124128
raise IOError("Bad header in storage file")
@@ -202,7 +206,7 @@ def createEncFile(self, fname, obfuscate, twice, outerKey=None, outerIv=None, in
202206
@param innerIv: see outerKey
203207
"""
204208

205-
with open(fname, 'rb') as f:
209+
with open(fname, "rb") as f:
206210
# Size 0 will read the ENTIRE file into memory!
207211
# File is open read-only
208212
# mmap does not implement __exit__ so we cannot use "with mmap... as m:"
@@ -427,15 +431,15 @@ def encryptOnTrezorDevice(self, blob, keystring, innerIv=None):
427431
try:
428432
encrypted += self.trezor.encrypt_keyvalue(Magic.levelTwoNode,
429433
ukeystring, padded, ask_on_encrypt=False, ask_on_decrypt=first, iv=rndBlock)
430-
except Exception, e:
434+
except Exception as e:
431435
self.logger.critical('Trezor failed. (%s)', e)
432436
raise
433437
first = False
434438
curr += 1
435439
if self.logger.getEffectiveLevel() == logging.DEBUG:
436-
print >> sys.stderr, "\rencrypting block", curr, "of", max,
440+
sys.stderr.write("\rencrypting block %d of %d" % (curr, max),)
437441
if self.logger.getEffectiveLevel() == logging.DEBUG:
438-
print >> sys.stderr, "done"
442+
sys.stderr.write(" --> done\n")
439443
ret = rndBlock + encrypted
440444
self.logger.debug("Trezor encryption: plain-size = %d, encrypted-size = %d", len(blob), len(ret))
441445
self.logger.debug('time leaving encryptOnTrezorDevice: %s', datetime.datetime.now())
@@ -453,7 +457,7 @@ def decryptOnTrezorDevice(self, encryptedblob, keystring):
453457
"Decrypting each Megabyte on the Trezor (model 1) takes about 75 seconds, "
454458
"or 0.8MB/min. This file will take about %d minutes. If you want to "
455459
"en/decrypt fast the next time around, remove the `-2` or `--twice` "
456-
"option when you encrypt a file.", len(encryptedblob) / 819200)
460+
"option when you encrypt a file.", len(encryptedblob) // 819200)
457461
self.logger.debug('time entering decryptOnTrezorDevice: %s', datetime.datetime.now())
458462
ukeystring = keystring.decode("utf-8")
459463
iv, encryptedblob = encryptedblob[:BLOCKSIZE], encryptedblob[BLOCKSIZE:]
@@ -469,16 +473,16 @@ def decryptOnTrezorDevice(self, encryptedblob, keystring):
469473
try:
470474
plain = self.trezor.decrypt_keyvalue(Magic.levelTwoNode,
471475
ukeystring, junk, ask_on_encrypt=False, ask_on_decrypt=first, iv=iv)
472-
except Exception, e:
476+
except Exception as e:
473477
self.logger.critical('Trezor failed. (%s)', e)
474478
raise
475479
first = False
476480
blob += Padding(BLOCKSIZE).unpad(plain)
477481
curr += 1
478482
if self.logger.getEffectiveLevel() == logging.DEBUG:
479-
print >> sys.stderr, "\rdecrypting block", curr, "of", max,
483+
sys.stderr.write("\rdecrypting block %d of %d" % (curr, max),)
480484
if self.logger.getEffectiveLevel() == logging.DEBUG:
481-
print >> sys.stderr, "done"
485+
sys.stderr.write(" --> done\n")
482486
self.logger.debug("Trezor decryption: encrypted-size = %d, plain-size = %d",
483487
len(encryptedblob), len(blob))
484488
if len(blob) == 0:

0 commit comments

Comments
 (0)