diff --git a/hivemind_bus_client/client.py b/hivemind_bus_client/client.py index e68e4b5..dbbf6b1 100644 --- a/hivemind_bus_client/client.py +++ b/hivemind_bus_client/client.py @@ -1,7 +1,7 @@ import json import ssl from threading import Event -from typing import Union, Optional, Callable, Literal +from typing import Union, Optional, Callable import pybase64 from Cryptodome.PublicKey import RSA @@ -102,13 +102,10 @@ def __init__(self, key: Optional[str] = None, binarize: bool = True, identity: NodeIdentity = None, internal_bus: Optional[OVOSBusClient] = None, - bin_callbacks: BinaryDataCallbacks = BinaryDataCallbacks(), - json_cipher: Literal[JsonCiphers] = JsonCiphers.JSON_HEX_AES_GCM_128, # TODO - default to b64 at some point - bin_cipher: Literal[BinaryCiphers] = BinaryCiphers.BINARY_AES_GCM_128, # TODO - ChaCha20 if certain hardware detected - ): + bin_callbacks: BinaryDataCallbacks = BinaryDataCallbacks()): self.bin_callbacks = bin_callbacks - self.json_cipher = json_cipher - self.bin_cipher = bin_cipher + self.json_cipher = JsonCiphers.JSON_HEX_AES_GCM_128 # server defaults before it was made configurable + self.bin_cipher = BinaryCiphers.BINARY_AES_GCM_128 # server defaults before it was made configurable self.identity = identity or None self._password = password diff --git a/hivemind_bus_client/encryption.py b/hivemind_bus_client/encryption.py index b1c4ea6..6bad2bb 100644 --- a/hivemind_bus_client/encryption.py +++ b/hivemind_bus_client/encryption.py @@ -6,9 +6,14 @@ import pybase64 from Cryptodome.Cipher import AES, ChaCha20_Poly1305 +from cpuinfo import get_cpu_info from hivemind_bus_client.exceptions import EncryptionKeyError, DecryptionKeyError, InvalidCipher +def cpu_supports_AES() -> bool: + return "aes" in get_cpu_info()["flags"] + + class JsonCiphers(str, enum.Enum): """ Enum representing JSON-based encryption ciphers. diff --git a/hivemind_bus_client/protocol.py b/hivemind_bus_client/protocol.py index 9be4bb8..d60bfdc 100644 --- a/hivemind_bus_client/protocol.py +++ b/hivemind_bus_client/protocol.py @@ -1,6 +1,6 @@ import pybase64 from dataclasses import dataclass -from typing import Optional +from typing import Optional, Tuple from ovos_bus_client import Message as MycroftMessage from ovos_bus_client import MessageBusClient @@ -9,7 +9,7 @@ from ovos_utils.log import LOG from hivemind_bus_client.client import HiveMessageBusClient -from hivemind_bus_client.encryption import JsonCiphers, BinaryCiphers +from hivemind_bus_client.encryption import JsonCiphers, BinaryCiphers, cpu_supports_AES from hivemind_bus_client.identity import NodeIdentity from hivemind_bus_client.message import HiveMessage, HiveMessageType from poorman_handshake import HandShake, PasswordHandShake @@ -119,6 +119,16 @@ def node_id(self): # this is how ovos-core bus refers to this slave's master return self.internal_protocol.node_id + @property + def optimal_ciphers(self) -> Tuple[JsonCiphers, BinaryCiphers]: + if not cpu_supports_AES(): + j = JsonCiphers.JSON_B64_CHACHA20_POLY1305 + b = BinaryCiphers.BINARY_CHACHA20_POLY1305 + else: + j = JsonCiphers.JSON_B64_AES_GCM_128 + b = BinaryCiphers.BINARY_AES_GCM_128 + return j, b + # TODO - handshake handlers # hivemind events def handle_illegal_msg(self, message: HiveMessage): @@ -184,6 +194,9 @@ def handle_handshake(self, message: HiveMessage): # master is performing the handshake if "envelope" in message.payload: envelope = message.payload["envelope"] + self.hm.json_cipher = message.payload.get("json_cipher") or JsonCiphers.JSON_HEX_AES_GCM_128 + self.hm.bin_cipher = message.payload.get("binary_cipher") or BinaryCiphers.BINARY_AES_GCM_128 + LOG.debug(f"Cipher to use: {self.hm.json_cipher} + {self.hm.bin_cipher}") self.receive_handshake(envelope) # master is requesting handshake start diff --git a/hivemind_bus_client/scripts.py b/hivemind_bus_client/scripts.py index e1eabb8..e7c4f0e 100644 --- a/hivemind_bus_client/scripts.py +++ b/hivemind_bus_client/scripts.py @@ -198,8 +198,8 @@ def test_identity(): node.close() -@hmclient_cmds.command(help="recreate the PGP key for inter-node communication", name="reset-pgp") -def reset_pgp_key(): +@hmclient_cmds.command(help="recreate the private RSA key for inter-node communication", name="reset-pgp") +def reset_keys(): identity = NodeIdentity() identity.create_keys() print("PUBKEY:", identity.public_key) diff --git a/requirements.txt b/requirements.txt index b2dac71..cacd61b 100644 --- a/requirements.txt +++ b/requirements.txt @@ -4,4 +4,5 @@ ovos_utils>=0.0.38 bitstring>=4.1.1 cryptography>=41.0.1 pycryptodomex>=3.18.0 -pybase64 \ No newline at end of file +pybase64 +py-cpuinfo \ No newline at end of file