Last active
February 25, 2024 22:10
-
-
Save netscylla/b54ab2fb2f4f5b06d3da86de70093889 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python3 | |
########################################## | |
# | |
# //\ e s h t /\ s t / c | |
# | |
# Meshtastic Channel URL Decoder (c) 2024 | |
# Print Key and Channelname from Meshtastic encoded-Channel URL | |
# | |
# License : | |
# http://www.gnu.org/licenses/agpl-3.0.txt | |
# | |
# Author: Andy @ Netscylla | |
# | |
########################################### | |
import argparse | |
import base64 | |
import urllib.parse | |
def parse_url_and_decode(url): | |
# Parse the URL | |
parsed_url = urllib.parse.urlparse(url) | |
# Get the last part of the path | |
element = parsed_url.fragment | |
padding_needed = len(element) % 5 | |
element += "=" * padding_needed | |
# Decode the last part using base64 | |
element = element.replace("-", "+").replace("_", "/") | |
decoded_bytes = base64.b64decode(element.encode("utf-8")) | |
return decoded_bytes | |
def interpret_bytes(decoded_bytes): | |
# Define a lambda function to extract key information | |
extract_key_info = lambda i: ( | |
decoded_bytes[i + 3], | |
decoded_bytes[i + 4 : i + 4 + decoded_bytes[i + 3]], | |
) | |
# Define a lambda function to extract channel name information | |
extract_channel_info = lambda i: decoded_bytes[ | |
i + 1 : i + 2 + decoded_bytes[i + 1] | |
].decode("utf-8") | |
result = "" | |
i = 0 | |
while i < len(decoded_bytes): | |
if decoded_bytes[i] == 0x0A: | |
# Length of key | |
length, key = extract_key_info(i) | |
result += f"Length of key: {length}" | |
result += "\nKey: " | |
result += " ".join([format(byte, "02x") for byte in key]) | |
reencoded_key = base64.b64encode(key).decode("utf-8") | |
result += f"\nRe-encoded key: {reencoded_key}" | |
i += 3 + length | |
elif decoded_bytes[i] == 0x1A: | |
# Channel name follows | |
channel_name = extract_channel_info(i) | |
result += f"\nChannel name: {channel_name}" | |
i += 1 + len(channel_name) | |
elif decoded_bytes[i] == 0x02: | |
# Byte after the end of channel name - Primary | |
result += "\nChannel type: Primary" | |
i += 1 | |
elif decoded_bytes[i] == 0x04: | |
# Byte after the end of channel name - Secondary | |
result += "\nChannel type: Secondary" | |
i += 1 | |
elif decoded_bytes[i : i + 2] == b"\x00\x28": | |
# Two bytes after 00 28 = Uplink enabled | |
result += "\nUplink enabled" | |
i += 2 | |
elif decoded_bytes[i : i + 2] == b"\x01\x30": | |
# Two bytes after 01 30 = Downlink enabled | |
result += "\nDownlink enabled" | |
i += 2 | |
else: | |
# Junk bytes | |
# result += f"\n\nJunk byte: {decoded_bytes[i]}" | |
i += 1 | |
return result | |
def main(): | |
parser = argparse.ArgumentParser(description="Decode and interpret a URL") | |
parser.add_argument("url", help="URL to decode and interpret") | |
args = parser.parse_args() | |
url = args.url | |
print("Found URL: ", url) | |
decoded_bytes = parse_url_and_decode(url) | |
interpretation = interpret_bytes(decoded_bytes) | |
print(interpretation) | |
if __name__ == "__main__": | |
print("//\ e s h t /\ s t / c Channel URL Decoder") | |
print("\nAndy@Netscylla (c) 2024\n\n") | |
main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment