Skip to content

Conversation

@torlando-tech
Copy link
Owner

Summary

  • Implements layered AES-256-GCM encryption for Reticulum identity keys using Android Keystore
  • Adds optional user password protection layer (PBKDF2 with 600K iterations)
  • Silently migrates existing unencrypted keys to encrypted storage on app startup
  • Updates migration export/import to use password-protected encryption

Security Properties

Property Implementation
At-rest encryption AES-256-GCM with Android Keystore
Hardware binding TEE/StrongBox backed (non-extractable)
Forward secrecy Random IV per encryption
Integrity GCM authentication tag prevents tampering
Password protection PBKDF2-HMAC-SHA256, 600K iterations
Secure deletion Memory wiped with random data before zeroing

Architecture

┌─────────────────────────────────────────────────────────────┐
│  64-byte Reticulum Identity Key                             │
└─────────────────────────────────────────────────────────────┘
                          │
                          ▼
┌─────────────────────────────────────────────────────────────┐
│  Layer 1: Device Key (Android Keystore)                     │
│  - AES-256-GCM with hardware backing (TEE/StrongBox)        │
│  - Always active, transparent to user                       │
└─────────────────────────────────────────────────────────────┘
                          │
                          ▼ (optional)
┌─────────────────────────────────────────────────────────────┐
│  Layer 2: User Password (PBKDF2 + AES-256-GCM)              │
│  - User-provided PIN/password required to unlock            │
└─────────────────────────────────────────────────────────────┘

Files Changed

New files:

  • IdentityKeyEncryptor.kt - Core AES-256-GCM encryption with Keystore
  • IdentityKeyMigrator.kt - Auto-migration of unencrypted keys
  • IdentityKeyProvider.kt - Runtime key access with caching

Modified files:

  • LocalIdentityEntity.kt - Added encrypted storage columns
  • LocalIdentityDao.kt - New queries for encrypted key management
  • DatabaseModule.kt - Migration 30→31
  • IdentityRepository.kt - Integration with encryption system
  • MigrationData/Exporter/Importer.kt - Password-protected export

Test plan

  • Unit tests for IdentityKeyEncryptor (password ops, export encryption)
  • Unit tests for IdentityKeyMigrator (migration scenarios)
  • Unit tests for IdentityKeyProvider (key access, caching)
  • Manual: Fresh install creates only encrypted keys in database
  • Manual: Upgrade from old version auto-migrates keys
  • Manual: Export with password, import on another device
  • Manual: Verify no plaintext keys in database (via adb)

Note: Device-key encryption tests require instrumented tests (real Keystore). Unit tests cover password-based encryption and utility methods.

🤖 Generated with Claude Code

Implements layered AES-256-GCM encryption for identity key protection:

- IdentityKeyEncryptor: Core encryption using Android Keystore (device key)
  with optional PBKDF2-based password protection layer
- IdentityKeyMigrator: Silent auto-migration of unencrypted keys at startup
- IdentityKeyProvider: Runtime decrypted key access with in-memory caching
  and lifecycle-aware cleanup when app goes to background

Database changes:
- Add encryptedKeyData, keyEncryptionVersion, passwordSalt,
  passwordVerificationHash columns to LocalIdentityEntity
- Migration 30→31 for new columns

Migration export/import:
- Password-protected export encryption for portable backups
- MigrationData version bumped to 7

Security properties:
- Hardware-backed encryption via TEE/StrongBox
- Random IV per encryption for forward secrecy
- GCM authentication prevents tampering
- Secure memory wiping after use

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@github-actions
Copy link

❌ Threading Architecture Audit Failed

View Audit Report
Dispatcher Audit Report - Sat Jan 17 03:22:50 UTC 2026
========================================


═══════════════════════════════════════
1. Checking for runBlocking in Production Code
═══════════════════════════════════════
❌ VIOLATION: runBlocking found: data/src/main/java/com/lxmf/messenger/data/crypto/IdentityKeyProvider.kt:460:            kotlinx.coroutines.runBlocking {

═══════════════════════════════════════
2. Checking for Forbidden Patterns
═══════════════════════════════════════
✅ PASS: No GlobalScope usage found
✅ PASS: No Dispatchers.Unconfined usage found

═══════════════════════════════════════
3. Checking Python Initialization Uses Main.immediate
═══════════════════════════════════════
✅ PASS: Python initialization uses Dispatchers.Main.immediate

═══════════════════════════════════════
4. Summary - CI Optimized Check Complete
═══════════════════════════════════════
ℹ️  INFO: Sections 5-9 skipped for CI performance (non-critical checks)
ℹ️  INFO: All critical threading violations checked (runBlocking, GlobalScope, Unconfined, Python init)
ℹ️  INFO: For comprehensive analysis, run audit-dispatchers-full.sh locally

Please fix the dispatcher violations before merging.

Replace runBlocking with synchronous cache clearing in onStop() lifecycle
callback. ConcurrentHashMap is thread-safe for this cleanup scenario.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@torlando-tech torlando-tech added this to the v0.7.0 milestone Jan 17, 2026
torlando-tech and others added 4 commits January 16, 2026 22:48
Fix compilation error caused by trailing lambda being interpreted
as the new importPassword parameter instead of onProgress.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add mock initializations for keyEncryptor, keyMigrator, and keyProvider
parameters that were added to IdentityRepository constructor as part of
the encrypted identity key storage feature.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The migration bundle version was bumped to 7 for encrypted identity
key support. Update test assertion to match.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The test was flaky because yield() doesn't guarantee the collector is
subscribed before downloadRegion starts emitting statuses. Use onStart{}
with CompletableDeferred to ensure the collector is fully subscribed
before starting the download.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@codecov
Copy link

codecov bot commented Jan 17, 2026

Codecov Report

❌ Patch coverage is 8.60215% with 85 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
.../com/lxmf/messenger/migration/MigrationExporter.kt 2.17% 45 Missing ⚠️
.../com/lxmf/messenger/migration/MigrationImporter.kt 2.43% 40 Missing ⚠️

📢 Thoughts on this report? Let us know!

@torlando-tech torlando-tech modified the milestones: v0.7.0, v0.8.0 Jan 18, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants