Thank you for your interest in contributing to Ultimate Enigma Messenger! This document provides guidelines for development, testing, and code style.
- Python 3.10 or higher
- pip (Python package manager)
- Git
- Windows Users Only: Visual Studio Build Tools with MSVC and Windows 11 SDK (required for native Python extensions like
cryptographyandargon2-cffi). Run the providedsetup_dev_env.ps1script as Administrator to install these automatically.
-
Clone the repository:
git clone https://github.com/yourusername/ultimate-enigma.git cd ultimate-enigma -
Create a virtual environment:
python -m venv venv source venv/bin/activate # Linux/macOS venv\Scripts\activate # Windows
-
Install dependencies:
pip install -r requirements.txt
-
Run the application:
python main.py
The application follows an MVC architecture with approximately 8 tabs, 23 service modules, and 8 reusable components.
main.py Entry point, logging, anti-tamper, theme init
app.py EnigmaApp composition root (8 tabs, event wiring, emergency lock)
crypto.py AES-GCM + RSA-OAEP, time-based keys, constant-time decrypt
database.py SQLCipher/SQLite layer, Argon2id KDF, PBKDF2→Argon2id migration
key_manager.py KeyStore: RSA 4096, PQC keys, duress mode, password change
builders/
app_builder.py Application composition root builder
models/ Data structures (envelope, friend_profile)
views/ UI files (tabs, lock_screen, utils)
ecdh.py ECDH key exchange view
controllers/ Business logic coordination (3 controllers)
services/ 23 service modules (plus encryption/ and friends/ subpackages)
ecdh_service.py ECDH key exchange service
file_ops.py File operation utilities
encryption/ Subpackage: encryption strategies (facade, legacy, pqc, ratchet)
friends/ Subpackage: friends management (crud, facade, keys)
components/ 8 reusable dialogs
recovery_unlock_dialog.py
update_friend_keys_dialog.py
src/ Constants, exceptions, helpers
crypto_task_helper.py Async crypto task helpers
security/ Memory security, anti-dump, guarded buffers, lockout
tests/ 36 test files, 550+ tests
encryption/ (empty) – future grouped tests
friends/ (empty) – future grouped tests
- Use type hints for all function signatures
- Write docstrings for all public classes and methods
- Follow PEP 8 naming conventions
- Keep functions focused and single-purpose
- Use logging instead of print statements
- Never log sensitive data (keys, passwords, plaintext)
- Use
SecureStringfor sensitive string handling - Always wipe sensitive data when no longer needed
- Use constants from
src/constants.pyinstead of magic numbers - Apply timeout decorators to potentially blocking operations
- Anti-tamper protections (
src/anti_tamper.py) only activate in frozen .exe; do not test debugger detection from source - Use
GuardedBuffer(security/guarded_buffer.py) for in-memory secrets (e.g. chain keys, global secret). GuardedBuffer supportsbytes(),len(), iteration, and==comparison for seamless interop with bytes-based code. Always wrap values via_update_chain_key()orGuardedBuffer.write()— never store rawbytesfor sensitive data.
Use the shared helpers in views/utils.py instead of ad-hoc implementations so behavior stays consistent (see docs/VIEWS_AND_CONTROLLERS.md → Shared UI Helpers).
- Never show raw exceptions to users. Wrap user-facing errors with
friendly_error(exc)inmessagebox.showerror, and log the raw detail withlogger.exception(...). - Don't block the UI thread. Run blocking crypto/network/file work off-thread via
run_busy(...)(or the existingsubmit_crypto_task). Show a busy cursor and disable the trigger button while in flight. Tkinter is not thread-safe — thework()callable must do no UI calls; perform all widget updates inon_done/on_error. - Modal dialogs: call
init_modal(dlg, parent, focus_widget=...)once after creating/sizing aToplevel— it centers over the parent, makes it modal (grab_set), binds<Escape>and the window-close (X) button, and sets initial focus. - Feedback: prefer inline feedback (
flash_widget_texton a copy button) over modal "done" dialogs for frequent actions. Confirm destructive actions withaskyesno, and act on the current selection rather than asking the user to retype identifiers. - Theme over hardcoded styling: use ttkbootstrap
bootstyleandttk.Style().colors; avoid hardcoded hex colors and Windows-only fonts so light/dark themes and non-Windows platforms render correctly. Don't rely on color alone to convey state — pair it with a text label. - Read-only displays: keep ciphertext/plaintext output widgets
state='disabled'(toggle only while inserting) so users can't corrupt them.
def encrypt(self, plaintext: str, friend_name: str = None, mode: str = 'shared', sign: bool = True) -> bytes:
"""Encrypt a message for optional specific recipient.
Args:
plaintext: The message text to encrypt.
friend_name: Optional friend name for recipient-specific encryption.
Returns:
Base64-encoded ciphertext string.
Raises:
KeyNotFoundError: If friend's key is not found.
EncryptionError: If encryption fails.
"""
# Implementation...Run all tests:
pytest tests/ -vRun specific test file:
pytest tests/test_encryption_service.py -vRun with coverage:
pytest tests/ --cov=. --cov-report=html- Place tests in
tests/directory - Name test files
test_<module>.py - Name test functions
test_<feature>_<scenario> - Use fixtures from
conftest.pyfor common setup - Test both success and failure cases
The test directory contains 36 test files with 550+ tests. It includes subdirectories for future grouped tests:
tests/
├── encryption/ # (empty) – future encryption service tests
├── friends/ # (empty) – future friends service tests
├── test_*.py # Individual module tests (36 files, 550+ tests)
└── conftest.py # Shared fixtures
import pytest
from services.encryption import EncryptionService
class TestEncryptionService:
def test_encrypt_decrypt_roundtrip(self, key_store):
"""Test that encrypted messages can be decrypted."""
service = EncryptionService(key_store)
plaintext = "Hello, World!"
ciphertext, timestamp = service.encrypt(plaintext)
result = service.decrypt(ciphertext)
assert plaintext in result
def test_decrypt_invalid_ciphertext_raises(self, key_store):
"""Test that invalid ciphertext raises DecryptionError."""
service = EncryptionService(key_store)
with pytest.raises(DecryptionError):
service.decrypt_message("invalid_base64!!!")- Create
services/new_service.py(or use the sub-package pattern:services/new_service/__init__.pywith separate modules) - Define the service class with
__init__(self, key_store: KeyStore) - Add to
ServiceOrchestrator.__init__()andrebuild_services() - Update tab references if needed
- If the service needs periodic background work, create an agent class in
services/background_agents.py - Write comprehensive tests
- Create
new_tab.pywith a class inheriting from or containing a Frame - Accept required services in
__init__ - Add to
_setup_tabs()inapp.py - Subscribe to relevant events if needed
- Update
ServiceOrchestrator._update_tab_references()if service-dependent
- Add constant to
Eventsclass inservices/event_bus.py - Publish event where appropriate:
event_bus.publish(Events.NEW_EVENT, ...) - Subscribe in components that need to react
- Document the event in this file and ARCHITECTURE.md
-
Create a feature branch from
master:git checkout -b feature/your-feature-name
-
Make your changes with clear, atomic commits
-
Ensure all tests pass:
pytest tests/ -v
-
Update documentation if applicable:
docs/ARCHITECTURE.mdfor structural changesdocs/API.mdfor new public APIsdocs/SECURITY.mdfor security-relevant changesdocs/SCIENTIFIC_REPORT.mdfor cryptographic research and standards updatesreadme.mdfor user-facing changes
-
Submit a pull request with:
- Clear description of changes
- Reference to any related issues
- Summary of testing performed
Do not open public issues for security vulnerabilities.
Please report security issues privately to the maintainer. Include:
- Description of the vulnerability
- Steps to reproduce
- Potential impact assessment
- Suggested fix (if any)
By contributing, you agree that your contributions will be licensed under the Polyform Noncommercial License 1.0.0.
Open an issue for questions about development, architecture, or features.