fognode - headless secure encrypted data transmission. TLS + X25519 + AESGCM + PBKDF2.
Project description
fognode
headless secure encrypted data transmission
Peer-to-peer encrypted channel library for headless projects. Built for speed and zero-trust networking.
Security Stack
| Layer | Technology |
|---|---|
| Transport | TLS 1.2+ with self-signed RSA-4096 certs |
| Key Exchange | X25519 ephemeral ECDH |
| Session Keys | HKDF-SHA256 |
| Channel Cipher | mini-MTProto (AES-256-IGE + SHA-256 msg_key) |
| Password Derivation | PBKDF2-HMAC-SHA256 (390k iterations) |
| Auth Challenge | HMAC-SHA256 over random nonce |
| Cert Pinning | SHA-256 fingerprint verification |
How connection works
Install
pip install fognode
Quick Start
Server
from fognode import Server, MessageEvent, ConnectEvent, DisconnectEvent
server = Server(host="0.0.0.0", port=9443, password="secret")
@server.on_event(MessageEvent)
async def on_message(ctx):
if ctx.event.text:
await ctx.answer(f"echo: {ctx.event.text}")
@server.on_event(ConnectEvent)
async def on_connect(ctx):
print("+ peer connected")
@server.on_event(DisconnectEvent)
async def on_disconnect(ctx):
print("- peer disconnected")
if __name__ == "__main__":
server.run()
Client
from fognode import Client, MessageEvent, ClosedEvent, ErrorEvent
client = Client(connect_string="7sf9Tn:9443", password="secret")
@client.on_event(MessageEvent)
async def on_message(ctx):
print(f"msg: {ctx.event.text}")
@client.on_event(ClosedEvent)
async def on_closed(ctx):
print("connection closed")
@client.on_event(ErrorEvent)
async def on_error(ctx):
print(f"error: {ctx.event.exception}")
if __name__ == "__main__":
client.connect()
Classic API
from fognode import start_server, client_connect
ip, code, fp = start_server("0.0.0.0", 9443, "secret")
print(f"Server running at {code}:9443") # e.g. 7sf9Tn:9443
Events
| Event | Server | Client | Description |
|---|---|---|---|
StartEvent |
yes | yes | Server/client started |
ConnectEvent |
yes | yes | Peer connected |
DisconnectEvent |
yes | yes | Peer disconnected |
MessageEvent |
yes | yes | Message received (type, text, ts) |
ClosedEvent |
no | yes | Connection closed |
ErrorEvent |
no | yes | Error occurred (exception) |
Decorators
# Specific event
@server.on_event(MessageEvent)
async def handler(ctx):
pass
# Aliases
@server.on_connect()
@server.on_disconnect()
@server.on_message()
@client.on_closed()
@client.on_error()
How mini-MTProto Works
Each message is encrypted independently using a simplified MTProto 2.0 scheme:
- Serialize JSON payload to bytes
- Pad to AES block size (16 bytes)
- Compute msg_key =
SHA-256(padded)[8:24](128 bits) - Derive AES key =
SHA-256(auth_key + msg_key) - Derive AES IV =
SHA-256(msg_key + auth_key) - Encrypt with AES-256-IGE
- Send
length(4 bytes) + msg_key(16 bytes) + ciphertext
Decryption reverses the process and verifies msg_key integrity.
CLI
# Run server
fognode server --host 0.0.0.0 --port 9443 --password secret
# Interactive client
fognode client 7sf9Tn:9443 --password secret
# Probe TLS fingerprint (no auth)
fognode probe 7sf9Tn:9443
# Server status via authenticated channel
fognode status 7sf9Tn:9443 --password secret
# Send one message and exit
fognode send 7sf9Tn:9443 --password secret --text "hello"
# Monitor messages only
fognode monitor 7sf9Tn:9443 --password secret
# Show certificate info
fognode cert --file fognode_cert.pem
Project Structure
src/fognode/
├── app.py # Server, Client, Context
├── cipher.py # mini-MTProto AES-256-IGE encrypt/decrypt
├── cli/
│ └── entrypoint.py # argparse CLI
├── core/
│ ├── client.py # client_connect()
│ ├── events.py # Event classes
│ ├── probe.py # probe_server()
│ └── server.py # start_server()
├── crypto/
│ ├── cert.py # Self-signed cert generation
│ ├── channel.py # SecureChannel (mini-MTProto)
│ ├── kdf.py # Session key helpers
│ ├── kx.py # X25519 keypair + shared secret
│ ├── password.py # PBKDF2 password store
│ └── primitives.py # pbkdf2, hmac256, hkdf_expand
├── filters/ # BaseFilter, Command, Text
├── handlers/ # HandlerObject
├── types/ # constants, exceptions, protocol
├── utils/ # ipwords, ratelimit, net
└── wire/ # Length-prefixed JSON framing
MIT © reekeer
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file fognode-0.3.0.tar.gz.
File metadata
- Download URL: fognode-0.3.0.tar.gz
- Upload date:
- Size: 36.8 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
4e8c7163edd0e002c4f6f236e36a46f80111ed4194fa18e3f369e4c44f12ad8a
|
|
| MD5 |
8f2d62845e9625bfef9a4db904a575fe
|
|
| BLAKE2b-256 |
57ed1cb8a46582f5718e4015cc73325cb7da4f7db0b5c1bf08a92584b29443fe
|
File details
Details for the file fognode-0.3.0-py3-none-any.whl.
File metadata
- Download URL: fognode-0.3.0-py3-none-any.whl
- Upload date:
- Size: 33.8 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
78a827a19d2d06732ff342d08b731daad7428689b6abd0e11fac5213d95e5b55
|
|
| MD5 |
c70a7424b43671aa2e2228f4ca9d199c
|
|
| BLAKE2b-256 |
bda7b81fbab4f5c569aea89852e59c17e21a58555da5f358d73705d87f0859d5
|