# MeshCore Decoder - Python Port
A Python library for decoding MeshCore mesh networking packets with full cryptographic support. Complete Python implementation of the [MeshCore Packet Decoder](https://github.com/michaelhart/meshcore-decoder) by [Michael Hart](https://github.com/michaelhart).
## Features
- **Packet Decoding**: Decode MeshCore packets
- **Built-in Decryption**: Decrypt GroupText, TextMessage, and other encrypted payloads
- **Developer Friendly**: Python-first with full type hints and data classes
## Installation
### Install to a single project
```bash
pip install -r requirements.txt
```
### Install via pip (if published)
```bash
pip install meshcore-decoder
```
## Requirements
- `pycryptodome>=3.19.0` - Core cryptography (AES, HMAC)
- `cryptography>=41.0.0` - Ed25519 signature support
- `click>=8.1.0` - CLI improvements
## Quick Start
```python
from src.decoder.packet_decoder import MeshCorePacketDecoder
from src.types.enums import PayloadType
from src.utils.enum_names import get_route_type_name, get_payload_type_name, get_device_role_name
import json
# Decode a MeshCore packet
hex_data = '11007E7662676F7F0850A8A355BAAFBFC1EB7B4174C340442D7D7161C9474A2C94006CE7CF682E58408DD8FCC51906ECA98EBF94A037886BDADE7ECD09FD92B839491DF3809C9454F5286D1D3370AC31A34593D569E9A042A3B41FD331DFFB7E18599CE1E60992A076D50238C5B8F85757375354522F50756765744D65736820436F75676172'
packet = MeshCorePacketDecoder.decode(hex_data)
print(f"Route Type: {get_route_type_name(packet.route_type)}")
print(f"Payload Type: {get_payload_type_name(packet.payload_type)}")
print(f"Message Hash: {packet.message_hash}")
if packet.payload_type == PayloadType.Advert and packet.payload.get('decoded'):
advert = packet.payload['decoded']
print(f"Device Name: {advert.app_data.get('name')}")
print(f"Device Role: {get_device_role_name(advert.app_data.get('device_role'))}")
if advert.app_data.get('location'):
location = advert.app_data['location']
print(f"Location: {location['latitude']}, {location['longitude']}")
```
## Full Packet Structure Example
Here's what a complete decoded packet looks like:
```python
from src.decoder.packet_decoder import MeshCorePacketDecoder
import json
hex_data = '11007E7662676F7F0850A8A355BAAFBFC1EB7B4174C340442D7D7161C9474A2C94006CE7CF682E58408DD8FCC51906ECA98EBF94A037886BDADE7ECD09FD92B839491DF3809C9454F5286D1D3370AC31A34593D569E9A042A3B41FD331DFFB7E18599CE1E60992A076D50238C5B8F85757375354522F50756765744D65736820436F75676172'
packet = MeshCorePacketDecoder.decode(hex_data)
packet_dict = packet.to_dict()
print(json.dumps(packet_dict, indent=2, default=str))
```
**Output:**
```json
{
"messageHash": "F9C060FE",
"routeType": 1,
"payloadType": 4,
"payloadVersion": 0,
"pathLength": 0,
"path": null,
"payload": {
"raw": "7E7662676F7F0850A8A355BAAFBFC1EB7B4174C340442D7D7161C9474A2C94006CE7CF682E58408DD8FCC51906ECA98EBF94A037886BDADE7ECD09FD92B839491DF3809C9454F5286D1D3370AC31A34593D569E9A042A3B41FD331DFFB7E18599CE1E60992A076D50238C5B8F85757375354522F50756765744D65736820436F75676172",
"decoded": {
"type": 4,
"version": 0,
"isValid": true,
"publicKey": "7E7662676F7F0850A8A355BAAFBFC1EB7B4174C340442D7D7161C9474A2C9400",
"timestamp": 1758455660,
"signature": "2E58408DD8FCC51906ECA98EBF94A037886BDADE7ECD09FD92B839491DF3809C9454F5286D1D3370AC31A34593D569E9A042A3B41FD331DFFB7E18599CE1E609",
"appData": {
"flags": 146,
"deviceRole": 2,
"hasLocation": true,
"hasName": true,
"location": {
"latitude": 47.543968,
"longitude": -122.108616
},
"name": "WW7STR/PugetMesh Cougar"
}
}
},
"totalBytes": 134,
"isValid": true
}
```
## Decryption Support
Simply provide your channel secret keys and the library handles everything else:
```python
from src.decoder.packet_decoder import MeshCorePacketDecoder
from src.crypto.key_manager import MeshCoreKeyStore
from src.types.crypto import DecryptionOptions
from src.types.enums import PayloadType
# Create a key store with channel secret keys
key_store = MeshCoreKeyStore({
'channel_secrets': [
'8b3387e9c5cdea6ac9e5edbaa115cd72', # Public channel (channel hash 11)
'ff2b7d74e8d20f71505bda9ea8d59a1c', # A different channel's secret
]
})
group_text_hex_data = '...' # Your encrypted GroupText packet hex
# Decode encrypted GroupText message
options = DecryptionOptions(key_store=key_store)
encrypted_packet = MeshCorePacketDecoder.decode(group_text_hex_data, options)
if encrypted_packet.payload_type == PayloadType.GroupText and encrypted_packet.payload.get('decoded'):
group_text = encrypted_packet.payload['decoded']
if group_text.decrypted:
print(f"Sender: {group_text.decrypted.get('sender')}")
print(f"Message: {group_text.decrypted.get('message')}")
print(f"Timestamp: {group_text.decrypted.get('timestamp')}")
else:
print('Message encrypted (no key available)')
```
The library automatically:
- Calculates channel hashes from your secret keys using SHA256
- Handles hash collisions (multiple keys with same first byte) by trying all matching keys
- Verifies message authenticity using HMAC-SHA256
- Decrypts using AES-128 ECB
### With Signature Verification
```python
import asyncio
from src.decoder.packet_decoder import MeshCorePacketDecoder
# Async verification for Ed25519 signatures
async def verify_packet():
packet = await MeshCorePacketDecoder.decode_with_verification(hex_data)
if packet.payload.get('decoded'):
advert = packet.payload['decoded']
if hasattr(advert, 'signature_valid'):
print(f"Signature Valid: {advert.signature_valid}")
asyncio.run(verify_packet())
```
## Packet Structure Analysis
For detailed packet analysis and debugging, use `analyze_structure()` to get byte-level breakdowns:
```python
from src.decoder.packet_decoder import MeshCorePacketDecoder
print('=== Packet Breakdown ===')
hex_data = '11007E7662676F7F0850A8A355BAAFBFC1EB7B4174C340442D7D7161C9474A2C94006CE7CF682E58408DD8FCC51906ECA98EBF94A037886BDADE7ECD09FD92B839491DF3809C9454F5286D1D3370AC31A34593D569E9A042A3B41FD331DFFB7E18599CE1E60992A076D50238C5B8F85757375354522F50756765744D65736820436F75676172'
print(f"Packet length: {len(hex_data)}")
print(f"Expected bytes: {len(hex_data) / 2}")
structure = MeshCorePacketDecoder.analyze_structure(hex_data)
print('\nMain segments:')
for i, seg in enumerate(structure.segments):
print(f"{i+1}. {seg.name} (bytes {seg.start_byte}-{seg.end_byte}): {seg.value}")
print('\nPayload segments:')
for i, seg in enumerate(structure.payload['segments']):
print(f"{i+1}. {seg.name} (bytes {seg.start_byte}-{seg.end_byte}): {seg.value}")
print(f" Description: {seg.description}")
```
**Output:**
```
=== Packet Breakdown ===
Packet length: 268
Expected bytes: 134
Main segments:
1. Header (bytes 0-0): 0x11
2. Path Length (bytes 1-1): 0x00
3. Payload (bytes 2-133): 7E7662676F7F0850A8A355BAAFBFC1EB7B4174C340442D7D7161C9474A2C94006CE7CF682E58408DD8FCC51906ECA98EBF94A037886BDADE7ECD09FD92B839491DF3809C9454F5286D1D3370AC31A34593D569E9A042A3B41FD331DFFB7E18599CE1E60992A076D50238C5B8F85757375354522F50756765744D65736820436F75676172
Payload segments:
1. Public Key (bytes 0-31): 7E7662676F7F0850A8A355BAAFBFC1EB7B4174C340442D7D7161C9474A2C9400
Description: Ed25519 public key
2. Timestamp (bytes 32-35): 6CE7CF68
Description: 1758455660 (2025-09-21T11:54:20Z)
3. Signature (bytes 36-99): 2E58408DD8FCC51906ECA98EBF94A037886BDADE7ECD09FD92B839491DF3809C9454F5286D1D3370AC31A34593D569E9A042A3B41FD331DFFB7E18599CE1E609
Description: Ed25519 signature
4. App Flags (bytes 100-100): 92
Description: Binary: 10010010 | Bits 0-3 (Role): Room server | Bit 4 (Location): Yes | Bit 5 (Feature1): No | Bit 6 (Feature2): No | Bit 7 (Name): Yes
5. Latitude (bytes 101-104): A076D502
Description: 47.543968° (47.543968)
6. Longitude (bytes 105-108): 38C5B8F8
Description: -122.108616° (-122.108616)
7. Node Name (bytes 109-131): 5757375354522F50756765744D65736820436F75676172
Description: Node name: "WW7STR/PugetMesh Cougar"
```
The `analyze_structure()` method provides:
- **Header breakdown** with bit-level field analysis
- **Byte-accurate segments** with start/end positions
- **Payload field parsing** for all supported packet types
- **Human-readable descriptions** for each field
## Ed25519 Key Derivation
The library includes MeshCore-compatible Ed25519 key derivation using the exact orlp/ed25519 algorithm:
```python
from src.crypto.ed25519_verifier import derive_public_key, validate_key_pair
# Derive public key from MeshCore private key (64-byte format)
private_key = '18469d6140447f77de13cd8d761e605431f52269fbff43b0925752ed9e6745435dc6a86d2568af8b70d3365db3f88234760c8ecc645ce469829bc45b65f1d5d5'
public_key = derive_public_key(private_key)
print('Derived Public Key:', public_key)
# Output: 4852B69364572B52EFA1B6BB3E6D0ABED4F389A1CBFBB60A9BBA2CCE649CAF0E
# Validate a key pair
is_valid = validate_key_pair(private_key, public_key)
print('Key pair valid:', is_valid) # True
```
## Command Line Interface
For quick analysis from the terminal, use the CLI:
```bash
# Analyze a packet
python cli.py decode 11007E7662676F7F0850A8A355BAAFBFC1EB7B4174C340442D7D7161C9474A2C94006CE7CF682E58408DD8FCC51906ECA98EBF94A037886BDADE7ECD09FD92B839491DF3809C9454F5286D1D3370AC31A34593D569E9A042A3B41FD331DFFB7E18599CE1E60992A076D50238C5B8F85757375354522F50756765744D65736820436F75676172
# With decryption (provide channel secrets)
python cli.py decode 150011C3C1354D619BAE9590E4D177DB7EEAF982F5BDCF78005D75157D9535FA90178F785D --key 8b3387e9c5cdea6ac9e5edbaa115cd72
# Show detailed structure analysis
python cli.py decode --structure 11007E7662676F7F0850A8A355BAAFBFC1EB7B4174C340442D7D7161C9474A2C94006CE7CF682E58408DD8FCC51906ECA98EBF94A037886BDADE7ECD09FD92B839491DF3809C9454F5286D1D3370AC31A34593D569E9A042A3B41FD331DFFB7E18599CE1E60992A076D50238C5B8F85757375354522F50756765744D65736820436F75676172
# JSON output
python cli.py decode --json 11007E7662676F7F0850A8A355BAAFBFC1EB7B4174C340442D7D7161C9474A2C94006CE7CF682E58408DD8FCC51906ECA98EBF94A037886BDADE7ECD09FD92B839491DF3809C9454F5286D1D3370AC31A34593D569E9A042A3B41FD331DFFB7E18599CE1E60992A076D50238C5B8F85757375354522F50756765744D65736820436F75676172
# Derive public key from MeshCore private key
python cli.py derive-key 18469d6140447f77de13cd8d761e605431f52269fbff43b0925752ed9e6745435dc6a86d2568af8b70d3365db3f88234760c8ecc645ce469829bc45b65f1d5d5
# Validate key pair
python cli.py validate-key 18469d6140447f77de13cd8d761e605431f52269fbff43b0925752ed9e6745435dc6a86d2568af8b70d3365db3f88234760c8ecc645ce469829bc45b65f1d5d5 4852b69364572b52efa1b6bb3e6d0abed4f389a1cbfbb60a9bba2cce649caf0e
```
## License
MIT License
Copyright (c) 2025 Michael Hart <michaelhart@michaelhart.me> (https://github.com/michaelhart)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
Raw data
{
"_id": null,
"home_page": "https://github.com/chrisdavis2110/meshcore-decoder-py",
"name": "meshcore-decoder",
"maintainer": null,
"docs_url": null,
"requires_python": ">=3.8",
"maintainer_email": null,
"keywords": "meshcore, decoder, packet, mesh, networking",
"author": "Chris Davis",
"author_email": "Chris Davis <chrisdavis2110@gmail.com>, Michael Hart <michaelhart@michaelhart.me>",
"download_url": "https://files.pythonhosted.org/packages/c4/ec/e797bb37a41fd1b05c5128c9f795574201d789238d7bdc52e83f17c1bb0e/meshcore_decoder-0.1.0.tar.gz",
"platform": null,
"description": "# MeshCore Decoder - Python Port\n\nA Python library for decoding MeshCore mesh networking packets with full cryptographic support. Complete Python implementation of the [MeshCore Packet Decoder](https://github.com/michaelhart/meshcore-decoder) by [Michael Hart](https://github.com/michaelhart).\n\n## Features\n\n- **Packet Decoding**: Decode MeshCore packets\n- **Built-in Decryption**: Decrypt GroupText, TextMessage, and other encrypted payloads\n- **Developer Friendly**: Python-first with full type hints and data classes\n\n## Installation\n\n### Install to a single project\n\n```bash\npip install -r requirements.txt\n```\n\n### Install via pip (if published)\n\n```bash\npip install meshcore-decoder\n```\n\n## Requirements\n\n- `pycryptodome>=3.19.0` - Core cryptography (AES, HMAC)\n- `cryptography>=41.0.0` - Ed25519 signature support\n- `click>=8.1.0` - CLI improvements\n\n## Quick Start\n\n```python\nfrom src.decoder.packet_decoder import MeshCorePacketDecoder\nfrom src.types.enums import PayloadType\nfrom src.utils.enum_names import get_route_type_name, get_payload_type_name, get_device_role_name\nimport json\n\n# Decode a MeshCore packet\nhex_data = '11007E7662676F7F0850A8A355BAAFBFC1EB7B4174C340442D7D7161C9474A2C94006CE7CF682E58408DD8FCC51906ECA98EBF94A037886BDADE7ECD09FD92B839491DF3809C9454F5286D1D3370AC31A34593D569E9A042A3B41FD331DFFB7E18599CE1E60992A076D50238C5B8F85757375354522F50756765744D65736820436F75676172'\npacket = MeshCorePacketDecoder.decode(hex_data)\n\nprint(f\"Route Type: {get_route_type_name(packet.route_type)}\")\nprint(f\"Payload Type: {get_payload_type_name(packet.payload_type)}\")\nprint(f\"Message Hash: {packet.message_hash}\")\n\nif packet.payload_type == PayloadType.Advert and packet.payload.get('decoded'):\n advert = packet.payload['decoded']\n print(f\"Device Name: {advert.app_data.get('name')}\")\n print(f\"Device Role: {get_device_role_name(advert.app_data.get('device_role'))}\")\n if advert.app_data.get('location'):\n location = advert.app_data['location']\n print(f\"Location: {location['latitude']}, {location['longitude']}\")\n```\n\n## Full Packet Structure Example\n\nHere's what a complete decoded packet looks like:\n\n```python\nfrom src.decoder.packet_decoder import MeshCorePacketDecoder\nimport json\n\nhex_data = '11007E7662676F7F0850A8A355BAAFBFC1EB7B4174C340442D7D7161C9474A2C94006CE7CF682E58408DD8FCC51906ECA98EBF94A037886BDADE7ECD09FD92B839491DF3809C9454F5286D1D3370AC31A34593D569E9A042A3B41FD331DFFB7E18599CE1E60992A076D50238C5B8F85757375354522F50756765744D65736820436F75676172'\n\npacket = MeshCorePacketDecoder.decode(hex_data)\n\npacket_dict = packet.to_dict()\nprint(json.dumps(packet_dict, indent=2, default=str))\n```\n\n**Output:**\n```json\n{\n \"messageHash\": \"F9C060FE\",\n \"routeType\": 1,\n \"payloadType\": 4,\n \"payloadVersion\": 0,\n \"pathLength\": 0,\n \"path\": null,\n \"payload\": {\n \"raw\": \"7E7662676F7F0850A8A355BAAFBFC1EB7B4174C340442D7D7161C9474A2C94006CE7CF682E58408DD8FCC51906ECA98EBF94A037886BDADE7ECD09FD92B839491DF3809C9454F5286D1D3370AC31A34593D569E9A042A3B41FD331DFFB7E18599CE1E60992A076D50238C5B8F85757375354522F50756765744D65736820436F75676172\",\n \"decoded\": {\n \"type\": 4,\n \"version\": 0,\n \"isValid\": true,\n \"publicKey\": \"7E7662676F7F0850A8A355BAAFBFC1EB7B4174C340442D7D7161C9474A2C9400\",\n \"timestamp\": 1758455660,\n \"signature\": \"2E58408DD8FCC51906ECA98EBF94A037886BDADE7ECD09FD92B839491DF3809C9454F5286D1D3370AC31A34593D569E9A042A3B41FD331DFFB7E18599CE1E609\",\n \"appData\": {\n \"flags\": 146,\n \"deviceRole\": 2,\n \"hasLocation\": true,\n \"hasName\": true,\n \"location\": {\n \"latitude\": 47.543968,\n \"longitude\": -122.108616\n },\n \"name\": \"WW7STR/PugetMesh Cougar\"\n }\n }\n },\n \"totalBytes\": 134,\n \"isValid\": true\n}\n```\n\n## Decryption Support\n\nSimply provide your channel secret keys and the library handles everything else:\n\n```python\nfrom src.decoder.packet_decoder import MeshCorePacketDecoder\nfrom src.crypto.key_manager import MeshCoreKeyStore\nfrom src.types.crypto import DecryptionOptions\nfrom src.types.enums import PayloadType\n\n# Create a key store with channel secret keys\nkey_store = MeshCoreKeyStore({\n 'channel_secrets': [\n '8b3387e9c5cdea6ac9e5edbaa115cd72', # Public channel (channel hash 11)\n 'ff2b7d74e8d20f71505bda9ea8d59a1c', # A different channel's secret\n ]\n})\n\ngroup_text_hex_data = '...' # Your encrypted GroupText packet hex\n\n# Decode encrypted GroupText message\noptions = DecryptionOptions(key_store=key_store)\nencrypted_packet = MeshCorePacketDecoder.decode(group_text_hex_data, options)\n\nif encrypted_packet.payload_type == PayloadType.GroupText and encrypted_packet.payload.get('decoded'):\n group_text = encrypted_packet.payload['decoded']\n\n if group_text.decrypted:\n print(f\"Sender: {group_text.decrypted.get('sender')}\")\n print(f\"Message: {group_text.decrypted.get('message')}\")\n print(f\"Timestamp: {group_text.decrypted.get('timestamp')}\")\n else:\n print('Message encrypted (no key available)')\n```\n\nThe library automatically:\n- Calculates channel hashes from your secret keys using SHA256\n- Handles hash collisions (multiple keys with same first byte) by trying all matching keys\n- Verifies message authenticity using HMAC-SHA256\n- Decrypts using AES-128 ECB\n\n### With Signature Verification\n\n```python\nimport asyncio\nfrom src.decoder.packet_decoder import MeshCorePacketDecoder\n\n# Async verification for Ed25519 signatures\nasync def verify_packet():\n packet = await MeshCorePacketDecoder.decode_with_verification(hex_data)\n\n if packet.payload.get('decoded'):\n advert = packet.payload['decoded']\n if hasattr(advert, 'signature_valid'):\n print(f\"Signature Valid: {advert.signature_valid}\")\n\nasyncio.run(verify_packet())\n```\n\n## Packet Structure Analysis\n\nFor detailed packet analysis and debugging, use `analyze_structure()` to get byte-level breakdowns:\n\n```python\nfrom src.decoder.packet_decoder import MeshCorePacketDecoder\n\nprint('=== Packet Breakdown ===')\nhex_data = '11007E7662676F7F0850A8A355BAAFBFC1EB7B4174C340442D7D7161C9474A2C94006CE7CF682E58408DD8FCC51906ECA98EBF94A037886BDADE7ECD09FD92B839491DF3809C9454F5286D1D3370AC31A34593D569E9A042A3B41FD331DFFB7E18599CE1E60992A076D50238C5B8F85757375354522F50756765744D65736820436F75676172'\n\nprint(f\"Packet length: {len(hex_data)}\")\nprint(f\"Expected bytes: {len(hex_data) / 2}\")\n\nstructure = MeshCorePacketDecoder.analyze_structure(hex_data)\nprint('\\nMain segments:')\nfor i, seg in enumerate(structure.segments):\n print(f\"{i+1}. {seg.name} (bytes {seg.start_byte}-{seg.end_byte}): {seg.value}\")\n\nprint('\\nPayload segments:')\nfor i, seg in enumerate(structure.payload['segments']):\n print(f\"{i+1}. {seg.name} (bytes {seg.start_byte}-{seg.end_byte}): {seg.value}\")\n print(f\" Description: {seg.description}\")\n```\n\n**Output:**\n```\n=== Packet Breakdown ===\nPacket length: 268\nExpected bytes: 134\n\nMain segments:\n1. Header (bytes 0-0): 0x11\n2. Path Length (bytes 1-1): 0x00\n3. Payload (bytes 2-133): 7E7662676F7F0850A8A355BAAFBFC1EB7B4174C340442D7D7161C9474A2C94006CE7CF682E58408DD8FCC51906ECA98EBF94A037886BDADE7ECD09FD92B839491DF3809C9454F5286D1D3370AC31A34593D569E9A042A3B41FD331DFFB7E18599CE1E60992A076D50238C5B8F85757375354522F50756765744D65736820436F75676172\n\nPayload segments:\n1. Public Key (bytes 0-31): 7E7662676F7F0850A8A355BAAFBFC1EB7B4174C340442D7D7161C9474A2C9400\n Description: Ed25519 public key\n2. Timestamp (bytes 32-35): 6CE7CF68\n Description: 1758455660 (2025-09-21T11:54:20Z)\n3. Signature (bytes 36-99): 2E58408DD8FCC51906ECA98EBF94A037886BDADE7ECD09FD92B839491DF3809C9454F5286D1D3370AC31A34593D569E9A042A3B41FD331DFFB7E18599CE1E609\n Description: Ed25519 signature\n4. App Flags (bytes 100-100): 92\n Description: Binary: 10010010 | Bits 0-3 (Role): Room server | Bit 4 (Location): Yes | Bit 5 (Feature1): No | Bit 6 (Feature2): No | Bit 7 (Name): Yes\n5. Latitude (bytes 101-104): A076D502\n Description: 47.543968\u00b0 (47.543968)\n6. Longitude (bytes 105-108): 38C5B8F8\n Description: -122.108616\u00b0 (-122.108616)\n7. Node Name (bytes 109-131): 5757375354522F50756765744D65736820436F75676172\n Description: Node name: \"WW7STR/PugetMesh Cougar\"\n```\n\nThe `analyze_structure()` method provides:\n- **Header breakdown** with bit-level field analysis\n- **Byte-accurate segments** with start/end positions\n- **Payload field parsing** for all supported packet types\n- **Human-readable descriptions** for each field\n\n## Ed25519 Key Derivation\n\nThe library includes MeshCore-compatible Ed25519 key derivation using the exact orlp/ed25519 algorithm:\n\n```python\nfrom src.crypto.ed25519_verifier import derive_public_key, validate_key_pair\n\n# Derive public key from MeshCore private key (64-byte format)\nprivate_key = '18469d6140447f77de13cd8d761e605431f52269fbff43b0925752ed9e6745435dc6a86d2568af8b70d3365db3f88234760c8ecc645ce469829bc45b65f1d5d5'\n\npublic_key = derive_public_key(private_key)\nprint('Derived Public Key:', public_key)\n# Output: 4852B69364572B52EFA1B6BB3E6D0ABED4F389A1CBFBB60A9BBA2CCE649CAF0E\n\n# Validate a key pair\nis_valid = validate_key_pair(private_key, public_key)\nprint('Key pair valid:', is_valid) # True\n```\n\n## Command Line Interface\n\nFor quick analysis from the terminal, use the CLI:\n\n```bash\n# Analyze a packet\npython cli.py decode 11007E7662676F7F0850A8A355BAAFBFC1EB7B4174C340442D7D7161C9474A2C94006CE7CF682E58408DD8FCC51906ECA98EBF94A037886BDADE7ECD09FD92B839491DF3809C9454F5286D1D3370AC31A34593D569E9A042A3B41FD331DFFB7E18599CE1E60992A076D50238C5B8F85757375354522F50756765744D65736820436F75676172\n\n# With decryption (provide channel secrets)\npython cli.py decode 150011C3C1354D619BAE9590E4D177DB7EEAF982F5BDCF78005D75157D9535FA90178F785D --key 8b3387e9c5cdea6ac9e5edbaa115cd72\n\n# Show detailed structure analysis\npython cli.py decode --structure 11007E7662676F7F0850A8A355BAAFBFC1EB7B4174C340442D7D7161C9474A2C94006CE7CF682E58408DD8FCC51906ECA98EBF94A037886BDADE7ECD09FD92B839491DF3809C9454F5286D1D3370AC31A34593D569E9A042A3B41FD331DFFB7E18599CE1E60992A076D50238C5B8F85757375354522F50756765744D65736820436F75676172\n\n# JSON output\npython cli.py decode --json 11007E7662676F7F0850A8A355BAAFBFC1EB7B4174C340442D7D7161C9474A2C94006CE7CF682E58408DD8FCC51906ECA98EBF94A037886BDADE7ECD09FD92B839491DF3809C9454F5286D1D3370AC31A34593D569E9A042A3B41FD331DFFB7E18599CE1E60992A076D50238C5B8F85757375354522F50756765744D65736820436F75676172\n\n# Derive public key from MeshCore private key\npython cli.py derive-key 18469d6140447f77de13cd8d761e605431f52269fbff43b0925752ed9e6745435dc6a86d2568af8b70d3365db3f88234760c8ecc645ce469829bc45b65f1d5d5\n\n# Validate key pair\npython cli.py validate-key 18469d6140447f77de13cd8d761e605431f52269fbff43b0925752ed9e6745435dc6a86d2568af8b70d3365db3f88234760c8ecc645ce469829bc45b65f1d5d5 4852b69364572b52efa1b6bb3e6d0abed4f389a1cbfbb60a9bba2cce649caf0e\n```\n\n\n\n\n## License\n\nMIT License\n\nCopyright (c) 2025 Michael Hart <michaelhart@michaelhart.me> (https://github.com/michaelhart)\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n",
"bugtrack_url": null,
"license": "MIT",
"summary": "Complete Python implementation of the MeshCore Packet Decoder",
"version": "0.1.0",
"project_urls": {
"Homepage": "https://github.com/chrisdavis2110/meshcore-decoder-py",
"Issues": "https://github.com/chrisdavis2110/meshcore-decoder-py/issues",
"Repository": "https://github.com/chrisdavis2110/meshcore-decoder-py"
},
"split_keywords": [
"meshcore",
" decoder",
" packet",
" mesh",
" networking"
],
"urls": [
{
"comment_text": null,
"digests": {
"blake2b_256": "7530b74ffec7ead13585ce9c8c670e2c376b93b4d23b85081e299f88bb40da5c",
"md5": "f9bba88a307d70df5e8446aedc8a7e1f",
"sha256": "9df251d6fe17c0cd112ad417ba52f826a913cefaffb25b5b9dbb20538fc0eda5"
},
"downloads": -1,
"filename": "meshcore_decoder-0.1.0-py3-none-any.whl",
"has_sig": false,
"md5_digest": "f9bba88a307d70df5e8446aedc8a7e1f",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": ">=3.8",
"size": 42013,
"upload_time": "2025-10-28T05:23:16",
"upload_time_iso_8601": "2025-10-28T05:23:16.107914Z",
"url": "https://files.pythonhosted.org/packages/75/30/b74ffec7ead13585ce9c8c670e2c376b93b4d23b85081e299f88bb40da5c/meshcore_decoder-0.1.0-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": null,
"digests": {
"blake2b_256": "c4ece797bb37a41fd1b05c5128c9f795574201d789238d7bdc52e83f17c1bb0e",
"md5": "a70f990b5ff7e4bb2d5463e7ddc204ed",
"sha256": "af4b7d2ecf3c46674abf7e770aaf1500cfbb286ffb50a38c2acf78c385f30683"
},
"downloads": -1,
"filename": "meshcore_decoder-0.1.0.tar.gz",
"has_sig": false,
"md5_digest": "a70f990b5ff7e4bb2d5463e7ddc204ed",
"packagetype": "sdist",
"python_version": "source",
"requires_python": ">=3.8",
"size": 29421,
"upload_time": "2025-10-28T05:23:18",
"upload_time_iso_8601": "2025-10-28T05:23:18.692319Z",
"url": "https://files.pythonhosted.org/packages/c4/ec/e797bb37a41fd1b05c5128c9f795574201d789238d7bdc52e83f17c1bb0e/meshcore_decoder-0.1.0.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2025-10-28 05:23:18",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "chrisdavis2110",
"github_project": "meshcore-decoder-py",
"travis_ci": false,
"coveralls": false,
"github_actions": false,
"requirements": [
{
"name": "pycryptodome",
"specs": [
[
">=",
"3.19.0"
]
]
},
{
"name": "cryptography",
"specs": [
[
">=",
"41.0.0"
]
]
},
{
"name": "click",
"specs": [
[
">=",
"8.1.0"
]
]
}
],
"lcname": "meshcore-decoder"
}