Skip to content
This repository was archived by the owner on Oct 16, 2024. It is now read-only.

Commit 6d82fba

Browse files
committed
Python 3 support WIP
1 parent a08f018 commit 6d82fba

File tree

10 files changed

+103
-92
lines changed

10 files changed

+103
-92
lines changed

btchip/bitcoinTransaction.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
********************************************************************************
1818
"""
1919

20-
from bitcoinVarint import *
20+
from .bitcoinVarint import *
2121
from binascii import hexlify
2222

2323
class bitcoinInput:
@@ -95,7 +95,7 @@ def __init__(self, data=None):
9595
offset = 0
9696
self.version = data[offset:offset + 4]
9797
offset += 4
98-
if (data[offset] == 0) and (data[offset + 1] <> 0):
98+
if (data[offset] == 0) and (data[offset + 1] != 0):
9999
offset += 2
100100
self.witness = True
101101
inputSize = readVarint(data, offset)

btchip/bitcoinVarint.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
********************************************************************************
1818
"""
1919

20-
from btchipException import BTChipException
20+
from .btchipException import BTChipException
2121

2222
def readVarint(buffer, offset):
2323
varintSize = 0

btchip/btchip.py

Lines changed: 41 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -17,13 +17,13 @@
1717
********************************************************************************
1818
"""
1919

20-
from btchipComm import *
21-
from bitcoinTransaction import *
22-
from bitcoinVarint import *
23-
from btchipException import *
24-
from btchipHelpers import *
25-
from btchipKeyRecovery import *
26-
from binascii import hexlify
20+
from .btchipComm import *
21+
from .bitcoinTransaction import *
22+
from .bitcoinVarint import *
23+
from .btchipException import *
24+
from .btchipHelpers import *
25+
from .btchipKeyRecovery import *
26+
from binascii import hexlify, unhexlify
2727

2828
class btchip:
2929
BTCHIP_CLA = 0xe0
@@ -71,9 +71,9 @@ class btchip:
7171
FEATURE_FREE_SIGHASHTYPE = 0x04
7272
FEATURE_NO_2FA_P2SH = 0x08
7373

74-
QWERTY_KEYMAP = bytearray("000000000000000000000000760f00d4ffffffc7000000782c1e3420212224342627252e362d3738271e1f202122232425263333362e37381f0405060708090a0b0c0d0e0f101112131415161718191a1b1c1d2f3130232d350405060708090a0b0c0d0e0f101112131415161718191a1b1c1d2f313035".decode('hex'))
75-
QWERTZ_KEYMAP = bytearray("000000000000000000000000760f00d4ffffffc7000000782c1e3420212224342627252e362d3738271e1f202122232425263333362e37381f0405060708090a0b0c0d0e0f101112131415161718191a1b1d1c2f3130232d350405060708090a0b0c0d0e0f101112131415161718191a1b1d1c2f313035".decode('hex'))
76-
AZERTY_KEYMAP = bytearray("08000000010000200100007820c8ffc3feffff07000000002c38202030341e21222d352e102e3637271e1f202122232425263736362e37101f1405060708090a0b0c0d0e0f331112130415161718191d1b1c1a2f64302f2d351405060708090a0b0c0d0e0f331112130415161718191d1b1c1a2f643035".decode('hex'))
74+
QWERTY_KEYMAP = bytearray(unhexlify("000000000000000000000000760f00d4ffffffc7000000782c1e3420212224342627252e362d3738271e1f202122232425263333362e37381f0405060708090a0b0c0d0e0f101112131415161718191a1b1c1d2f3130232d350405060708090a0b0c0d0e0f101112131415161718191a1b1c1d2f313035"))
75+
QWERTZ_KEYMAP = bytearray(unhexlify("000000000000000000000000760f00d4ffffffc7000000782c1e3420212224342627252e362d3738271e1f202122232425263333362e37381f0405060708090a0b0c0d0e0f101112131415161718191a1b1d1c2f3130232d350405060708090a0b0c0d0e0f101112131415161718191a1b1d1c2f313035"))
76+
AZERTY_KEYMAP = bytearray(unhexlify("08000000010000200100007820c8ffc3feffff07000000002c38202030341e21222d352e102e3637271e1f202122232425263736362e37101f1405060708090a0b0c0d0e0f331112130415161718191d1b1c1a2f64302f2d351405060708090a0b0c0d0e0f331112130415161718191d1b1c1a2f643035"))
7777

7878
def __init__(self, dongle):
7979
self.dongle = dongle
@@ -98,6 +98,8 @@ def setAlternateCoinVersion(self, versionRegular, versionP2SH):
9898
self.dongle.exchange(bytearray(apdu))
9999

100100
def verifyPin(self, pin):
101+
if isinstance(pin, str):
102+
pin = pin.encode('utf-8')
101103
apdu = [ self.BTCHIP_CLA, self.BTCHIP_INS_VERIFY_PIN, 0x00, 0x00, len(pin) ]
102104
apdu.extend(bytearray(pin))
103105
self.dongle.exchange(bytearray(apdu))
@@ -107,7 +109,7 @@ def getVerifyPinRemainingAttempts(self):
107109
apdu.extend(bytearray("0"))
108110
try:
109111
self.dongle.exchange(bytearray(apdu))
110-
except BTChipException, e:
112+
except BTChipException as e:
111113
if ((e.sw & 0xfff0) == 0x63c0):
112114
return e.sw - 0x63c0
113115
raise e
@@ -235,7 +237,7 @@ def startUntrustedTransaction(self, newTransaction, inputIndex, outputList, rede
235237
if ('trustedInput' in passedOutput) and passedOutput['trustedInput']:
236238
params.append(len(passedOutput['value']))
237239
params.extend(passedOutput['value'])
238-
if currentIndex <> inputIndex:
240+
if currentIndex != inputIndex:
239241
script = bytearray()
240242
writeVarint(len(script), params)
241243
if len(script) == 0:
@@ -270,7 +272,7 @@ def finalizeInput(self, outputAddress, amount, fees, changePath, rawTx=None):
270272
try:
271273
fullTx = bitcoinTransaction(bytearray(rawTx))
272274
outputs = fullTx.serializeOutputs()
273-
if len(donglePath) <> 0:
275+
if len(donglePath) != 0:
274276
apdu = [ self.BTCHIP_CLA, self.BTCHIP_INS_HASH_INPUT_FINALIZE_FULL, 0xFF, 0x00 ]
275277
params = []
276278
params.extend(donglePath)
@@ -305,7 +307,7 @@ def finalizeInput(self, outputAddress, amount, fees, changePath, rawTx=None):
305307
apdu.append(len(params))
306308
apdu.extend(params)
307309
response = self.dongle.exchange(bytearray(apdu))
308-
result['confirmationNeeded'] = response[1 + response[0]] <> 0x00
310+
result['confirmationNeeded'] = response[1 + response[0]] != 0x00
309311
result['confirmationType'] = response[1 + response[0]]
310312
if result['confirmationType'] == 0x02:
311313
result['keycardData'] = response[1 + response[0] + 1:]
@@ -329,7 +331,7 @@ def finalizeInput(self, outputAddress, amount, fees, changePath, rawTx=None):
329331
def finalizeInputFull(self, outputData):
330332
result = {}
331333
offset = 0
332-
encryptedOutputData = ""
334+
encryptedOutputData = b""
333335
while (offset < len(outputData)):
334336
blockLength = self.scriptBlockLength
335337
if ((offset + blockLength) < len(outputData)):
@@ -345,11 +347,11 @@ def finalizeInputFull(self, outputData):
345347
encryptedOutputData = encryptedOutputData + response[1 : 1 + response[0]]
346348
offset += dataLength
347349
if len(response) > 1:
348-
result['confirmationNeeded'] = response[1 + response[0]] <> 0x00
350+
result['confirmationNeeded'] = response[1 + response[0]] != 0x00
349351
result['confirmationType'] = response[1 + response[0]]
350352
else:
351353
# Support for old style API before 1.0.2
352-
result['confirmationNeeded'] = response[0] <> 0x00
354+
result['confirmationNeeded'] = response[0] != 0x00
353355
result['confirmationType'] = response[0]
354356
if result['confirmationType'] == 0x02:
355357
result['keycardData'] = response[1 + response[0] + 1:] # legacy
@@ -368,6 +370,8 @@ def finalizeInputFull(self, outputData):
368370
return result
369371

370372
def untrustedHashSign(self, path, pin="", lockTime=0, sighashType=0x01):
373+
if isinstance(pin, str):
374+
pin = pin.encode('utf-8')
371375
donglePath = parse_bip32_path(path)
372376
if self.needKeyCache:
373377
self.resolvePublicKeysInPath(path)
@@ -397,7 +401,7 @@ def signMessagePrepareV1(self, path, message):
397401
apdu.append(len(params))
398402
apdu.extend(params)
399403
response = self.dongle.exchange(bytearray(apdu))
400-
result['confirmationNeeded'] = response[0] <> 0x00
404+
result['confirmationNeeded'] = response[0] != 0x00
401405
result['confirmationType'] = response[0]
402406
if result['confirmationType'] == 0x02:
403407
result['keycardData'] = response[1:]
@@ -433,7 +437,7 @@ def signMessagePrepareV2(self, path, message):
433437
response = self.dongle.exchange(bytearray(apdu))
434438
encryptedOutputData = encryptedOutputData + response[1 : 1 + response[0]]
435439
offset += blockLength
436-
result['confirmationNeeded'] = response[1 + response[0]] <> 0x00
440+
result['confirmationNeeded'] = response[1 + response[0]] != 0x00
437441
result['confirmationType'] = response[1 + response[0]]
438442
if result['confirmationType'] == 0x03:
439443
offset = 1 + response[0] + 1
@@ -453,6 +457,8 @@ def signMessagePrepare(self, path, message):
453457
return result
454458

455459
def signMessageSign(self, pin=""):
460+
if isinstance(pin, str):
461+
pin = pin.encode('utf-8')
456462
apdu = [ self.BTCHIP_CLA, self.BTCHIP_INS_SIGN_MESSAGE, 0x80, 0x00 ]
457463
params = []
458464
if pin is not None:
@@ -466,12 +472,16 @@ def signMessageSign(self, pin=""):
466472
return response
467473

468474
def setup(self, operationModeFlags, featuresFlag, keyVersion, keyVersionP2SH, userPin, wipePin, keymapEncoding, seed=None, developerKey=None):
475+
if isinstance(userPin, str):
476+
userPin = userPin.encode('utf-8')
469477
result = {}
470478
apdu = [ self.BTCHIP_CLA, self.BTCHIP_INS_SETUP, 0x00, 0x00 ]
471479
params = [ operationModeFlags, featuresFlag, keyVersion, keyVersionP2SH ]
472480
params.append(len(userPin))
473481
params.extend(bytearray(userPin))
474482
if wipePin is not None:
483+
if isinstance(wipePin, str):
484+
wipePin = wipePin.encode('utf-8')
475485
params.append(len(wipePin))
476486
params.extend(bytearray(wipePin))
477487
else:
@@ -526,10 +536,10 @@ def getOperationMode(self):
526536
return response[0]
527537

528538
def setOperationMode(self, operationMode):
529-
if operationMode <> btchip.OPERATION_MODE_WALLET \
530-
and operationMode <> btchip.OPERATION_MODE_RELAXED_WALLET \
531-
and operationMode <> btchip.OPERATION_MODE_SERVER \
532-
and operationMode <> btchip.OPERATION_MODE_DEVELOPER:
539+
if operationMode != btchip.OPERATION_MODE_WALLET \
540+
and operationMode != btchip.OPERATION_MODE_RELAXED_WALLET \
541+
and operationMode != btchip.OPERATION_MODE_SERVER \
542+
and operationMode != btchip.OPERATION_MODE_DEVELOPER:
533543
raise BTChipException("Invalid operation mode")
534544
apdu = [ self.BTCHIP_CLA, self.BTCHIP_INS_SET_OPERATION_MODE, 0x00, 0x00, 0x01, operationMode ]
535545
self.dongle.exchange(bytearray(apdu))
@@ -576,9 +586,9 @@ def getPOSEncryptedSeed(self):
576586

577587
def importPrivateKey(self, data, isSeed=False):
578588
apdu = [ self.BTCHIP_CLA, self.BTCHIP_INS_IMPORT_PRIVATE_KEY, (0x02 if isSeed else 0x01), 0x00 ]
579-
apdu.append(len(data))
580-
apdu.extend(data)
581-
return self.dongle.exchange(bytearray(apdu))
589+
apdu.append(len(data))
590+
apdu.extend(data)
591+
return self.dongle.exchange(bytearray(apdu))
582592

583593
def getPublicKey(self, encodedPrivateKey):
584594
result = {}
@@ -587,9 +597,9 @@ def getPublicKey(self, encodedPrivateKey):
587597
apdu.append(len(encodedPrivateKey))
588598
apdu.extend(encodedPrivateKey)
589599
response = self.dongle.exchange(bytearray(apdu))
590-
offset = 1
591-
result['publicKey'] = response[offset + 1 : offset + 1 + response[offset]]
592-
offset = offset + 1 + response[offset]
600+
offset = 1
601+
result['publicKey'] = response[offset + 1 : offset + 1 + response[offset]]
602+
offset = offset + 1 + response[offset]
593603
if response[0] == 0x02:
594604
result['chainCode'] = response[offset : offset + 32]
595605
offset = offset + 32
@@ -678,7 +688,7 @@ def resolvePublicKeysInPath(self, path):
678688
startOffset = offset
679689
break
680690
offset = offset + 1
681-
if startOffset <> 0:
691+
if startOffset != 0:
682692
searchPath = splitPath[0:startOffset - 1]
683693
offset = startOffset - 1
684694
while(offset < len(splitPath)):
@@ -691,5 +701,5 @@ def getJCExtendedFeatures(self):
691701
result = {}
692702
apdu = [ self.BTCHIP_JC_EXT_CLA, self.BTCHIP_INS_EXT_CACHE_GET_FEATURES, 0x00, 0x00, 0x00 ]
693703
response = self.dongle.exchange(bytearray(apdu))
694-
result['proprietaryApi'] = ((response[0] & 0x01) <> 0)
704+
result['proprietaryApi'] = ((response[0] & 0x01) != 0)
695705
return result

btchip/btchipComm.py

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,8 @@
1818
"""
1919

