Technische Dokumentation für Sicherheitsforschende, IT-Verantwortliche und Kundinnen, die genau wissen wollen, was wie und warum verschlüsselt wird.
Revier3D verschlüsselt alle Jagddaten clientseitig, bevor sie den Server erreichen. Der Server ist ein dummer, verschlüsselter Speicher: er sieht nur Chiffretext und kann ihn nicht entschlüsseln. Er weiß nicht, wo deine Grenze liegt, und nicht, was du erlegt hast.
Jedes Revier, das über den Einrichtungsassistenten entsteht, ist ab der Anlage-Sekunde versiegelt: Schlüsselmaterial und Revierzeile entstehen in einem einzigen Schreibvorgang, es gibt also kein Fenster „Revier existiert schon, Schlüssel noch nicht". Das Revier-Passwort ist dort Pflicht, und es ist zugleich das Verschlüsselungspasswort; der Server verweigert es, daneben ein abweichendes zweites zu etablieren.
Architektur: Row-Level-Verschlüsselung statt einer _enc-Spalte je Feld. Jede Zeile wird als ein verschlüsselter JSON-Blob (data_enc) gespeichert. Im Klartext bleiben nur die Spalten, die der Server für Sync, Mandantentrennung und Fremdschlüssel braucht: id, revier_id, die *_id-Bezüge, created_at, updated_at, deleted_at, created_by. Alle Inhalte (Koordinaten, Wildart, Datum, Name, Notiz und so weiter) liegen im Blob.
Der Revier-Schlüssel (RK) wird einmalig beim Anlegen als 256-Bit-Zufall erzeugt und nicht aus dem Passwort abgeleitet, sondern mit einem aus dem Passwort erzeugten Schlüssel (KEK) verpackt. Das ist die Voraussetzung dafür, dass ein Passwortwechsel die Daten nicht unlesbar macht. Der Wechsel selbst ist noch nicht gebaut und wird derzeit mit 409 abgewiesen, siehe Abschnitt 7.
Was der Server am Ende noch weiß: Account-E-Mail (Login), Paddle-Zahlungsdaten (Billing), Revier-Slug (URL), Revier-Status (Zugangskontrolle), Mitgliedschaften (wer mit welcher Rolle), Speichermenge (Quota). Keine Jagddaten, nicht einmal die Position. 3D-Gelände, Luftbild-Vorrat und Grenzdatei folgen einem zweiten Weg (Abschnitt 5.3), weil sie auf dem Server entstehen und nicht auf dem Gerät.
Es gibt keinen Betreiber-Notschlüssel und keine Hintertür, auch nicht während der Beta. In der Datenbank existiert keine Spalte für eine zweite, betreibereigene Verpackung des RK; sie war geplant und wurde am 09.08.2026 ausdrücklich verworfen (Abschnitt 6).
hash-wasmp=4 bringt im einfädigen WASM heute nichts und kostet nichts; es steht für einen künftigen Thread-fähigen Bau.revier.kek_salt)revier.kek_params im Datensatz mit und werden über /api/r/<slug>/info ausgeliefert. Sie hart zu verdrahten hieße, dass ein späterer Wechsel jedes bestehende rk_wrapped unauspackbar macht.Das Passwort verlässt den Client nicht mehr. Bis zur Verschlüsselung ging es bei /api/login/shared im Klartext an den Server, der damit selbst den KEK hätte ableiten und rk_wrapped auspacken können. Deshalb liefert ein einziger Argon2id-Lauf 64 Byte, die HKDF-SHA256 mit verschiedenen Etiketten in zwei Schlüssel spaltet: KEK bleibt im Gerät und packt den RK aus, AUTH geht zum Server, der davon nur einen Passwort-Hash hält. Aus AUTH lässt sich KEK nicht zurückrechnen. Ein zweiter Argon2id-Lauf wäre eine zweite Sekunde Wartezeit am Handy ohne Sicherheitsgewinn.
Warum nicht PBKDF2 oder scrypt? PBKDF2 ist GPU- und ASIC-freundlich und damit für passwortbasierte Schlüssel heute unterlegen. scrypt ist eine starke Alternative, Argon2id ist jedoch der Gewinner der Password Hashing Competition 2015 und hat eine breitere Bibliotheksunterstützung. Der hybride Modus (id) schützt sowohl gegen Seitenkanäle (vorne memory-hard) als auch gegen GPU-Cracking (hinten time-hard).
Bewusst speicherhungrig. 64 MiB je Versuch machen Massen-Cracking auf GPUs unrentabel. Auf dem Endgerät eines Nutzers sind 64 MiB eine vernachlässigbare Last, für einen Angreifer mit Millionen Versuchen eine mengenbegrenzende Barriere. Serverseitig kommt eine schlichte Bremse dazu: zehn Versuche je Verbindung in zehn Minuten, danach 429.
draft-irtf-cfrg-xchacha über ChaCha20-Poly1305 aus RFC 8439@noble/ciphers; Server cryptography (ChaCha20-Poly1305, X25519, HKDF) plus rund 30 selbst geschriebene Zeilen HChaCha20, gegen den Testvektor des Entwurfs geprüftWarum XChaCha20 und nicht AES-256-GCM (NIST SP 800-38D)? Der 192-Bit-Nonce erlaubt zufällige Nonces ohne Buchhaltung. Bei AES-GCM sind es 96 Bit, und ein Zähler müsste über alle Geräte hinweg eindeutig bleiben: Vier Freunde, die dasselbe Revier offline bearbeiten und später nachsenden, bekommen das nicht sicher hin, und eine Nonce-Wiederholung kostet bei GCM nicht nur die Vertraulichkeit der beiden Nachrichten, sondern den Authentisierungsschlüssel. Dazu kommt: ChaCha20 ist reine Ganzzahl-Arithmetik, braucht kein AES-NI, ist auf dem fünf Jahre alten Android im Revier schneller als AES und hat keine Tabellen-Seitenkanäle.
Der Preis dieser Wahl steht in Abschnitt 2.2: WebCrypto kennt XChaCha20 nicht, also entfällt der nicht auslesbare Schlüssel-Handle, den crypto.subtle für AES-GCM anbieten würde. Wir halten die Nonce-Sicherheit über Gerätegrenzen hinweg für das schwerere Argument, benennen den Verlust aber, statt ihn zu verschweigen.
Wozu der Pflicht-Kontext gut ist. Das Datenmodell ist Row-Level: eine ganze Zeile liegt als ein Blob in data_enc. Ohne mitauthentisierten Kontext könnte, wer die Datenbank hat, Blobs vertauschen, den Blob von Marker 7 nach Marker 9 schreiben oder eine Zeile aus strecke nach ansitz, und der Client entschlüsselte sie klaglos: Die Verschlüsselung wäre intakt und die Daten trotzdem falsch. Was der Kontext nicht abwehrt, ist das Weglassen oder Doppeln ganzer Zeilen und das Zurückspielen eines älteren Blobs derselben Zeile. Dagegen hilft erst ein Versionsvektor, und der ist nicht gebaut.
revier.pubkey und kann es danach selbst nicht mehr öffnen. (2) Bau-Artefakte: Gelände, Luftbild und Kachel-Vorrat versiegelt der Server nach dem Bau selbst, weil der Weg über den Client 150 MB hin und zurück wären.revier.pubkey liegt offen auf dem Server, der private Teil daneben als revier_priv_enc, verschlüsselt mit dem RK. Jeder Client mit RK packt ihn aus, der Server nie.Was das nicht leistet: Es ist keine Absender-Authentisierung. Wer den öffentlichen Schlüssel des Reviers hat, und der liegt offen, kann etwas hineinlegen. Für den Kamera-Eingang ist genau das die Anforderung, denn der Server soll es können. Wer Herkunft beweisen muss, braucht eine Signatur.
Warum X25519 und nicht ECDH P-256? P-256 (FIPS 186-4) wäre der Weg gewesen, um über crypto.subtle einen nicht auslesbaren privaten Schlüssel zu bekommen. Nachdem die symmetrische Seite (Abschnitt 3.2) diesen Vorteil ohnehin nicht nutzen kann, wiegt er hier nicht mehr auf: Curve25519 hat die einfacheren Implementierungen, keine Parameterwahl, die man falsch treffen kann, und die kürzeren Schlüssel. Beide Seiten, Browser und Python-Server, benutzen dieselbe Bauform.
info-Etiketten, damit die eine Hälfte die andere nicht verrät. (2) Aus dem X25519-Ergebnis den eigentlichen Schachtel-Schlüssel ableiten und ihn an dieses eine Schlüsselpaar binden.RK_data / RK_cam / RK_meta aus dem RK. Eine frühere Fassung dieses Dokuments nannte sie; heute verschlüsselt der RK die Zeilen direkt, und die Trennung leistet der Pflicht-Kontext aus 3.2.# Einmalig beim Anlegen des Reviers erzeugt, im selben Schreibvorgang wie die # Revierzeile (kein Fenster "Revier da, Schlüssel noch nicht"): RK = random(256 bit) # Revier-Schlüssel, EINMAL erzeugt, danach konstant # Ein Argon2id-Lauf, zwei Schlüssel. Das Passwort selbst geht nirgends hin. roh = Argon2id(revier_passwort, revier.kek_salt, m=64 MiB, t=3, p=4) # 64 Byte KEK = HKDF(roh, info="kek") # bleibt im Gerät AUTH = HKDF(roh, info="auth") # geht zum Server, der nur hash(AUTH) hält # Verpackung 1: Revier-Passwort (vier Freunde teilen Link + Passwort) revier.rk_wrapped = XChaCha20-Poly1305(Enc, RK, KEK) # Verpackung 2 (optional): je Konto, mit dessen öffentlichem Schlüssel membership.wrapped_rk = X25519-Seal(RK, konto_pubkey) # Verpackung 3 (optional): 12 Wiederherstellungs-Wörter, BIP39-Konstruktion woerter = 12 aus 2048 # 128 Bit Zufall + 4 Bit Prüfsumme recovery_enc = Enc(RK, schluessel_aus_woertern) # Weg zurück zum RK recovery_woerter_enc = Enc(woerter, RK) # Weg zu den Wörtern # KEIN Betreiber-Notschlüssel. Keine Hintertür. Die Zusage gilt ab Tag 1, # und die Spalte dafür existiert im Schema nicht. # Daten-Verschlüsselung (je Zeile, Row-Level): aad = "revier3d.e2ee.v1|" + revier + "|" + tabelle + "|" + zeile + "|" + gen huelle = 0x01 || nonce(192 bit, zufällig) || XChaCha20-Poly1305(Enc, zeile_json, RK, aad) # Server-Eingang ohne offenen Client (Kamera, Bau-Artefakte): huelle = X25519-Seal(datei, revier.pubkey) # hineinlegen ja, öffnen nein
Die Trennung zwischen RK (konstant) und KEK (aus dem Passwort) löst das Hauptproblem einer ableitungsbasierten Architektur: Ein Passwortwechsel muss keine Daten kosten. Er bedeutet nur, dass die eine Verpackung rk_wrapped neu erzeugt wird, eine kleine Blob-Operation, und die verschlüsselten Daten bleiben unberührt. Gebaut ist dieser Wechsel noch nicht: Weil Revier-Passwort und Verschlüsselungspasswort dasselbe sind, muss er beides atomar umstellen, und bis dahin weist der Server einen Wechsel am verschlüsselten Revier mit 409 und einem Hinweistext ab, statt still den Zugang vom Schlüssel zu trennen.
rk_version trägt die Schlüsselgeneration und fährt im Kontext jeder Zeile mit. Sie steht heute überall auf 1: Einen Wechsel des RK mit anschließender Umschlüsselung des Bestands gibt es noch nicht. Erst er würde einen alten, eventuell abgeflossenen RK wertlos machen.
Verschlüsselt werden 26 Fachtabellen, darunter marker, foto, strecke, ansitz, wartung, schaden, belegung, buchung, sketch und sketch_stroke, kontrolle, nachsuche, fuetterung_log, zone, line, cam_bild. Jede davon bekommt eine Spalte:
data_enc: die ganze Zeile als ein verschlüsseltes JSON-Paket. Die bisherigen Fachspalten bleiben bestehen und tragen im versiegelten Revier neutrale Platzhalter (Koordinaten 0/0, Daten 1970-01-01, Beträge 0), damit Fremdschlüssel, Indizes und Prüfregeln der Datenbank weiter greifen.Im Klartext bleiben pro Zeile: id, revier_id, alle *_id-Bezüge, die Zeitstempel created_at / updated_at / deleted_at, created_by und einige Ordnungswerte, die der Server prüfen muss (Belegnummer und Belegjahr der Buchhaltung wegen des lückenlosen Nummernkreises nach § 131 BAO, Dateigröße und Dateityp der Fotos wegen des Speicherkontingents, Zeitstempel und Kamera-Kennung der Kamerabilder).
Am Revier selbst: kek_salt (128 Bit), kek_params, rk_wrapped, rk_version, pubkey (X25519, öffentlich), revier_priv_enc (privater Teil, mit RK verschlüsselt), recovery_enc und recovery_woerter_enc, e2ee_aktiv. Je Mitgliedschaft: wrapped_rk.
⚠️ Die Tabelle revier ist selbst keine zeilenverschlüsselte Tabelle. Sie hat kein data_enc, steht in keinem Räumfragment und wird von finalize nur mit SET e2ee_aktiv=TRUE berührt. Ihre fachlichen Spalten bleiben deshalb dauerhaft Klartext, darunter name, bundesland und land. Die vollständige Aufzählung samt Folgen steht in 5.3.
Die Route /foto/<id> liefert im versiegelten Revier Chiffretext aus, mit einem Kopfzeilen-Vermerk, welche der beiden Siegelarten anliegt. Ein Service Worker (sw.js) fängt die Anfrage ab, entschlüsselt clientseitig und liefert eine gewöhnliche Antwort zurück. Damit bleibt <img src="/foto/…"> im HTML unverändert, und Lazy-Loading, Caching und Speicherverwaltung des Browsers funktionieren weiter. Derselbe Worker rechnet im versiegelten Revier auch die Höhenkacheln der 2D-Schummerung aus der entschlüsselten Höhenkarte, weil der Server dafür weder eine fremde Quelle fragen noch die eigene Datei lesen darf.
Grenze, Geländemodell und Luftbild-Vorrat entstehen beim 3D-Bau auf dem Server, aus den amtlichen Quellen. Sie können deshalb nicht am Gerät verschlüsselt werden; der Server versiegelt sie selbst mit dem öffentlichen Revier-Schlüssel (3.3). Der Zeitpunkt ist ein Riegel und kein Zufall:
Der Ortsteil der Weltdatei wird beim Schließen abgetrennt und mitversiegelt. Es sind genau neun Felder: lat_c, lon_c, bbox3857, env_bbox3857, merc_edge, minH, maxH, env_minH, env_maxH. Der Rest bleibt lesbar, damit Vorrats-Zähler und Auslieferungs-Versionen weiterlaufen; edge_ground (Boden-Kantenlänge in Metern) gehört dazu und ist allein ortsfrei, weil die Rückrechnung auf den Breitengrad merc_edge braucht und das versiegelt ist.
Nicht gelöst und hier benannt, in der Reihenfolge ihrer Reichweite:
.enc an und benennt nichts um. Auf der Platte steht danach reviere/<rid>/tiles/<z>/<x>/<y>.jpg.enc: der Inhalt ist zu, der Pfad ist eine Web-Mercator-Kachelkoordinate. Aus Minimum und Maximum der Ordner- und Dateinamen fällt der Diorama-Ausschnitt heraus, bei z19 auf etwa 50 m genau, und er ist über den Ordner <rid> genau einem Revier zugeordnet. Zwei Umstände verschärfen das: der Vorrat enthält nach dem Schließen nur noch das Diorama-Fenster, weil _vorrat_im_fenster ohne bbox3857 konstant falsch liefert und nichts mehr dazugespiegelt wird, es gibt also kein Rauschen; und _e2ee_klartext_offen klassifiziert ausschließlich Datei-inhalte und sieht einen Verzeichnisnamen nie an. Ein Gegenmittel wäre ein Namens-HMAC über (z,x,y) mit dem Revierschlüssel; er müsste zeichengleich in _e2ee_datei_zeile, _vorrat_kachel und sw.js nachgezogen werden, und die AAD hängt heute an genau dieser Klartext-Kennung tiles/z/x/y. Solange das nicht gebaut ist, steht der Ort des 3D-Modells auf /sicherheit als benannte Ausnahme.dem, env_dem, ortho_quelle, quellen{} und veg_stichtag bleiben Klartext (etwa bev1m, at-basemap) und verraten damit das Land, in Deutschland über das Vermessungsamt auch das Bundesland.revier selbst. Die Tabelle revier ist keine der zeilenverschlüsselten Tabellen und wird vom Versiegelungslauf nicht angefasst: slug, name, bundesland, land, betriebsart sowie die Behördenstammdaten jab_anschrift, jab_bezirk, jab_bevollm_ort, jab_behoerde und jagdgebiets_nr bleiben lesbar. _bl_key liest bundesland ohne jede E2EE-Weiche.cam hat den Primärschlüssel (revier_id, slug); name wird auf '' geräumt, der slug bleibt als Zeilenkennung und als Ordnername auf der Platte stehen. Er ist der slugifizierte Kameraname, also Reviergeografie in Prosa.meldungs_empfaenger.bezeichnung steht nicht in E2EE_TABELLEN; ein Eintrag wie „Polizeiposten Pernitz" verrät die Region.Es gibt keinen Betreiber-Notschlüssel und keine Hintertür. Die Zusage „wir können nicht hineinsehen" gilt ab Tag 1, nicht erst nach einer Beta-Phase. Eine zweite, betreibereigene Verpackung des RK war im ersten Entwurf dieses Vorhabens vorgesehen und wurde am 09.08.2026 ausdrücklich verworfen; die Spalte dafür existiert im Schema nicht, und der Abschnitt des alten Plans steht dort nur noch als Chronik der verworfenen Variante.
Ehrlich zur Betreiber-Rolle: Ein Sitzungs-Zugang der Betreiberseite in ein fremdes Revier existiert weiterhin (Support-Zugang). Er verschafft eine Sitzung, keinen Schlüssel: Ohne Mitgliedschafts-Verpackung, ohne KEK und ohne Revier-Passwort liefert er in einem versiegelten Revier Chiffretext und Platzhalter. Das ist der Unterschied zwischen „darf zugreifen" und „kann lesen", und nur der zweite Teil ist hier durch Kryptographie und nicht durch eine Regel abgesichert.
Geplant, noch nicht gebaut: ein Knopf „Fehler melden mit Daten". Der Client packt dabei den kaputten Datensatz samt Umfeld, verschlüsselt ihn mit dem öffentlichen Betreiber-Schlüssel und lädt ihn hoch; lesen kann ihn dann nur der private Schlüssel auf dem Rechner des Betreibers, und zwar genau diesen einen Datensatz. Bis dahin läuft Fehlersuche über Beschreibung und Bildschirmfotos. Im ausgelieferten Code gibt es diesen Knopf heute nicht.
Eine Verschlüsselung, die alles verspricht, lügt. Folgende Daten bleiben Klartext, das Minimum, ohne das der Server nicht funktionieren kann:
Konkrete Folge: der Server weiß nicht, wo deine Grenze liegt, nicht wo ein Marker steht, nicht was du erlegt hast. Er weiß nur: „Konto #31 zahlt für Revier #71, das 2,3 GB belegt hat."
Weitere Grenzen, benannt statt weggelassen:
.enc, der Server kann sie nicht lesen und holt sich für das Rendern keinen Klartext zurück./api/cam/stats) braucht ihn trotzdem, seit dem 04.09.2026 als einzige Route. Der Client schickt ihn deshalb im Rumpf der Anfrage mit ({"e2ee_ort":{"lat":…,"lon":…}}, auf 0,01° gerundet, also rund einen Kilometer). Bewusst im Rumpf und nie als Query-Parameter: die Query stünde im Zugriffsprotokoll, und daraus ließen sich Mandant und Ort rekonstruieren. Unversiegelt nimmt der Server einen Rumpf-Ort gar nicht erst an. Abgelegt wird er nicht, weder in der Datenbank noch in einem Protokoll; im Arbeitsspeicher steht er als Schlüssel des Sonnenzeiten-Caches (je Tag und Ort, bis zum Neustart des Dienstes). Fehlt der Ort, benennt er den Zustand (ort_fehlt) und die ortsabhängigen Blöcke bleiben leer, statt für einen Ersatz-Standort gerechnet zu werden. Es ist dasselbe Fenster wie beim Bearbeiten der Grenze, kein zweites Zugeständnis. Was die Rundung leistet und was nicht: 0,01° ist bei 47,5° N ein Raster von 1.112 m Höhe und 753 m Breite, Zellfläche 0,84 km², maximaler Versatz zum echten Mittelpunkt 672 m. Es ist ein Raster-Snap, keine Verwischung: dasselbe Revier landet immer in derselben Zelle, Wiederholungen bringen keinen Zusatzgewinn und mitteln sich auch nicht heraus. Und sie ist keine Ortsverschleierung im Ruhezustand: die Pfade des Kachel-Vorrats (5.3) nennen denselben Ort dauerhaft und rund zwanzigmal genauer. Die Rundung begrenzt allein, was dieser Weg zusätzlich über die Leitung schickt. Ein Restpfad: zwischen finalize und dem Dateien-Schritt liegt world.json noch im Klartext mit lat_c; dann greift Zweig 1 von _revier_coords(), der Server rechnet die Sonnenzeiten mit dem echten Mittelpunkt, und der gerundete Rumpfwert wird durch das or gar nicht gelesen. An einen Fremddienst geht dieser Wert nicht mehr, seit der Browser das Wetter selbst holt.„Vertrau uns" reicht bei Verschlüsselung nicht. Vier Stufen, aufsteigend nach Überzeugungskraft:
Bewusst nicht: ein externes Audit (Cure53 und andere). Zu teuer für den jetzigen Stand, ohne zahlende Kunden auch nicht nötig. Kann später folgen und wird in diesem Whitepaper als „nicht erfolgt" ausgewiesen, nicht verschwiegen.
Marktrecherche August 2026, nachgemessen statt behauptet. Belege in PLAN-APP-SYNC-E2EE.md Teil A.
| Anbieter | Verschlüsselungszusage | Quelle |
|---|---|---|
| Revierwelt (Marktführer) | Keine E2EE-Zusage messbar. Apples Datenschutzangaben deklarieren Standort, Fotos, Identität, alle mit Nutzeridentität verknüpft. | App Store |
| Waidly | Gar keine Cloud, alles lokal am Gerät, keine Registrierung. 12,99 € einmalig. Dafür: kein Teilen, kein Backup, kein Web, kein 3D. | iphone-ticker |
| RevierBuch, JagdCom, Mein Revier | Allgemeine „Datensicherheit", keine E2EE-Zusage über TLS hinaus. | Anbieterseiten |
| Jagdgefährte | „Verschlüsselter Chat". Betrifft Kommunikation, nicht Revierdaten. | Store-Beschreibung |
| CoHunt (international) | E2EE für Peer-to-peer-Kommunikation (Mesh-Chat); Revierdaten werden nicht zentral gespeichert (kein Konto, kein Cloud-Bestand). Zusage betrifft Kommunikation, nicht cloudgespeicherte Revierdaten. | Anbieter-Datenschutzerklärung 03/2026 |
| HuntStand, onX Hunt (international) | Keine E2EE- oder Zero-Knowledge-Zusage auffindbar. | Marktübersichten 2026 |
| Signal, Matrix | E2EE für Kommunikation. Nicht auf Revierdaten und 3D-Karten ausgelegt. | Projektseiten |
Belastbare Fassung der Aussage: Es war keine cloudbasierte Revier-App auffindbar, die Ende-zu-Ende-Verschlüsselung für Revierdaten zusagt.
Revier3D positioniert sich damit zwischen Waidly (lokal, isoliert) und Revierwelt (Cloud, mitlesbar): privat wie eine Offline-App, aber trotzdem gemeinsam nutzbar, gesichert und von überall erreichbar.
Dieser Abschnitt prüft, ob die Vollverschlüsselung mit österreichischem Recht und der DSGVO vereinbar ist. Die Einschätzung beruht auf der Rechtslage Stand August 2026 und ersetzt keine anwaltliche Prüfung im Einzelfall.
Der Verfassungsgerichtshof (VfGH) hat die Vorratsdatenspeicherung 2014 als verfassungswidrig aufgehoben. Es gibt keine gesetzliche Pflicht für Web-Anwendungen, IP-Adressen zu speichern. Revier3D ist kein Telekommunikationsanbieter im Sinne des TKG. Die Nichtspeicherung von IP-Adressen ist nicht nur legal, sondern datenschutzrechtlich geboten (DSGVO Art. 5 Abs. 1 lit. c, Datenminimierung).
Bei einer konkreten Strafverfolgung (§ 76 StPO) kann die Behörde verlangen, was vorhanden ist. Ist nichts gespeichert, gibt es nichts herauszugeben. Man kann nicht verpflichtet werden, Daten zu speichern, die man nicht speichern will.
Der Nutzer hat Anspruch auf Auskunft über die Verarbeitung seiner Daten. Mit E2EE kann Revier3D Auskunft geben über Metadaten (Konto, E-Mail, Tarif, Speichermenge, Revier-ID). Die verschlüsselten Inhalte kann Revier3D nicht ausweisen, weil es sie nicht entschlüsseln kann. Der Nutzer kann die Inhalte selbst einsehen (er entschlüsselt lokal). Art. 15 ist erfüllt.
Der Nutzer kann seine Daten in einem strukturierten, gängigen Format exportieren. Der Browser entschlüsselt sie dafür lokal und schickt die entschlüsselten Zeilen für diese eine Anfrage an den Server, der die Datei setzt und nichts davon behält (Ausgabe-Fenster, Abschnitt 7). Die fertige Datei ist unverschlüsselt, weil sie beim Nutzer landet und dort weiterverarbeitet werden soll. Art. 20 ist erfüllt.
Die DSGVO fordert ausdrücklich Verschlüsselung als technische und organisatorische Maßnahme (Art. 32 Abs. 1 lit. a) und Privacy by Design (Art. 25). Vollständige E2EE übertrifft die Anforderungen. E2EE ist nicht nur legal, sondern datenschutzrechtlich das Optimum.
Der Nutzer hat eine gesetzliche 7-Jahres-Aufbewahrungspflicht für Buchhaltungsunterlagen. Mit E2EE sind Belege und Buchungen verschlüsselt. Bei Schlüsselverlust ohne Wiederherstellungscode sind diese Daten unwiderruflich verloren.
Dies ist die Pflicht des Nutzers, nicht die von Revier3D. Die AGB (§ 2.4) stellen ausdrücklich klar: „Die Verantwortung für die steuerliche Richtigkeit der Eintragungen und für die Einhaltung der Aufbewahrungspflichten (insbesondere § 132 BAO) liegt beim Kunden." E2EE ändert daran nichts, verschärft aber das Risiko bei Schlüsselverlust.
Revier3D mindert dieses Risiko durch: (1) die 12 Wiederherstellungs-Wörter bei der Einrichtung, jederzeit im Planer wieder ansehbar, (2) den Export als zusätzliche Sicherung außerhalb des Produkts, (3) den Buchhaltungs-Export, den die Revierleitung entschlüsselt zieht und an die Kanzlei weitergibt (Abschnitt 7).
Öffentliche Behörden können Daten beschlagnahmen (§ 76 StPO) oder Auskunft verlangen. Revier3D gibt heraus, was es hat: Kontometadaten und chiffrierte Datenblöcke. Die verschlüsselten Inhalte kann Revier3D nicht entschlüsseln und daher nicht ausweisen. Das ist mit ProtonMail (Schweiz) und Tutanota (Deutschland) vergleichbar, die beide legal in deutschsprachigen Rechtsräumen operieren.
Revier3D kann nicht ausschließen, dass künftig eine gesetzliche Verpflichtung zur Protokollierung von Verbindungsdaten (IP-Adressen) eingeführt wird. Eine solche Pflicht gälte aber für Metadaten, nicht für Jagddaten. Selbst dann blieben die verschlüsselten Inhalte unlesbar.
Es gibt keine österreichische Rechtsgrundlage, die einen Software-Anbieter zwingt, seine Verschlüsselung zu schwächen oder eine Hintertür einzubauen. Auf EU-Ebene wird die CSAR-Verordnung („Chat Control") diskutiert, die Scanning verschlüsselter Kommunikation vorsehen würde. Stand August 2026 ist sie nicht verabschiedet, richtet sich gegen Messenger und nicht gegen Nischen-SaaS. Mit offenem Code und reproduzierbarem Bau wäre ein heimlicher Backdoor nachweisbar.
@noble/ciphers (XChaCha20-Poly1305), @noble/curves (X25519), @noble/hashes (HKDF-SHA256), hash-wasm (Argon2id, WASM-basiert). Auf dem Server cryptography (ChaCha20-Poly1305, X25519, HKDF) plus rund 30 selbst geschriebene Zeilen HChaCha20, weil die Bibliothek die XChaCha20-Variante nicht mitbringt.revier3d/src/crypto/, ausgeliefert als webmap/static/revier-crypto.js; Server-Seite webmap/e2ee.py.webmap/PLAN-APP-SYNC-E2EE.md im Repository.