diff --git a/hivemind_bus_client/client.py b/hivemind_bus_client/client.py index 92d459a..0ecfcb4 100644 --- a/hivemind_bus_client/client.py +++ b/hivemind_bus_client/client.py @@ -1,12 +1,14 @@ -import pybase64 import json import ssl from threading import Event from typing import Union, Optional, Callable -import pgpy +import pybase64 +from Cryptodome.PublicKey import RSA from ovos_bus_client import Message as MycroftMessage, MessageBusClient as OVOSBusClient from ovos_bus_client.session import Session +from ovos_utils.fakebus import FakeBus +from ovos_utils.log import LOG from pyee import EventEmitter from websocket import ABNF from websocket import WebSocketApp, WebSocketConnectionClosedException @@ -17,8 +19,7 @@ from hivemind_bus_client.serialization import get_bitstring, decode_bitstring from hivemind_bus_client.util import serialize_message, \ encrypt_as_json, decrypt_from_json, encrypt_bin, decrypt_bin -from ovos_utils.log import LOG -from ovos_utils.fakebus import FakeBus +from poorman_handshake.asymmetric.utils import encrypt_RSA, load_RSA_key, sign_RSA class BinaryDataCallbacks: @@ -492,24 +493,15 @@ def wait_for_payload_response(self, message: Union[MycroftMessage, HiveMessage], self.emit(message) return waiter.wait(timeout) - # targeted messages for nodes, assymetric encryption + # targeted messages for nodes, asymmetric encryption def emit_intercom(self, message: Union[MycroftMessage, HiveMessage], - pubkey: Union[str, pgpy.PGPKey]): - - if isinstance(pubkey, str): - pubkey, _ = pgpy.PGPKey.from_blob(pubkey) - assert isinstance(pubkey, pgpy.PGPKey) - - txt = message.serialize() + pubkey: Union[str, bytes, RSA.RsaKey]): - text_message = pgpy.PGPMessage.new(txt) - encrypted_message = pubkey.encrypt(text_message) + encrypted_message = encrypt_RSA(pubkey, message.serialize()) # sign message - with open(self.identity.private_key, "r") as f: - private_key = pgpy.PGPKey.from_blob(f.read()) - # the bitwise OR operator '|' is used to add a signature to a PGPMessage. - encrypted_message |= private_key.sign(encrypted_message, - intended_recipients=[pubkey]) + private_key = load_RSA_key(self.identity.private_key) + signature = sign_RSA(private_key, encrypted_message) - self.emit(HiveMessage(HiveMessageType.INTERCOM, payload={"ciphertext": str(encrypted_message)})) + self.emit(HiveMessage(HiveMessageType.INTERCOM, payload={"ciphertext": pybase64.b64encode(encrypted_message), + "signature": pybase64.b64encode(signature)})) diff --git a/hivemind_bus_client/protocol.py b/hivemind_bus_client/protocol.py index ef94a25..d071728 100644 --- a/hivemind_bus_client/protocol.py +++ b/hivemind_bus_client/protocol.py @@ -1,17 +1,18 @@ +import pybase64 from dataclasses import dataclass +from typing import Optional -import pgpy from ovos_bus_client import Message as MycroftMessage from ovos_bus_client import MessageBusClient from ovos_bus_client.message import Message from ovos_bus_client.session import Session, SessionManager from ovos_utils.log import LOG -from poorman_handshake import HandShake, PasswordHandShake -from typing import Optional from hivemind_bus_client.client import HiveMessageBusClient from hivemind_bus_client.identity import NodeIdentity from hivemind_bus_client.message import HiveMessage, HiveMessageType +from poorman_handshake import HandShake, PasswordHandShake +from poorman_handshake.asymmetric.utils import decrypt_RSA, load_RSA_key @dataclass() @@ -274,12 +275,17 @@ def handle_intercom(self, message: HiveMessage): pload = message.payload if isinstance(pload, dict) and "ciphertext" in pload: try: - message_from_blob = pgpy.PGPMessage.from_blob(pload["ciphertext"]) + ciphertext = pybase64.b64decode(pload["ciphertext"]) + signature = pybase64.b64decode(pload["signature"]) + + # TODO allow verifying, but we need to store known pubkeys before this is possible + # pubkey = "" + # verified: bool = verify_RSA(pubkey, ciphertext, signature) + + private_key = load_RSA_key(self.identity.private_key) - with open(self.identity.private_key, "r") as f: - private_key = pgpy.PGPKey.from_blob(f.read()) + decrypted = decrypt_RSA(private_key, ciphertext).decode("utf8") - decrypted: str = private_key.decrypt(message_from_blob) message._payload = HiveMessage.deserialize(decrypted) except: if k: