mirror of
https://github.com/meshcore-dev/meshcore_py.git
synced 2026-04-20 22:13:49 +00:00
Add private key export support
- Add PRIVATE_KEY and DISABLED event types - Add packet parsing for private key export responses - Add export_private_key() method to DeviceCommands - Add comprehensive unit tests - Add BLE private key export example - Update documentation with security notes
This commit is contained in:
parent
c697c960a6
commit
e0f71482c6
6 changed files with 305 additions and 0 deletions
102
examples/ble_private_key_export.py
Normal file
102
examples/ble_private_key_export.py
Normal file
|
|
@ -0,0 +1,102 @@
|
|||
#!/usr/bin/env python3
|
||||
"""
|
||||
Example: BLE Private Key Export with MeshCore
|
||||
|
||||
This example demonstrates how to export the private key from a MeshCore device
|
||||
using BLE with PIN-based pairing for enhanced security.
|
||||
|
||||
Note: This feature requires:
|
||||
1. A MeshCore device running companion radio firmware
|
||||
2. ENABLE_PRIVATE_KEY_EXPORT=1 compile-time flag enabled
|
||||
3. Authenticated BLE connection with PIN
|
||||
"""
|
||||
|
||||
import asyncio
|
||||
import argparse
|
||||
from meshcore import MeshCore
|
||||
from meshcore.events import EventType
|
||||
|
||||
|
||||
async def main():
|
||||
parser = argparse.ArgumentParser(description="Export private key from MeshCore device via BLE")
|
||||
parser.add_argument("-a", "--addr", help="BLE address of the device (optional, will scan if not provided)")
|
||||
parser.add_argument("-p", "--pin", help="PIN for BLE pairing (required for private key export)")
|
||||
parser.add_argument("--debug", action="store_true", help="Enable debug logging")
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
if not args.pin:
|
||||
print("❌ PIN is required for private key export. Use -p or --pin to specify it.")
|
||||
return 1
|
||||
|
||||
try:
|
||||
print("Connecting to MeshCore device...")
|
||||
print(f"Using PIN for pairing: {args.pin}")
|
||||
|
||||
# Create BLE connection with PIN (required for private key export)
|
||||
meshcore = await MeshCore.create_ble(
|
||||
address=args.addr,
|
||||
pin=args.pin,
|
||||
debug=args.debug
|
||||
)
|
||||
|
||||
print("✅ Connected successfully!")
|
||||
|
||||
# Get device information to verify connection
|
||||
result = await meshcore.commands.send_device_query()
|
||||
if result.payload:
|
||||
print(f"Device model: {result.payload.get('model', 'Unknown')}")
|
||||
print(f"Firmware version: {result.payload.get('fw ver', 'Unknown')}")
|
||||
|
||||
# Export private key
|
||||
print("\n🔑 Requesting private key export...")
|
||||
result = await meshcore.commands.export_private_key()
|
||||
|
||||
if result.type == EventType.PRIVATE_KEY:
|
||||
private_key = result.payload["private_key"]
|
||||
print("✅ Private key exported successfully!")
|
||||
print(f"Private key (64 bytes): {private_key.hex()}")
|
||||
print(f"Private key length: {len(private_key)} bytes")
|
||||
|
||||
# Optionally save to file
|
||||
save_to_file = input("\nSave private key to file? (y/N): ").lower().strip()
|
||||
if save_to_file == 'y':
|
||||
filename = input("Enter filename (default: private_key.bin): ").strip()
|
||||
if not filename:
|
||||
filename = "private_key.bin"
|
||||
|
||||
with open(filename, 'wb') as f:
|
||||
f.write(private_key)
|
||||
print(f"Private key saved to {filename}")
|
||||
|
||||
elif result.type == EventType.DISABLED:
|
||||
print("❌ Private key export is disabled on this device")
|
||||
print("This feature requires:")
|
||||
print(" - Companion radio firmware")
|
||||
print(" - ENABLE_PRIVATE_KEY_EXPORT=1 compile-time flag")
|
||||
|
||||
elif result.type == EventType.ERROR:
|
||||
print(f"❌ Error exporting private key: {result.payload}")
|
||||
|
||||
else:
|
||||
print(f"❌ Unexpected response: {result.type}")
|
||||
|
||||
print("\nPrivate key export test completed!")
|
||||
|
||||
except ConnectionError as e:
|
||||
print(f"❌ Failed to connect: {e}")
|
||||
return 1
|
||||
except Exception as e:
|
||||
print(f"❌ Error: {e}")
|
||||
return 1
|
||||
finally:
|
||||
if 'meshcore' in locals():
|
||||
await meshcore.disconnect()
|
||||
print("Disconnected from device")
|
||||
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
import sys
|
||||
sys.exit(asyncio.run(main()))
|
||||
Loading…
Add table
Add a link
Reference in a new issue