Skip to content

Repository files navigation

Numyn logo

Numyn

You're just a number. Keep it that way.

An ICQ-style, end-to-end encrypted, server-distrusting messenger — in pure Python.

License: MIT Python 3.11+ Status: work in progress Crypto


Numyn ("NEW-min") is a chat system styled and behaving like classic ICQ. You are a number (a UIN). You add numbers. You see who's online. It feels like ICQ — but every message is end-to-end encrypted, the server can never read your messages or impersonate your contacts, and a man-in-the-middle attack is detectable by anyone who checks a safety number.

Private. Verifiable. Yours.

New here?QUICK_USE.md gets you chatting in five minutes · PRE-REQ.md explains what you need and why.


⚠️ Work in progress — for play, not production

This is an experimental, work-in-progress project. Use it only for playing, learning, and tinkering — not for any serious or production-ready purpose.

It has not had an independent third-party security audit. Despite the careful threat model and adversarial test suite, the protocol and code may contain bugs or design flaws that compromise the security guarantees described below. Do not rely on it to protect real secrets or to keep anyone safe. Run it to explore the ideas, read the code, and experiment — that's what this release is for.


Why this exists

Mainstream "encrypted" chat usually trusts a central provider for identity and key distribution; a compromised or coerced provider can silently man-in-the-middle users. Numyn keeps the friendly ICQ identity model but makes the server untrusted: it is a directory and a fallback relay, never a holder of plaintext, and it cannot substitute a contact's keys without that substitution being visible to users who verify safety numbers.

See docs/THREAT_MODEL.md for the threat model and docs/DECISIONS.md for the key design decisions.

Features

  • Numeric UINs, lookup-by-number, a buddy list, and ICQ-style presence/status.
  • End-to-end encryption with a Signal-style Double Ratchet (forward secrecy + post-compromise security).
  • Anti-MITM identity verification: trust-on-first-use pinning, loud key-change warnings, and human-comparable safety numbers.
  • Authorization requests (mutual consent) before any keys are exchanged.
  • P2P-first message delivery with an encrypted relay fallback (ciphertext only) and offline store-and-forward.
  • P2P-only file transfer, AEAD-chunked and order-bound, written to a quarantined folder.
  • At-rest key encryption with Argon2id — a stolen, locked device yields no usable keys.
  • A friendly tkinter GUI and a fully-functional text UI for headless use.

The five cryptographic relationships

Numyn keeps five independent key relationships strictly separated:

# Relationship Module
1 Client ↔ Account (login auth) numyn.crypto.login
2 Per-contact pairwise keys (message E2E) numyn.crypto.handshake + session
3 Server ↔ Client transport (pinned) numyn.crypto.transport
4 File-transfer encryption (derived from #2) numyn.crypto.filecrypto
5 At-rest keystore (Argon2id) numyn.crypto.keystore

Cryptography

Only vetted primitives from maintained libraries (cryptography, argon2-cffi) — no hand-rolled crypto, no gpg shell-out, no OpenPGP packet parsing: Ed25519 (signing), X25519 (key agreement), ChaCha20-Poly1305 (AEAD), HKDF-SHA-256 (domain-separated subkeys), Argon2id (passphrase KDF), SHA-256 (fingerprints/safety numbers). All randomness is from the OS CSPRNG; all secret comparisons are constant-time.

Install

Requires Python 3.11+ (developed/tested on 3.11 and 3.12, Linux/macOS).

python -m venv .venv
source .venv/bin/activate

# Reproducible, hash-locked runtime install:
pip install --require-hashes -r requirements.lock

# Then install the package (and dev tools for tests/lint):
pip install -e ".[dev]"

Run

1. Start the server (it prints the fingerprint clients must pin):

python -m numyn.server --host 0.0.0.0 --port 8765
# ...
#   identity fingerprint (clients pin this): 9ce7 9c0c 4c4d ...

To encrypt the server's identity key at rest, set NUMYN_SERVER_KEY_PASSPHRASE.

2. Start the client (GUI):

python -m numyn.client

In the GUI: open ⚙ Server Settings, enter the server host/port and the pinned fingerprint (obtained out of band), then Create a New UIN or Sign In.

Text UI (headless):

python -m numyn.client --cli --host <server> --port 8765 --fingerprint <hex>

Quickstart (two users)

  1. Both users register (each gets a UIN like 100000).
  2. Alice clicks ➕ Add a Buddy, enters Bob's UIN → Bob gets an authorization request.
  3. Bob accepts → a secure session is established and a chat window opens.
  4. (Recommended) Click 🔐 Verify Safety Number and compare the 60 digits out of band.
  5. Chat, and send files with 📎 Send File (P2P only).

Develop / test

pytest -q                               # full suite (unit + integration + adversarial + guardrails)
pytest tests/test_adversarial.py -q     # the CRITERIA §4 adversarial suite
pytest tests/test_adversarial.py::test_replay_rejected   # a single test
ruff check src/ tests/ scripts/         # lint
ruff format src/                        # format
python scripts/secret_scan.py           # secret-scanner gate
python scripts/demo_success_criteria.py # reproduce S1–S5

What is not hidden (read this)

Numyn protects message content and authenticity, not all metadata. The server still learns the social graph, presence, online times, IP addresses, and message timing/approximate size. Direct P2P reveals your IP to your contact (use relay-only mode to avoid this). An unlocked, compromised device exposes that account. See docs/PRIVACY.md and docs/THREAT_MODEL.md — we state the limits honestly.

License & security

Licensed under the MIT License — © g023 (github.com/g023). To report a vulnerability, see SECURITY.md. Design decisions for the v1 open questions are recorded in docs/DECISIONS.md.


Built by g023 · You're just a number. Keep it that way.

About

ICQ-style, end-to-end encrypted, server-distrusting messenger in pure Python. You're just a number — keep it that way. (WIP)

Topics

Resources

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages