Technika

Jak to działa w szczegółach

Dla tych, którzy chcą wiedzieć dokładnie: formaty, parametry, konstrukcje — i miejsca, w których świadomie niczego nie obiecujemy.

1. Kontener

Plik sejfu to jawny, ale chroniony MAC-iem nagłówek i zaszyfrowany korpus. W nagłówku stoi wyłącznie to, co potrzebne do wyprowadzenia klucza: sól, parametry KDF i rodzaje czynników. Cała reszta — wpisy, notatki, zdjęcia oraz warunki dostępu — leży w korpusie.

Do wersji 3 współrzędne i data otwarcia stały w jawnym nagłówku. W aplikacji, której zadaniem jest ukryć, gdzie leżą kosztowności, był to produkt zdradzający własny przedmiot. Od wersji 4 są w korpusie, a konsekwencja jest zamierzona: warunki da się odczytać dopiero po odszyfrowaniu.

Plik zawsze zawiera dwa miejsca. Nigdy nieskonfigurowane drugie miejsce jest wypełniane danymi losowymi tej samej długości i nie da się go odróżnić od prawdziwego — z pliku nie wynika więc, czy drugi sejf istnieje.

ParametrWartość
version4
AEADAES-256-GCM
KDFArgon2id (libsodium), opsLimit 2, memLimit 64 MiB, p = 1
KDF (Altbestand)PBKDF2-HMAC-SHA256, 600 000
HKDFHKDF-SHA256, reine Dart-Implementierung
Slots2 (immer beide vorhanden)
Wraps je Slot2 — Faktorpfad, Notfallpfad

2. Od hasła do klucza

Z czynników Argon2id tworzy klucz bazowy. Argon2id jest twardy pamięciowo: 64 MiB na próbę uderza w napastnika ze sprzętem specjalnym znacznie mocniej niż same rundy obliczeń. Na urządzeniu z 2024 roku próba kosztuje około sekundy; PBKDF2 przy porównywalnie uczciwej liczbie rund mierzył od kilku do ponad dwudziestu sekund, bo Android nie oferuje dla niego ścieżki natywnej.

Klucz bazowy niczego nie odszyfrowuje wprost. Szyfrowanie idzie losowym kluczem korpusu, opakowanym dwukrotnie: raz ścieżką czynników, raz ścieżką awaryjną. Tam, gdzie ścieżka nie jest używana, stoi atrapa tej samej długości. Dwie konsekwencje: kosztowny Argon2id liczy się raz, niezależnie od liczby sprawdzanych pól, a nagłówek nie zdradza, jaki sejf trzymasz w ręku.

Pliki jako część klucza idą przez Shamira nad GF(28) z wielomianem Rijndaela 0x11B: albo wszystkie N w ustalonej kolejności, albo dowolne K z nich jako droga awaryjna.

3. Miejsce jako czynnik klucza

Miejsce nie jest pytaniem zadawanym przez aplikację, tylko częścią planu klucza. Pozycja jest kwantowana na siatkę, z pola liczony jest identyfikator, a ten identyfikator wchodzi jako sól do wyprowadzenia klucza ścieżki:

masterKey = HKDF(baseKey, salt = identyfikator pola)

Poza polem klucz zatem nie istnieje — nie ma czego obejść ani zmienioną aplikacją, ani podstawionym GPS-em. Sejf jest związany z dokładnie jednym polem; promień szukania mówi tylko, ile pól sąsiednich sprawdza klient, więc kosztuje czas, a nie bezpieczeństwo.

ParametrWartość
Raster50 m, metrisch quantisiert
ZellkennungSHA-256 über tva:geo:v1:…
AbleitungHKDF-SHA256, salt = Zellkennung
Suchradius150 / 300 / 600 / 1200 m
Kandidaten25 / 121 / 529 / 2209 Zellen
Kosten (razr 50 ultra)72 / 162 / 220 / 385 ms
Gespeichertnichts — weder Koordinaten noch Zelle noch Radius

4. Kapsuły czasowe

Kapsuła czasowa to implementacja beattime-seal-v1. Klucz notatki jest dzielony metodą Shamira; udziały beaconów szyfruje się szyfrowaniem opartym na tożsamości (Boneh–Franklin nad BLS12-381) na tożsamość wynikającą z chwili otwarcia. Odpowiadająca jej „prywatna” połowa to podpis, który beacon publikuje w tej chwili — wcześniej nie istnieje, także u operatora.

Arytmetyka par leży we własnej bibliotece w Ruście na ark-bls12-381. Popularna skrzynka tlock nie jest używana: ma zaszyte 16-bajtowe sigma, bo szyfruje wyłącznie klucze plików age. Referencja losuje sigma o długości wiadomości — przy 32 bajtach pieczętowanych tutaj obie dają różne szyfrogramy i żadna nie otworzy drugiej.

Przez granicę C nie jest alokowane nic, co ktoś musiałby zwolnić: oba wyniki mają długość policzalną z góry, bufor daje wołający, a każdy punkt wejścia przechwytuje paniki.

ParametrWartość
Formatbeattime-seal-v1
Hauptgeheimnis32 B, Shamir über GF(28), Polynom 0x11B
NutzlastAES-256-GCM-STREAM, Segment 65 536 B
NoncePräfix 7 B ‖ Zähler 4 B BE ‖ last 1 B
AADSHA-256 des kanonischen Kopfs
SchlüsselHKDF-SHA256, info = beattime-seal-v1|aead
IBEBoneh–Franklin über BLS12-381
Kurvenschemabls-unchained-g1-rfc9380
ChiffratU 96 B (G2) ‖ V 32 B ‖ W 32 B
Beaconsdrand quicknet + BeatTime-Schlüsselserver
Profilstandard — 2 von 3

5. Dowód czasu dla zdjęć

Zdjęciu zrobionemu w aplikacji można wystawić dowód istnienia. Przesyłana jest suma SHA-256, nigdy obraz. Serwis umieszcza wartość w liściu drzewa Merkle; po zamknięciu tygodnia korzeń podpisywany jest Ed25519. Aplikacja zapisuje sumę, czas, dowód inkluzji i podpis, a cały dowód przelicza offline: od zdjęcia do liścia, od liścia do korzenia, podpis wobec klucza publicznego.

To dowód skierowany wstecz — „to istniało już wtedy” — i dlatego wyraźnie nie jest zamkiem czasowym. Zamek czasowy wymaga kierunku przeciwnego i od tego są kapsuły.

6. Na czym to jest sprawdzone

Format, który rozmawia wyłącznie sam ze sobą, niczego nie dowodzi. Trzy sprawdzenia idą przeciwko cudzemu kodowi, po jednym na warstwę:

Do tego testy na prawdziwym sprzęcie: że biblioteka arm64 ładuje się w pakiecie, że kapsuła z miejscem nie otwiera się w innym mieście, i ile to wszystko kosztuje — parowanie wychodzi około 10 ms.

7. Czego tu nie twierdzimy