def __init__(self, plugin, handler): if not LIBS_AVAILABLE: self.print_error("** No libraries available") return self.print_error("__init__()")#debugSatochip self.device = plugin.device self.handler = handler #self.parser= CardDataParser() #self.cc= CardConnector(self, _logger.getEffectiveLevel()) self.cc= CardConnector(self) if is_verbose: logger.setLevel(logging.DEBUG) else: logger.setLevel(logging.INFO)
class SatochipClient(PrintError): def __init__(self, plugin, handler): if not LIBS_AVAILABLE: self.print_error("** No libraries available") return self.print_error("__init__()")#debugSatochip self.device = plugin.device self.handler = handler #self.parser= CardDataParser() #self.cc= CardConnector(self, _logger.getEffectiveLevel()) self.cc= CardConnector(self) if is_verbose: logger.setLevel(logging.DEBUG) else: logger.setLevel(logging.INFO) def __repr__(self): return '<SatochipClient TODO>' def is_pairable(self): return LIBS_AVAILABLE def close(self): self.print_error("close()")#debugSatochip self.cc.card_disconnect() self.cc.cardmonitor.deleteObserver(self.cc.cardobserver) def timeout(self, cutoff): pass def is_initialized(self): return LIBS_AVAILABLE def label(self): # TODO - currently empty #debugSatochip return "" def has_usable_connection_with_device(self): self.print_error(f"has_usable_connection_with_device()")#debugSatochip try: (response, sw1, sw2)=self.cc.card_select() #TODO: something else? except SWException as e: self.print_error(e) return False return True def get_xpub(self, bip32_path, xtype): assert xtype in SatochipPlugin.SUPPORTED_XTYPES try: hex_authentikey = self.handler.win.wallet.storage.get('authentikey') self.print_error("get_xpub(): self.handler.win.wallet.storage.authentikey:", hex_authentikey)#debugSatochip if hex_authentikey is not None: self.cc.parser.authentikey_from_storage= ECPubkey(bytes.fromhex(hex_authentikey)) except Exception as e: #attributeError? self.print_error("get_xpub(): exception when getting authentikey from self.handler.win.wallet.storage:", str(e))#debugSatochip try: # needs PIN self.cc.card_verify_PIN() # bip32_path is of the form 44'/0'/1' self.print_error("[get_xpub(): bip32_path = ", bip32_path)#debugSatochip (depth, bytepath)= bip32path2bytes(bip32_path) (childkey, childchaincode)= self.cc.card_bip32_get_extendedkey(bytepath) if depth == 0: #masterkey fingerprint= bytes([0,0,0,0]) child_number= bytes([0,0,0,0]) else: #get parent info (parentkey, parentchaincode)= self.cc.card_bip32_get_extendedkey(bytepath[0:-4]) fingerprint= hash_160(parentkey.get_public_key_bytes(compressed=True))[0:4] child_number= bytepath[-4:] #xpub= serialize_xpub('standard', childchaincode, childkey.get_public_key_bytes(compressed=True), depth, fingerprint, child_number) xpub= serialize_xpub(xtype, childchaincode, childkey.get_public_key_bytes(compressed=True), depth, fingerprint, child_number) self.print_error("SatochipClient: get_xpub(): xpub=", xpub)#debugSatochip return xpub # return BIP32Node(xtype=xtype, # eckey=childkey, # chaincode=childchaincode, # depth=depth, # fingerprint=fingerprint, # child_number=child_number).to_xpub() except Exception as e: self.print_error(repr(e)) return None def ping_check(self): #check connection is working try: print('ping_check')#debug #atr= self.cc.card_get_ATR() except Exception as e: self.print_error(repr(e)) raise RuntimeError("Communication issue with Satochip") def request(self, request_type, *args): self.print_error('client request: '+ str(request_type)) if self.handler is not None: if (request_type=='update_status'): reply = self.handler.update_status(*args) return reply elif (request_type=='show_error'): reply = self.handler.show_error(*args) return reply elif (request_type=='show_message'): reply = self.handler.show_message(*args) return reply else: reply = self.handler.show_error('Unknown request: '+str(request_type)) return reply else: self.print_error("self.handler is None! ") return None # try: # method_to_call = getattr(self.handler, request_type) # print('Type of method_to_call: '+ str(type(method_to_call))) # print('method_to_call: '+ str(method_to_call)) # reply = method_to_call(*args) # return reply # except Exception as e: # _logger.exception(f"Exception: {str(e)}") # raise RuntimeError("GUI exception") def PIN_dialog(self, msg): while True: password = self.handler.get_passphrase(msg, False) if password is None: return False, None if len(password) < 4: msg = _("PIN must have at least 4 characters.") + \ "\n\n" + _("Enter PIN:") elif len(password) > 64: msg = _("PIN must have less than 64 characters.") + \ "\n\n" + _("Enter PIN:") else: password = password.encode('utf8') return True, password def PIN_setup_dialog(self, msg, msg_confirm, msg_error): while(True): (is_PIN, pin)= self.PIN_dialog(msg) if not is_PIN: #return (False, None) raise RuntimeError(('A PIN code is required to initialize the Satochip!')) (is_PIN, pin_confirm)= self.PIN_dialog(msg_confirm) if not is_PIN: #return (False, None) raise RuntimeError(('A PIN confirmation is required to initialize the Satochip!')) if (pin != pin_confirm): self.request('show_error', msg_error) else: return (is_PIN, pin) def PIN_change_dialog(self, msg_oldpin, msg_newpin, msg_confirm, msg_error, msg_cancel): #old pin (is_PIN, oldpin)= self.PIN_dialog(msg_oldpin) if (not is_PIN): self.request('show_message', msg_cancel) return (False, None, None) # new pin while (True): (is_PIN, newpin)= self.PIN_dialog(msg_newpin) if (not is_PIN): self.request('show_message', msg_cancel) return (False, None, None) (is_PIN, pin_confirm)= self.PIN_dialog(msg_confirm) if (not is_PIN): self.request('show_message', msg_cancel) return (False, None, None) if (newpin != pin_confirm): self.request('show_error', msg_error) else: return (True, oldpin, newpin)
# print("Import exception for eth_keys") # print(repr(e)) if (len(sys.argv)>=2) and (sys.argv[1]in ['-v', '--verbose']): logging.basicConfig(level=logging.DEBUG, format='%(levelname)s [%(module)s] %(funcName)s | %(message)s') else: logging.basicConfig(level=logging.INFO, format='%(levelname)s [%(module)s] %(funcName)s | %(message)s') logger = logging.getLogger(__name__) #logger.setLevel(logging.DEBUG) logger.warning("loglevel: "+ str(logger.getEffectiveLevel()) ) #handler= HandlerTxt() handler= HandlerSimpleGUI(logger.getEffectiveLevel()) client= Client(None, handler, logger.getEffectiveLevel()) cc = CardConnector(client, logger.getEffectiveLevel()) status= None wallets = {} EXIT_SUCCESS=0 EXIT_FAILURE=1 # TODO list: # authentikey image # Daemon mode # logging & versioning # DONE: Support 2FA # DONE Check origin and host (+ whitelist?) # DONE GUI # DONE Satochip initialization