async def wait_qr_scan(): ws_message = await self.websocket.messages.get("s1", 20) connection_data = ws_message[1] self.phone_info = connection_data["phone"] self.session.secret = base64.b64decode( connection_data["secret"].encode()) self.session.server_token = connection_data["serverToken"] self.session.client_token = connection_data["clientToken"] self.session.browser_token = connection_data["browserToken"] self.session.wid = connection_data["wid"] self.session.shared_secret = self.session.private_key.do_exchange( donna25519.PublicKey(self.session.secret[:32])) self.session.shared_secret_expanded = crypto.hkdf_expand( self.session.shared_secret, 80) if not crypto.validate_secrets( self.session.secret, self.session.shared_secret_expanded): raise exceptions.HMACValidationError self.session.keys_encrypted = self.session.shared_secret_expanded[ 64:] + self.session.secret[64:] self.session.keys_decrypted = crypto.aes_decrypt( self.session.shared_secret_expanded[:32], self.session.keys_encrypted) self.session.enc_key = self.session.keys_decrypted[:32] self.session.mac_key = self.session.keys_decrypted[32:64] print(self.session.enc_key, self.session.mac_key)
def _unmarshal_public_key(marshaled): if marshaled[0] != _ECC_CURVE_TYPE: raise ValueError('Unsupported curve type {!02x}'.format(marshaled[0])) if len(marshaled[1:]) != 32: raise ValueError('Expected 32 ECC point bytes, got {}'.format( len(marshaled[1:]))) return donna25519.PublicKey(marshaled[1:])
def gen_secret(device): privateKey = donna25519.PrivateKey() publicKey = privateKey.get_public() privateKeyBase64 = base64.b64encode(privateKey.private).decode('ascii') publicKeyBase64 = base64.b64encode(publicKey.public).decode('ascii') #print("private: " + privateKeyBase64) #print("public: " + publicKeyBase64) coolSwitchPublicKeyBase64 = run_command(device, "/secret?publicKey=" + publicKeyBase64) print("CoolSwitch Public: " + publicKeyBase64) coolSwitchPublicKey = donna25519.PublicKey(base64.b64decode(coolSwitchPublicKeyBase64)) sharedSecret = privateKey.do_exchange(coolSwitchPublicKey) print("sharedSecret: " + base64.b64encode(sharedSecret).decode('ascii'))
def __ajouter_cle_appareil(self, node_id, message): self.__logger.debug("Messages : %s" % str(message)) uuid_senseur = message['uuid_senseur'] uuid_senseur_bytes = binascii.unhexlify(uuid_senseur.encode('utf-8')) cle = message['cle_publique'] crc32_recu = message['crc32'] self.__logger.debug("Recu cle publique appareil : %s" % binascii.hexlify(cle)) # Valider la cle avec le CRC32 calcul_crc32 = crc32(uuid_senseur_bytes + cle) & 0xffffffff crc32_recu_int = unpack('I', crc32_recu)[0] self.__logger.debug("CRC32 cle calcule %s, recu %s" % (hex(calcul_crc32), hex(crc32_recu_int))) if calcul_crc32 != crc32_recu_int: raise Exception("CRC32 cle different de celui recu") # Conserver la cle publique de l'appareil pour reference future self.__reserve_dhcp.conserver_cle(uuid_senseur_bytes, cle) # Generer nouvelle cle ed25519 pour identifier cle partagee appareil_side = donna25519.PublicKey(cle) # serveur_side = donna25519.PrivateKey() shared_key = self.__cle_privee.do_exchange(appareil_side) # self.__logger.debug("Cle shared %s : %s" % (uuid_senseur, binascii.hexlify(shared_key))) # Transmettre serveur side public serveur_side_public = bytes(self.__cle_privee.get_public().public) self.__logger.debug("Cle publique serveur : %s" % binascii.hexlify(serveur_side_public)) # self.__logger.debug("Cle privee serveur : %s" % binascii.hexlify(bytes(serveur_side))) paquets = [ ProtocoleVersion9.PaquetReponseCleServeur1(node_id, serveur_side_public), ProtocoleVersion9.PaquetReponseCleServeur2(node_id, serveur_side_public), ] self.__logger.debug( "Transmission paquet cle publique vers reponse nodeId:%d" % node_id) self.transmettre_paquets(paquets, node_id) info_appareil = self.__information_appareils_par_uuid.get(uuid_senseur) if info_appareil is None: info_appareil = {'uuid': uuid_senseur} self.__information_appareils_par_uuid[uuid_senseur] = info_appareil info_appareil['cle_partagee'] = shared_key info_appareil['node_id'] = node_id
def get_infoappareil_par_nodeid(self, node_id: int): for uuid_appareil, info_app in self.__information_appareils_par_uuid.items( ): if info_app['node_id'] == node_id: self.__logger.debug( "get_infoappareil_par_nodeid: Info app : %s" % str(info_app)) # info_complete['uuid'] = uuid_appareil return info_app # On n'a pas l'information par uuid, tenter de charger avec info # connue dans le DHCP info_appareil = self.__reserve_dhcp.get_info_par_nodeid(node_id) if info_appareil is not None: self.__logger.debug("Recharger appareil connu : %s" % str(info_appareil)) # On a trouve, charger la base de l'information info_mappee = { 'uuid': info_appareil['uuid'], 'node_id': info_appareil['node_id'] } # Recalculer la cle partagee try: cle_publique = binascii.unhexlify( info_appareil.get('cle_publique')) appareil_side = donna25519.PublicKey(cle_publique) shared_key = self.__cle_privee.do_exchange(appareil_side) info_mappee['cle_publique'] = cle_publique info_mappee['cle_partagee'] = shared_key except TypeError: self.__logger.exception("Erreur chargement cle publique") # Note : la cle (uuid) est en format hex str, pas en bytes self.__information_appareils_par_uuid[ info_appareil['uuid']] = info_mappee return info_appareil return None
def curve25519(pk, sk): assert len(pk) == PUB_KEY_LEN assert len(sk) == SEC_KEY_LEN private = donna25519.PrivateKey.load(sk) public = donna25519.PublicKey(pk) return private.do_exchange(public)
def load_pubkey(): with open(pub_key_file, 'rb') as fd: return donna25519.PublicKey(fd.read()).public