Room server identity_key rejects 64-byte MeshCore firmware keys #97

Closed
opened 2026-10-27 09:33:02 +01:00 by adam · 0 comments
Owner

When importing a private key exported from an official MeshCore Room Server firmware device, pyMC_Repeater silently skips the room server with only a log error:

Identity key for 'MyRoom' is invalid length: 64 bytes (expected 32)

Root cause

MeshCore firmware exports private keys in a 64-byte expanded format: [32-byte scalar][32-byte nonce] (128 hex characters). The room server identity loader in main.py strictly
requires 32 bytes and discards any other length.

The fix is a one-line change — allow 64-byte keys to pass through:

Before

if len(identity_key_bytes) != 32:

After

if len(identity_key_bytes) not in (32, 64):

Why simply truncating to 32 bytes does not work

LocalIdentity(seed=bytes) behaves differently depending on length:

  • 32 bytes → treated as a standard PyNaCl seed, SHA-512 hashed internally → produces a different public key
  • 64 bytes → treated as a MeshCore expanded key, derives public key via crypto_scalarmult_ed25519_base_noclamp (no hashing) → matches the firmware identity

LocalIdentity already correctly handles the 64-byte format. The room server loader just needs to let it through.

Steps to reproduce

  1. Export the private key from a MeshCore Room Server firmware device (64-byte / 128 hex char key)
  2. Add it as identity_key under identities.room_servers in config.yaml
  3. Start pyMC_Repeater — the room server is skipped

Expected behaviour

The room server loads with the same public key and node address as the original firmware device.

When importing a private key exported from an official MeshCore Room Server firmware device, pyMC_Repeater silently skips the room server with only a log error: Identity key for 'MyRoom' is invalid length: 64 bytes (expected 32) Root cause MeshCore firmware exports private keys in a 64-byte expanded format: [32-byte scalar][32-byte nonce] (128 hex characters). The room server identity loader in main.py strictly requires 32 bytes and discards any other length. The fix is a one-line change — allow 64-byte keys to pass through: # Before if len(identity_key_bytes) != 32: # After if len(identity_key_bytes) not in (32, 64): Why simply truncating to 32 bytes does not work LocalIdentity(seed=bytes) behaves differently depending on length: - 32 bytes → treated as a standard PyNaCl seed, SHA-512 hashed internally → produces a different public key - 64 bytes → treated as a MeshCore expanded key, derives public key via crypto_scalarmult_ed25519_base_noclamp (no hashing) → matches the firmware identity LocalIdentity already correctly handles the 64-byte format. The room server loader just needs to let it through. Steps to reproduce 1. Export the private key from a MeshCore Room Server firmware device (64-byte / 128 hex char key) 2. Add it as identity_key under identities.room_servers in config.yaml 3. Start pyMC_Repeater — the room server is skipped Expected behaviour The room server loads with the same public key and node address as the original firmware device. <!-- github-sync-id:4527024766 -->
adam closed this issue 2026-10-27 09:33:02 +01:00
Sign in to join this conversation.
No labels
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: adam/pyMC_Repeater#97