Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: INTERCOM messages RSA #44

Merged
merged 2 commits into from
Jan 1, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 12 additions & 20 deletions hivemind_bus_client/client.py
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -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:
Expand Down Expand Up @@ -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)}))
20 changes: 13 additions & 7 deletions hivemind_bus_client/protocol.py
Original file line number Diff line number Diff line change
@@ -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()
Expand Down Expand Up @@ -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:
Expand Down
Loading