From eed37e82d2d610149bbe87a6428b02dcbd8538ab Mon Sep 17 00:00:00 2001 From: BTChip Date: Sun, 14 Jun 2015 11:25:26 +0200 Subject: [PATCH] Support Ledger 2FA Security Card and prepare for new encoding format --- plugins/btchipwallet.py | 35 +++++++++++++++++++++++++++++------ 1 file changed, 29 insertions(+), 6 deletions(-) diff --git a/plugins/btchipwallet.py b/plugins/btchipwallet.py index 22b2d6ce..bd4b72bf 100644 --- a/plugins/btchipwallet.py +++ b/plugins/btchipwallet.py @@ -28,7 +28,7 @@ try: from btchip.btchipFirmwareWizard import checkFirmware, updateFirmware from btchip.btchipException import BTChipException BTCHIP = True - BTCHIP_DEBUG = False + BTCHIP_DEBUG = False except ImportError: BTCHIP = False @@ -353,6 +353,7 @@ class BTChipWallet(BIP32_HD_Wallet): outputAmount = None use2FA = False pin = "" + rawTx = tx.serialize() # Fetch inputs of the transaction to sign for txinput in tx.inputs: if ('is_coinbase' in txinput and txinput['is_coinbase']): @@ -396,17 +397,39 @@ class BTChipWallet(BIP32_HD_Wallet): self.get_client().startUntrustedTransaction(firstTransaction, inputIndex, trustedInputs, redeemScripts[inputIndex]) outputData = self.get_client().finalizeInput(output, format_satoshis(outputAmount), - format_satoshis(self.get_tx_fee(tx)), changePath) + format_satoshis(self.get_tx_fee(tx)), changePath, bytearray(rawTx.decode('hex'))) if firstTransaction: transactionOutput = outputData['outputData'] if outputData['confirmationNeeded']: use2FA = True # TODO : handle different confirmation types. For the time being only supports keyboard 2FA waitDialog.emit(SIGNAL('dongle_done')) - confirmed, p, pin = self.password_dialog() - if not confirmed: - raise Exception('Aborted by user') - pin = pin.encode() + if 'keycardData' in outputData: + pin2 = "" + for keycardIndex in range(len(outputData['keycardData'])): + msg = "Do not enter your device PIN here !\r\n\r\n" + \ + "Your BTChip wants to talk to you and tell you a unique second factor code.\r\n" + \ + "For this to work, please match the character between stars of the output address using your security card\r\n\r\n" + \ + "Output address : " + for index in range(len(output)): + if index == outputData['keycardData'][keycardIndex]: + msg = msg + "*" + output[index] + "*" + else: + msg = msg + output[index] + msg = msg + "\r\n" + confirmed, p, pin = self.password_dialog(msg) + if not confirmed: + raise Exception('Aborted by user') + try: + pin2 = pin2 + chr(int(pin[0], 16)) + except: + raise Exception('Invalid PIN character') + pin = pin2 + else: + confirmed, p, pin = self.password_dialog() + if not confirmed: + raise Exception('Aborted by user') + pin = pin.encode() self.client.bad = True self.device_checked = False self.get_client(True)