2020
from abc import ABCMeta, abstractmethod
21-
from btchipException import *
22-
from ledgerWrapper import wrapCommandAPDU, unwrapResponseAPDU
21+
from .btchipException import *
22+
from .ledgerWrapper import wrapCommandAPDU, unwrapResponseAPDU
2323
from binascii import hexlify
2424
import hid
2525
import time
@@ -64,15 +64,15 @@ def __init__(self, device, ledger=False, debug=False):
6464

6565
def exchange(self, apdu, timeout=20000):
6666
if self.debug:
67-
print "=> %s" % hexlify(apdu)
67+
print("=> %s" % hexlify(apdu))
6868
if self.ledger:
6969
apdu = wrapCommandAPDU(0x0101, apdu, 64)
7070
padSize = len(apdu) % 64
7171
tmp = apdu
72-
if padSize <> 0:
72+
if padSize != 0:
7373
tmp.extend([0] * (64 - padSize))
7474
offset = 0
75-
while(offset <> len(tmp)):
75+
while(offset != len(tmp)):
7676
data = tmp[offset:offset + 64]
7777
data = bytearray([0]) + data
7878
self.device.write(data)
@@ -114,8 +114,8 @@ def exchange(self, apdu, timeout=20000):
114114
sw = (result[swOffset] << 8) + result[swOffset + 1]
115115
response = result[dataStart : dataLength + dataStart]
116116
if self.debug:
117-
print "<= %s%.2x" % (hexlify(response), sw)
118-
if sw <> 0x9000:
117+
print("<= %s%.2x" % (hexlify(response), sw))
118+
if sw != 0x9000:
119119
raise BTChipException("Invalid status %04x" % sw, sw)
120120
return response
121121

@@ -148,12 +148,12 @@ def __init__(self, device, debug=False):
148148

149149
def exchange(self, apdu, timeout=20000):
150150
if self.debug:
151-
print "=> %s" % hexlify(apdu)
151+
print("=> %s" % hexlify(apdu))
152152
response, sw1, sw2 = self.device.transmit(toBytes(hexlify(apdu)))
153153
sw = (sw1 << 8) | sw2
154154
if self.debug:
155-
print "<= %s%.2x" % (toHexString(response).replace(" ", ""), sw)
156-
if sw <> 0x9000:
155+
print("<= %s%.2x" % (toHexString(response).replace(" ", ""), sw))
156+
if sw != 0x9000:
157157
raise BTChipException("Invalid status %04x" % sw, sw)
158158
return bytearray(response)
159159

0 commit comments

Comments
 (0)