From b6f07161ef3b5c38d4cb7a0d777500241e93abda Mon Sep 17 00:00:00 2001 From: DeFiDude <59237470+DeFiDude@users.noreply.github.com> Date: Sat, 13 Jun 2026 17:58:26 -0600 Subject: [PATCH] identity: accept exported identity key filenames --- src/config/Config.h | 2 ++ src/reticulum/IdentityManager.cpp | 43 +++++++++++++++++++++++++++-- src/reticulum/IdentityManager.h | 1 + src/ui/screens/LvSettingsScreen.cpp | 27 ++++++++++++++++-- 4 files changed, 68 insertions(+), 5 deletions(-) diff --git a/src/config/Config.h b/src/config/Config.h index d76b5a5..642fc6f 100644 --- a/src/config/Config.h +++ b/src/config/Config.h @@ -49,7 +49,9 @@ #define SD_PATH_USER_CONFIG "/ratdeck/config/user.json" #define SD_PATH_MESSAGES "/ratdeck/messages" #define SD_PATH_CONTACTS "/ratdeck/contacts" +#define SD_PATH_IDENTITY_DIR "/ratdeck/identity" #define SD_PATH_IDENTITY "/ratdeck/identity/identity.key" +#define SD_PATH_IMPORT_IDENTITY "/ratdeck/identity/import.identity" #define SD_PATH_IMPORT_ID "/ratdeck/identity/import.key" // --- TCP Client --- diff --git a/src/reticulum/IdentityManager.cpp b/src/reticulum/IdentityManager.cpp index 90c4919..794be75 100644 --- a/src/reticulum/IdentityManager.cpp +++ b/src/reticulum/IdentityManager.cpp @@ -64,14 +64,52 @@ String IdentityManager::slotKeyPath(int slotNum) const { return String(path); } +String IdentityManager::importIdentityPath() const { + if (!_sd || !_sd->isReady()) return ""; + if (_sd->exists(SD_PATH_IMPORT_IDENTITY)) return String(SD_PATH_IMPORT_IDENTITY); + if (_sd->exists(SD_PATH_IMPORT_ID)) return String(SD_PATH_IMPORT_ID); + + File dir = _sd->openDir(SD_PATH_IDENTITY_DIR); + if (!dir) return ""; + String candidate; + int candidates = 0; + while (true) { + File entry = dir.openNextFile(); + if (!entry) break; + if (entry.isDirectory()) { + entry.close(); + continue; + } + String name = entry.name(); + entry.close(); + String lower = name; + lower.toLowerCase(); + bool legacyIdentityKey = lower == "identity.key" || lower.endsWith("/identity.key"); + bool importCandidate = lower.endsWith(".identity") || (lower.endsWith(".key") && !legacyIdentityKey); + if (importCandidate) { + candidate = name.startsWith("/") ? name : String(SD_PATH_IDENTITY_DIR) + "/" + name; + candidates++; + } + } + if (candidates == 1) return candidate; + if (candidates > 1) Serial.println("[IDMGR] Multiple import identity files found on SD"); + return ""; +} + int IdentityManager::importIdentity(const String& displayName) { (void)displayName; if (!_sd || !_sd->isReady()) return -1; if ((int)_slots.size() >= MAX_IDENTITIES) return -1; + String importPath = importIdentityPath(); + if (importPath.isEmpty()) { + Serial.println("[IDMGR] No import identity file found on SD"); + return -1; + } + uint8_t buffer[64]; size_t bytesRead = 0; - if (!_sd->readFile(SD_PATH_IMPORT_ID, buffer, sizeof(buffer), bytesRead) || bytesRead != sizeof(buffer)) { + if (!_sd->readFile(importPath.c_str(), buffer, sizeof(buffer), bytesRead) || bytesRead != sizeof(buffer)) { Serial.println("[IDMGR] Failed to read 64-byte import identity from SD"); return -1; } @@ -98,7 +136,8 @@ int IdentityManager::importIdentity(const String& displayName) { _slots.push_back(slot); saveSlotMeta(); - Serial.printf("[IDMGR] Imported identity %d: %s\n", slotNum, slot.hash.substr(0, 16).c_str()); + Serial.printf("[IDMGR] Imported identity %d from %s: %s\n", + slotNum, importPath.c_str(), slot.hash.substr(0, 16).c_str()); return slotNum; } diff --git a/src/reticulum/IdentityManager.h b/src/reticulum/IdentityManager.h index b22d557..8fb505b 100644 --- a/src/reticulum/IdentityManager.h +++ b/src/reticulum/IdentityManager.h @@ -56,6 +56,7 @@ private: void loadSlotMeta(); void saveSlotMeta(); String slotKeyPath(int slotNum) const; + String importIdentityPath() const; FlashStore* _flash = nullptr; SDStore* _sd = nullptr; diff --git a/src/ui/screens/LvSettingsScreen.cpp b/src/ui/screens/LvSettingsScreen.cpp index ad2581c..a08a82a 100644 --- a/src/ui/screens/LvSettingsScreen.cpp +++ b/src/ui/screens/LvSettingsScreen.cpp @@ -473,9 +473,30 @@ void LvSettingsScreen::buildItems() { if (_ui) _ui->lvStatusBar().showToast("No SD card", 1200); return; } - if (!_sd->exists(SD_PATH_IMPORT_ID)) { - if (_ui) _ui->lvStatusBar().showToast("Missing import.key", 1200); - return; + if (!_sd->exists(SD_PATH_IMPORT_IDENTITY) && !_sd->exists(SD_PATH_IMPORT_ID)) { + File dir = _sd->openDir(SD_PATH_IDENTITY_DIR); + int identityFiles = 0; + while (dir) { + File entry = dir.openNextFile(); + if (!entry) break; + if (!entry.isDirectory()) { + String name = entry.name(); + name.toLowerCase(); + bool legacyIdentityKey = name == "identity.key" || name.endsWith("/identity.key"); + if (name.endsWith(".identity") || (name.endsWith(".key") && !legacyIdentityKey)) { + identityFiles++; + } + } + entry.close(); + } + if (identityFiles == 0) { + if (_ui) _ui->lvStatusBar().showToast("Missing identity file", 1200); + return; + } + if (identityFiles > 1) { + if (_ui) _ui->lvStatusBar().showToast("Rename one import.identity", 1500); + return; + } } if (!_idMgr) { if (_ui) _ui->lvStatusBar().showToast("Not available", 1200);