From 8f4b4fa82dac66935a08cbd033214ce3b05f27f3 Mon Sep 17 00:00:00 2001 From: Mark Qvist Date: Tue, 8 Apr 2025 13:54:22 +0200 Subject: [PATCH] Add ability to search for identity by identity hash --- RNS/Destination.py | 2 +- RNS/Identity.py | 41 +++++++++++++++++++++++++++-------------- RNS/Utilities/rnid.py | 23 +++++++++++++---------- 3 files changed, 41 insertions(+), 25 deletions(-) diff --git a/RNS/Destination.py b/RNS/Destination.py index 3983758..b2bbda3 100755 --- a/RNS/Destination.py +++ b/RNS/Destination.py @@ -192,7 +192,7 @@ class Destination: """ :returns: A human-readable representation of the destination including addressable hash and full name. """ - return "<"+self.name+"/"+self.hexhash+">" + return "<"+self.name+":"+self.hexhash+">" def _clean_ratchets(self): if self.ratchets != None: diff --git a/RNS/Identity.py b/RNS/Identity.py index 429d6d4..382241b 100644 --- a/RNS/Identity.py +++ b/RNS/Identity.py @@ -93,29 +93,42 @@ class Identity: @staticmethod - def recall(destination_hash): + def recall(target_hash, from_identity_hash=False): """ - Recall identity for a destination hash. + Recall identity for a destination or identity hash. - :param destination_hash: Destination hash as *bytes*. + :param target_hash: Destination or identity hash as *bytes*. + :param from_identity_hash: Whether to search based on identity hash instead of destination hash as *bool*. :returns: An :ref:`RNS.Identity` instance that can be used to create an outgoing :ref:`RNS.Destination`, or *None* if the destination is unknown. """ - if destination_hash in Identity.known_destinations: - identity_data = Identity.known_destinations[destination_hash] - identity = Identity(create_keys=False) - identity.load_public_key(identity_data[2]) - identity.app_data = identity_data[3] - return identity - else: - for registered_destination in RNS.Transport.destinations: - if destination_hash == registered_destination.hash: + if from_identity_hash: + for destination_hash in Identity.known_destinations: + if target_hash == Identity.truncated_hash(Identity.known_destinations[destination_hash][2]): + identity_data = Identity.known_destinations[destination_hash] identity = Identity(create_keys=False) - identity.load_public_key(registered_destination.identity.get_public_key()) - identity.app_data = None + identity.load_public_key(identity_data[2]) + identity.app_data = identity_data[3] return identity return None + else: + if target_hash in Identity.known_destinations: + identity_data = Identity.known_destinations[target_hash] + identity = Identity(create_keys=False) + identity.load_public_key(identity_data[2]) + identity.app_data = identity_data[3] + return identity + else: + for registered_destination in RNS.Transport.destinations: + if target_hash == registered_destination.hash: + identity = Identity(create_keys=False) + identity.load_public_key(registered_destination.identity.get_public_key()) + identity.app_data = None + return identity + + return None + @staticmethod def recall_app_data(destination_hash): """ diff --git a/RNS/Utilities/rnid.py b/RNS/Utilities/rnid.py index 106a3a9..be7e908 100644 --- a/RNS/Utilities/rnid.py +++ b/RNS/Utilities/rnid.py @@ -63,7 +63,7 @@ def main(): # parser.add_argument("file", nargs="?", default=None, help="input file path", type=str) parser.add_argument("--config", metavar="path", action="store", default=None, help="path to alternative Reticulum config directory", type=str) - parser.add_argument("-i", "--identity", metavar="identity", action="store", default=None, help="hexadecimal Reticulum Destination hash or path to Identity file", type=str) + parser.add_argument("-i", "--identity", metavar="identity", action="store", default=None, help="hexadecimal Reticulum identity or destination hash, or path to Identity file", type=str) parser.add_argument("-g", "--generate", metavar="file", action="store", default=None, help="generate a new Identity") parser.add_argument("-m", "--import", dest="import_str", metavar="identity_data", action="store", default=None, help="import Reticulum identity in hex, base32 or base64 format", type=str) parser.add_argument("-x", "--export", action="store_true", default=None, help="export identity to hex, base32 or base64 format") @@ -205,29 +205,32 @@ def main(): if len(identity_str) == RNS.Reticulum.TRUNCATED_HASHLENGTH//8*2 and not os.path.isfile(identity_str): # Try recalling Identity from hex-encoded hash try: - destination_hash = bytes.fromhex(identity_str) - identity = RNS.Identity.recall(destination_hash) + ident_hash = bytes.fromhex(identity_str) + identity = RNS.Identity.recall(ident_hash) or RNS.Identity.recall(ident_hash, from_identity_hash=True) if identity == None: if not args.request: - RNS.log("Could not recall Identity for "+RNS.prettyhexrep(destination_hash)+".", RNS.LOG_ERROR) + RNS.log("Could not recall Identity for "+RNS.prettyhexrep(ident_hash)+".", RNS.LOG_ERROR) RNS.log("You can query the network for unknown Identities with the -R option.", RNS.LOG_ERROR) exit(5) else: - RNS.Transport.request_path(destination_hash) + RNS.Transport.request_path(ident_hash) def spincheck(): - return RNS.Identity.recall(destination_hash) != None - spin(spincheck, "Requesting unknown Identity for "+RNS.prettyhexrep(destination_hash), args.t) + return RNS.Identity.recall(ident_hash) != None + spin(spincheck, "Requesting unknown Identity for "+RNS.prettyhexrep(ident_hash), args.t) if not spincheck(): RNS.log("Identity request timed out", RNS.LOG_ERROR) exit(6) else: - identity = RNS.Identity.recall(destination_hash) - RNS.log("Received Identity "+str(identity)+" for destination "+RNS.prettyhexrep(destination_hash)+" from the network") + identity = RNS.Identity.recall(ident_hash) + RNS.log("Received Identity "+str(identity)+" for destination "+RNS.prettyhexrep(ident_hash)+" from the network") else: - RNS.log("Recalled Identity "+str(identity)+" for destination "+RNS.prettyhexrep(destination_hash)) + ident_str = str(identity) + hash_str = RNS.prettyhexrep(ident_hash) + if ident_str == hash_str: RNS.log(f"Recalled Identity {ident_str}") + else: RNS.log(f"Recalled Identity {ident_str} for destination {hash_str}") except Exception as e: