No description
  • JavaScript 45.2%
  • HTML 33.7%
  • Python 19.7%
  • CSS 1.3%
  • Shell 0.1%
Find a file
2026-07-26 14:41:40 +02:00
deploy Deploy: docker run statt compose (Subnet-Pool), run.sh, Pi-hole/NPM-Anleitung 2026-07-25 12:05:18 +02:00
docs Konzept-Artifacts als Markdown ins Repo gesichert (docs/artifacts/) 2026-07-26 14:35:02 +02:00
gemale Nachrichtentypen ressourcen-zentriert (hilfe/gefahr/sicher/personen/verletzte/wasser/nahrung/medizin/werkzeuge/energie/kommunikation/transport/unterkunft/treffpunkt/auftrag/handel). Konvention: Ressource=Angebot/Fund, Bedarf via hilfe. Fail-Safe-Rundruf nur gefahr. Codebuch RE-FROZEN als v1 (Hash 2f8e7549…, noch keine echten Bilder). Vektoren+Einzeldatei neu, Tests grün. SW v24 2026-07-25 22:19:38 +02:00
lexicon Nachrichtentypen ressourcen-zentriert (hilfe/gefahr/sicher/personen/verletzte/wasser/nahrung/medizin/werkzeuge/energie/kommunikation/transport/unterkunft/treffpunkt/auftrag/handel). Konvention: Ressource=Angebot/Fund, Bedarf via hilfe. Fail-Safe-Rundruf nur gefahr. Codebuch RE-FROZEN als v1 (Hash 2f8e7549…, noch keine echten Bilder). Vektoren+Einzeldatei neu, Tests grün. SW v24 2026-07-25 22:19:38 +02:00
tests Nachrichtentypen ressourcen-zentriert (hilfe/gefahr/sicher/personen/verletzte/wasser/nahrung/medizin/werkzeuge/energie/kommunikation/transport/unterkunft/treffpunkt/auftrag/handel). Konvention: Ressource=Angebot/Fund, Bedarf via hilfe. Fail-Safe-Rundruf nur gefahr. Codebuch RE-FROZEN als v1 (Hash 2f8e7549…, noch keine echten Bilder). Vektoren+Einzeldatei neu, Tests grün. SW v24 2026-07-25 22:19:38 +02:00
tools Abmelden: Panik-Knopf (🔒 Abmelden, nur angemeldet sichtbar, oben rechts) — ein Tipp, sofort abgemeldet + Mal-Fassade, keine Rückfrage. Plus Inaktivitäts-Timeout (3 Min ohne Berührung → auto-abmelden, jede Eingabe setzt zurück), zusätzlich zur bestehenden Hintergrund-Sperre. Hinweis im Sicherheit-Reiter. SW v39 2026-07-26 14:17:59 +02:00
webapp Abmelden: Panik-Knopf (🔒 Abmelden, nur angemeldet sichtbar, oben rechts) — ein Tipp, sofort abgemeldet + Mal-Fassade, keine Rückfrage. Plus Inaktivitäts-Timeout (3 Min ohne Berührung → auto-abmelden, jede Eingabe setzt zurück), zusätzlich zur bestehenden Hintergrund-Sperre. Hinweis im Sicherheit-Reiter. SW v39 2026-07-26 14:17:59 +02:00
.gitignore Geheimskizze (gemale): CLI + PWA — 6 Szenen, Hybrid-Container, Huffman, Emoji-Codebuch, Cross-Language-Interop 2026-07-25 11:52:24 +02:00
config.example.json Geheimskizze (gemale): CLI + PWA — 6 Szenen, Hybrid-Container, Huffman, Emoji-Codebuch, Cross-Language-Interop 2026-07-25 11:52:24 +02:00
README.md README: aktueller Stand — Webapp live auf gemale.de (Tresor, QR-Kamera, Mal-Fassade, Panik-Knopf), Doku-Abschnitt mit Links auf docs/artifacts/ und v2-Krypto-Plan, Phase-0/Papiertest-Verweise verlinkt 2026-07-26 14:41:40 +02:00

Gemale — CLI-Referenz (Python)

Verschlüsselte Kurzbotschaften, versteckt in einer harmlosen Handzeichnung, gelesen über einen reinen Text-Dialog. Ohne Netz, ohne Strom, ohne vorausgesetztes Gerät. Dieses Repo ist der Kommandozeilen-Prototyp aus Phase 2 des Projekts (siehe Phase-0-Spezifikation und Papiertest, Phase 1).

Der Mensch ist der Codec: Er setzt eine Textanleitung in eine Skizze um und liest eine Skizze über einen Fragebogen zurück. Die App macht nur Krypto, Codebuch und Fehlerkorrektur — keine Bildverarbeitung, keine Kamera.

Es gibt zwei Umsetzungen, die byte-genau kompatibel sind (Cross-Language-Interop geprüft): dieses CLI (Python) und die PWA unter webapp/ (JavaScript). Eine auf dem Handy gezeichnete Nachricht liest das CLI und umgekehrt.

Die PWA läuft live auf gemale.de — offline-fähig, installierbar, ganz ohne externe Abhängigkeiten. Sie kann über das CLI hinaus: passwortgeschützter Schlüssel-Tresor (PBKDF2 → AES-GCM), QR-Schlüsseltausch mit In-App-Kamera für den Austausch im Funkloch, sowie eine Mal-Fassade als Tarnung (ohne Anmeldung zeigt die App nur eine funktionierende Zeichenfläche; die echten Reiter erscheinen erst nach einer vereinbarten Geste + Passphrase). Ein Panik-Knopf und ein Inaktivitäts-Timeout sperren den Tresor sofort bzw. automatisch.

Schnellstart

cd gemale
python3 -m gemale demo --scene zug   # Vorführung mit einer Szene
python3 -m gemale info --scene unterwasser

Kompaktformat (1 Bild) mit Schlüssel:

python3 -m gemale genkey --out key.hex

# Senden: Botschaft -> Zeichenanleitung (die man dann abzeichnet)
python3 -m gemale encode --scene haus --typ treffen --stunde 18 \
    --ort 3 --ttl 7 --key key.hex

# Lesen: Fragebogen zur fremden Skizze -> Botschaft
python3 -m gemale decode --scene haus --key key.hex

Die strukturierte Botschaft hat vier Felder:

Feld Werte
--typ eine von 16 Arten: treffen, status_ok, hilfe, warnung, ressource, komme, bleib_weg, freitext, entwarnung, sammeln, evakuieren, angriff, verletzte, nachschub, position, abbruch
--stunde 023
--ort 07 (acht vereinbarte Orte pro Gruppe)
--ttl Gültigkeit in Tagen: 1, 2, 3, 5, 7, 14, 30 oder 0 = unbegrenzt (Hinterlassenschaft)

Sechs Szenen: haus, unterwasser, zug, familie, bauernhof, geburtstag. decode ohne --answers fragt interaktiv; encode --json gibt die Kanalwerte aus.

Freitext über mehrere Bilder (Hybrid-Container)

Bis zu 3 Bilder als ein Paket: strukturierter Kopf plus Freitext aus dem geteilten Codebuch (Wörter, Phrasen, Emojis), Huffman-komprimiert.

# 3 Bilder tragen die Botschaft + mehrere Wörter
python3 -m gemale text-encode --scenes haus,unterwasser,zug \
    --typ treffen --stunde 18 --ort 3 --ttl 7 --words "bringt wasser mit" --key key.hex

# Lesen: je Bild ein Fragebogen
python3 -m gemale text-decode --scenes haus,unterwasser,zug --key key.hex

Alles ist ein Parameter

Der Kern des Designs: Was der Papiertest (Phase 1) verändern könnte, ist eine Stellschraube in der Konfiguration — ohne Code anzufassen. Voreinstellung in gemale/config.py (DEFAULT), Überschreiben per JSON:

python3 -m gemale info   --config config.example.json
python3 -m gemale encode --config config.example.json --key key.hex --typ warnung

Eine Override-Datei muss nicht vollständig sein: Jeder Top-Level-Block, den sie setzt (codebook, channels, ecc), ersetzt genau diesen Block; der Rest bleibt Voreinstellung. config.example.json zeigt typische Anpassungen nach einem Papiertest (wackelige Zählkanäle verkleinert, ein Kanal abgeschaltet, Kapazität am Codebuch ausgeglichen).

Wichtigste Stellschrauben:

Parameter Wirkung
channels[].range / .states Wertebereich eines Kanals — verkleinern, wenn er im Papiertest Fehler macht
channels[].enabled Kanal ganz abschalten, ohne ihn zu löschen
codebook.mac_bits Fälschungsschutz gegen Kapazität — der wichtigste Kompromiss
codebook.fields_secret Felder der Botschaft (Bitbreite oder benannte Werteliste)
codebook.fields_cleartext[counter].bits Wie viele Botschaften vor Nonce-Wiederholung (PSK)
ecc.scheme none (nur Erkennung) oder rs (Reed-Solomon, kostet Kapazität)

info rechnet nach jeder Änderung sofort vor, ob Nutzlast in die Kanäle passt (Reserve … [OK] / [ZU KLEIN!]), und encode bricht mit klarer Meldung ab, wenn nicht.

Architektur (Schichten der Spezifikation)

Botschaft ─► codebook ─► aead (Verschlüsseln + MAC) ─► [gf_rs] ─► channels ─► scene
  dict         int          Kopf + Ciphertext + Tag      optional   Mixed-Radix   Text
Datei Schicht
config.py alle Parameter + Kapazitätsrechnung
codebook.py Botschaft ↔ Integer (Klartext-Kopf / geheime Nutzlast getrennt)
aead.py Verschlüsselung + Echtheitsprüfung (Encrypt-then-MAC)
gf_rs.py Reed-Solomon über GF(256), optional
pipeline.py Mixed-Radix Kanalwerte + encode / decode / selfcheck
container.py Mehrbild-Hybrid: strukturierter Kopf + Huffman-Freitext
huffman.py deterministische Huffman-Codes fürs Freitext-Codebuch
vocab.py geteiltes Codebuch (Wörter/Phrasen/Emojis) — generiert aus lexicon/lexicon.json
scenes/*.py die austauschbaren Motive: Kanalwerte ↔ Anleitung/Fragebogen
cli.py Kommandozeile

config.py + codebook.py + aead.py + pipeline.py sind der szenen­unabhängige Kern; scenes/*.py sind die austauschbaren Häute. Eine weitere Szene ist eine Parallel-Datei unter scenes/ mit eigenem Kanalsatz. Das Freitext-Codebuch entsteht aus lexicon/lexicon.json über node tools/gen_lexicon.mjs (erzeugt vocab.py + webapp/js/vocab.js byte-gleich).

Zwei ehrliche Befunde aus dem Bauen

  1. Kapazität ist knapp. Eine einzelne unverdächtige Zeichnung trägt real nur ~50 Bit (nach der Merkmals-Erweiterung; die schlanken Ur-Szenen hatten ~3036). Davon nutzt das Kompaktformat 33 Bit Nutzlast mit einer 12-Bit-MAC (1/4096 Fälschungschance pro handgemaltem Versuch — jeder wird zusätzlich von einem Menschen geprüft). Der Mehrbild-Container hat einen eigenen 16-Bit-MAC und trägt im Freitext ~12 Wörter. Mehr MAC/Felder brauchen mehr Kanäle oder mehr Bilder.

  2. Byte-Reed-Solomon ist hier teuer. Jedes Paritäts-Byte kostet 8 Bit Kapazität — für ein einzelnes Bild schnell zu viel. Voreinstellung ist deshalb ecc: none: Fehler werden über die MAC erkannt und über den Selbstcheck (Absender liest die eigene Skizze zurück, bevor er sie hinterlässt) abgefangen, statt sie vorwärts zu korrigieren. RS ist voll implementiert und getestet und lohnt bei kapazitätsstarken Profilen oder Mehrbild-Botschaften.

Krypto-Hinweis

aead.py setzt bekannte Standard-Bausteine der Python-Standardbibliothek zusammen (SHA-256-Schlüsselstrom + HMAC-SHA-256, Encrypt-then-MAC) — abhängigkeitsfrei und korrekt für den Prototyp, aber kein eigenes Krypto-Design. Für den echten Einsatz aead.py durch libsodium (PyNaCl, XChaCha20-Poly1305) ersetzen; die Schnittstelle seal_bits/open_bits bleibt gleich. Rein symmetrisch, Schlüssel persönlich getauscht — quantenresistent, kein angreifbarer Public-Key-Handshake.

Dokumentation

Die eingefrorenen Konzept- und Protokoll-Dokumente liegen unter docs/. Die Dateien in docs/artifacts/ sind die Repo-Sicherung früherer Online-Konzeptseiten — nichts davon liegt noch außerhalb dieses Repos oder gemale.de.

Dokument Inhalt
Phase-0-Spezifikation Konzept eingefroren: Prinzipien, Schichtarchitektur, Codebuch v1, Sicherheitsmodell, Kanäle, Phasenplan
Papiertest (Phase 1) Analoges Testkit: Würfeltabelle, Testkarten, Fragebogen, Go/No-Go
Protokoll-Spezifikation v0.1 Gruppen, Schlüssel & Zeit: Blom-Mesh, Rundruf-Fail-Safe, Epochen/TTL, App-Verteilung
Kritzel-16 — Glyphen-Alphabet Frühes Formatkonzept: 16-Glyphen-Alphabet + Motiv-Modus, Kanal-Katalog
Kurzanleitung für Eingeweihte Bedien-Kurzanleitung (identisch zum in-App-Hilfe-Reiter)
Krypto-Härtung (v2-Plan) Ehrliche Schwächen-Bewertung + Härtungs-Tracks (A AEAD, B Tresor, C offen)

Tests

python3 -m unittest discover -s tests -v

Deckt ab: Rundlauf über 400 Zufallsbotschaften, Makro-Variation (gleiche Botschaft → verschiedene Bilder), Ablehnung bei falschem Schlüssel und bei Verfälschung, Reed-Solomon-Korrektur, und dass der Kapazitäts-Wächter anschlägt.