Tłumaczenie maszynowe, niezweryfikowane przez osobę, dla której polski jest językiem ojczystym. Wzorcem jest wersja angielska.

Walidacja i dowodyEdytuj na GitHubieŹródło: docs/EVIDENCE-PACKS.md

Pakiety dowodowe: podpisany zapis zdarzenia dotyczącego zaufania do GNSS

Pakiet jest zapisem technicznym, a nie opinią prawną. Podaje, co silnik Kshana obliczył z podanego dziennika odbiornika przy podanej konfiguracji, i pozwala każdemu sprawdzić, że nic w nim nie zmieniono później. Nie mówi, co spowodowało zdarzenie, kto za nie odpowiadał, czy spełniono jakikolwiek obowiązek ani że dziennik pokazuje to, co odbiornik faktycznie odebrał. Mówią o tym zarówno manifest, jak i podsumowanie.

Pakiet dowodowy służy do raportu z incydentu, dla ubezpieczyciela lub na pytanie regulatora: „co wasz system powiedział o sygnale GNSS między tymi dwoma chwilami i czy możemy ufać temu zapisowi?”

Utwórz pakiet#

# once: a signing key. The private key stays with you; never commit it.
kshana evidence keygen --out signer.key        # writes signer.key (0600) and signer.key.pub

kshana receiver-trust evidence session.toml \
    --from 100 --to 260 \                       # seconds since the first epoch, or ISO-8601 UTC
    --key signer.key --out pack/ \
    --title "Berth 4, 14 June"                  # optional

Dla pakietu utworzonego z sesji laboratoryjnej --lab-attestation lab.toml zapisuje w podpisanym manifeście oświadczenie operatora o układzie (przewodowy lub ekranowany, tłumienie lub obudowa, co emitowało jakikolwiek sygnał RF); zob. HARDWARE-SAFETY.md. Jest zapisywane tak, jak podano, i nigdy nie jest weryfikowane.

--from i --to to sekundy od pierwszej epoki dziennika albo czas UTC w formacie ISO-8601, gdy dziennik podaje własny czas początku. --out nie może już zawierać plików. --created-utc przyjmuje rzeczywisty czas UTC, taki jak 2026-01-02T03:04:05Z (cokolwiek innego jest odrzucane), lub none, co pomija czas utworzenia i czyni pakiet odtwarzalnym bajt w bajt. Czas utworzenia jest tym, co poda podpisujący; nic nie sprawdza go względem zegara, do czego służy opcjonalny token znacznika czasu.

Plik klucza zawiera 32-bajtowe ziarno (seed) Ed25519 jako 64 cyfr szesnastkowych; podaj własny (na przykład przechowywany w twoim systemie zarządzania kluczami) albo pozwól, by keygen go utworzył. kshana ostrzega, jeśli plik jest czytelny dla innych użytkowników. .gitignore wyklucza *.evidence-key; nazwij tak swój klucz, jeśli leży w kopii roboczej repozytorium.

Co jest w pakiecie#

Struktura pakietu dowodowego. Dziennik odbiornika (NMEA, u-blox UBX, RINEX 3 lub dziennik Androida) i okno czasowe trafiają do kshana receiver-trust evidence, które zapisuje siedem plików: log-slice.bin, config.json, epochs.json, summary.html, manifest.json, manifest.sig i opcjonalny timestamp.tsr. Manifest zapisuje SHA-256 całego dziennika i każdego pliku oraz łańcuch skrótów po plikach; podpis obejmuje manifest. kshana evidence verify sprawdza podpis, skrót każdego pliku, łańcuch oraz to, że nie ma pliku spoza listy, i kończy się kodem 0, gdy zweryfikowano, 1, gdy coś zawiodło, i 3, gdy podpisujący nie był przypięty. Pakiet jest zapisem technicznym, a nie opinią prawną.Struktura pakietu dowodowego. Dziennik odbiornika (NMEA, u-blox UBX, RINEX 3 lub dziennik Androida) i okno czasowe trafiają do kshana receiver-trust evidence, które zapisuje siedem plików: log-slice.bin, config.json, epochs.json, summary.html, manifest.json, manifest.sig i opcjonalny timestamp.tsr. Manifest zapisuje SHA-256 całego dziennika i każdego pliku oraz łańcuch skrótów po plikach; podpis obejmuje manifest. kshana evidence verify sprawdza podpis, skrót każdego pliku, łańcuch oraz to, że nie ma pliku spoza listy, i kończy się kodem 0, gdy zweryfikowano, 1, gdy coś zawiodło, i 3, gdy podpisujący nie był przypięty. Pakiet jest zapisem technicznym, a nie opinią prawną.
Plik Zawartość
log-slice.bin surowe bajty dziennika odbiornika dla okna
config.json scenariusz tak, jak go uruchomiono (każdy próg monitora, zdarzenie i reguła porównania), uruchomione monitory, punkt odniesienia kalibracji i skrót scenariusza; dla statku także oświadczenie doradcze, które niesie każdy wynik dla statku (oprogramowanie doradcze, nie jest to sprzęt nawigacyjny z zatwierdzeniem typu); od 0,36 także geometry_model (faktycznie użyta tabela [geometry], waga monitora geometrii, każde pochodzenie i reguły klas). Nazwy katalogów i dane wbudowane są usuwane.
epochs.json każda epoka w oknie ze statystykami silnika, alarmami (przyczynami) i stanem zaufania; od 0,36 także jej satelitarne geometry (dobre, pogorszone z przyczynami lub nieznane, gdy dziennik nie podaje geometrii satelitów) oraz class przy każdym wniosku (geometry, environment, inconsistency)
summary.html samodzielne podsumowanie bez skryptów: identyfikacja, skróty, wyniki, przyczyny, pas geometrii (epoki według stanu geometrii) oddzielony od klas wniosków (0,36), każdy próg, tabela dla poszczególnych epok oraz ograniczenia zapisu
manifest.json wersja silnika, okno, czas utworzenia, format i nazwa dziennika, SHA-256 pełnego dziennika, zakres i SHA-256 wycinka, klucz publiczny i odcisk podpisującego, rozmiar i SHA-256 każdego pliku oraz łańcuch skrótów po plikach
manifest.sig podpis Ed25519 po dokładnych bajtach manifest.json
timestamp.tsr opcjonalny token znacznika czasu RFC 3161

Wycinek dziennika. Czytnik podaje zakres bajtów źródłowych każdej epoki, więc wycinek jest najmniejszym zakresem bajtów, który zawiera każdą epokę z okna (byte-range): NMEA, u-blox UBX, obserwacje RINEX 3 i dzienniki Androida. Jest haszowany jako surowe bajty, nigdy jako zdekodowany tekst. Dla kanału na żywo lub RINEX 2 zakresu nie ma; wtedy dołącza się cały dziennik, a manifest podaje whole-log (okno ogranicza, które epoki są raportowane, a nie które bajty są dołączone). Podsumowanie podaje, który przypadek zachodzi. Wycinek jest zapisem bajtów okna, a nie samodzielnym dziennikiem: na przykład wycinek RINEX nie ma nagłówka pliku.

Łańcuch skrótów. Manifest wymienia pliki w ustalonej kolejności. link₀ = SHA-256("kshana- evidence-chain/1"); dla każdego pliku linkᵢ = SHA-256(linkᵢ₋₁ ‖ SHA-256(file) ‖ len(name) ‖ name) (długość jako 4 bajty, big-endian). Ostatnie ogniwo to chain_head. Zmiana kolejności, usunięcie lub podmiana pliku zmienia łańcuch; podpis obejmuje łańcuch.

Zweryfikuj pakiet#

kshana evidence verify pack/ --pubkey signer.key.pub [--log session.nmea] \
    [--require-timestamp] [--allow-unpinned] [--json]

Kod wyjścia 0 oznacza zweryfikowano; 1 oznacza, że coś zawiodło; 2 oznacza błąd użycia; 3 oznacza, że pakiet jest nienaruszony, ale jego podpisujący nie był przypięty (zob. niżej). Każda kontrola zgłasza wynik pozytywny, negatywny lub pominięcie, a każda porażka jest nazwana:

Kod porażki Znaczenie
manifest-missing, manifest-malformed, unsupported-format nie można odczytać manifestu
signature-missing, signature-malformed, signature-invalid brak podpisu, to nie jest 64-bajtowy podpis szesnastkowy małymi literami albo nie weryfikuje się po manifest.json
public-key-malformed, public-key-mismatch klucz jest nieprawidłowy lub różni się od podanego przez ciebie
file-missing, file-size-mismatch, file-hash-mismatch wymieniony plik jest nieobecny lub różni się od manifestu; plik jest wskazany z nazwy
unlisted-file plik jest w pakiecie, ale nie ma go w manifeście
chain-mismatch, chain-head-mismatch ogniwo nie jest tym, co dają jego dane wejściowe; plik jest wskazany z nazwy
artifact-list-malformed, slice-record-inconsistent, epoch-count-mismatch manifest zaprzecza sam sobie lub epochs.json
full-log-hash-mismatch, slice-not-from-full-log z --log: dziennik, który masz, nie jest tym zapisanym albo wycinek nie jest tym zakresem dziennika
timestamp-missing, timestamp-malformed, timestamp-imprint-mismatch zob. poniżej

Zmiana jednego bajtu w dowolnym pliku powoduje porażkę weryfikacji z odpowiednim powodem: zmieniony artefakt jest zgłaszany jako niezgodność skrótu tego pliku i nic więcej; zmieniony manifest powoduje porażkę podpisu. Ponowne obliczenie skrótów i łańcucha po edycji pliku nie pomaga bez klucza podpisującego; wtedy zawodzi tylko podpis.

Przypnij klucz. Bez --pubkey pakiet dowodzi jedynie, że jest nienaruszony względem klucza, który sam wskazuje i który każdy może wygenerować. Dlatego weryfikacja kończy się wtedy kodem 3 i mówi „INTACT, BUT THE SIGNER IS NOT PINNED”, a nie „VERIFIED”; --allow-unpinned przyjmuje własny klucz pakietu świadomie i wypisuje „VERIFIED against the key the pack names itself (signer NOT pinned; pass --pubkey)”. Klucz publiczny podpisującego uzyskaj od podpisującego drogą, której ufasz (nie z pakietu) i przekaż go przez --pubkey: 64 cyfr szesnastkowych lub plik .pub. Przekazanie klucza prywatnego przez pomyłkę jest rozpoznawane i odrzucane. Odcisk (pierwsze 128 bitów SHA-256 klucza, 32 cyfry szesnastkowe) jest drukowany do porównania na oko; niezawodną drogą jest przypięcie pełnego klucza.

Format pakietu i procedura weryfikacji (normatywne)#

Ta sekcja jest specyfikacją, z której pisze się niezależny weryfikator. Słowa pisane wielkimi literami są wymaganiami. Pakiet jest katalogiem (lub dowolnym odwzorowaniem nazwy pliku na bajty) plików nazwanych dokładnie tak, jak niżej; weryfikator pracuje na bajtach każdego pliku w postaci zapisanej i niczego nie serializuje ponownie.

Pliki. Pliki artefaktów, w tej ustalonej kolejności, to log-slice.bin, config.json, epochs.json, summary.html. Pakiet ma także manifest.json i manifest.sig i MAY mieć timestamp.tsr. Każda inna nazwa to plik spoza listy.

Szesnastkowe. Każdy ciąg szesnastkowy to wyłącznie małe litery 0-9a-f, bez białych znaków; wielkie litery nie są akceptowane. Wartości SHA-256 mają 64 cyfry, klucz publiczny ma 64 cyfry, podpis ma 128 cyfr.

manifest.sig. 128-cyfrowy zapis szesnastkowy małymi literami 64-bajtowego podpisu Ed25519 (RFC 8032, czysty schemat Ed25519) po dokładnych bajtach manifest.json, po którym następuje dokładnie jeden \n i nic więcej. Podpis MUST być sprawdzany ściśle: podpis, którego wartość S nie jest mniejsza od rzędu grupy L, jest nieprawidłowy.

manifest.json. Obiekt JSON w UTF-8. Jego składowe (weryfikator MUST znaleźć każdą z podanym typem JSON; dodatkowe składowe są ignorowane):

składowa typ znaczenie
format ciąg znaków MUST równać się kshana-evidence/1
title, engine_version, disclaimer ciąg znaków opisowe
created_utc ciąg znaków lub null czas utworzenia, opisowy
window obiekt {from_s, to_s} liczby, sekundy
epochs_in_window nieujemna liczba całkowita liczba elementów tablicy JSON w epochs.json
log obiekt format ciąg znaków, file_name ciąg znaków, full_sha256 szesnastkowe, full_bytes nieujemna liczba całkowita, start_label ciąg znaków lub null oraz slice
log.slice obiekt kind (dokładnie byte-range lub whole-log; każda inna wartość czyni manifest wadliwym), start i end nieujemne liczby całkowite (przesunięcia w bajtach, koniec wyłączony), sha256 szesnastkowe
signer obiekt algorithm ciąg znaków (ed25519), public_key szesnastkowe (32 bajty), fingerprint ciąg znaków
artifacts tablica obiektów po jednym na plik artefaktu, w ustalonej kolejności: name ciąg znaków, role ciąg znaków, bytes nieujemna liczba całkowita, sha256 szesnastkowe, link szesnastkowe
chain_head szesnastkowe ostatnie ogniwo
lab_attestation obiekt, opcjonalny obecny tylko w pakiecie utworzonym z sesji laboratoryjnej (--lab-attestation): oświadczenie operatora operator, organisation, date, setup (conducted lub shielded), attenuation_db lub enclosure, emitter, statement i opcjonalnie signature, zapisane tak, jak podano. Obejmuje je podpis manifestu i nigdy nie jest weryfikowany; weryfikator zgłasza go jako „attested by the named operator; not verified by Kshana”. W pozostałych przypadkach nieobecny, a pakiet bez niego pozostaje bez zmian

signer.fingerprint to pierwsze 32 cyfry szesnastkowe SHA-256 po 32 bajtach klucza publicznego.

Łańcuch skrótów. link0 to SHA-256 z 23 bajtów ASCII kshana-evidence-chain/1. Dla każdego artefaktu w kolejności: link = SHA-256( previous_link (32 bytes) ‖ SHA-256(file) (32 bytes) ‖ len(name) as 4 bytes big-endian ‖ name as UTF-8 ), gdzie SHA-256(file) bierze się z zapisanego w manifeście sha256 dla tego artefaktu (więc łańcuch jest własnością manifestu i sprawdza się go względem manifestu, a nie względem plików).

Procedura. Weryfikator wykonuje te kroki po kolei i zbiera każdą porażkę; wynikiem jest zbiór porażek, z których każda to code i, gdzie podano, plik name. MUST NOT zatrzymywać się na pierwszej porażce, poza miejscami, gdzie podano. pin to klucz publiczny, któremu weryfikator kazano zaufać, jeśli jakiś jest.

  1. Brak manifest.json: porażka manifest-missing; stop.
  2. Jeśli manifest.json nie jest obiektem JSON ze wszystkimi powyższymi składowymi w podanych typach (w tym wpisami artifacts z każdą składową oraz log.slice): porażka manifest-malformed. W przeciwnym razie, jeśli format nie jest powyższą wartością: unsupported-format.
  3. Faza podpisu. Ta faza jest wykonywana niezależnie od tego, czy manifest dało się odczytać. Jeśli manifest dało się odczytać, klucz wskazany to signer.public_key; jeśli nie jest to 64 cyfr szesnastkowych małymi literami, porażka public-key-malformed (brak klucza wskazanego); w przeciwnym razie, jeśli signer.fingerprint nie jest jego odciskiem, porażka public-key-malformed (klucz pozostaje użyteczny). Jeśli istnieją zarówno pin, jak i klucz wskazany i się różnią: porażka public-key-mismatch. Klucz kontrolny to pin, jeśli go podano, w przeciwnym razie klucz wskazany, jeśli istnieje; jeśli nie ma żadnego, nie ma klucza kontrolnego (dotyczy to każdego przypadku, gdy manifestu nie dało się odczytać i nie podano pin). Jeśli nie ma manifest.sig: signature-missing. W przeciwnym razie, jeśli plik nie składa się dokładnie z 128 cyfr szesnastkowych małymi literami plus jednego \n: signature-malformed. W przeciwnym razie, jeśli jest klucz kontrolny, który nie jest prawidłowym kodowaniem klucza publicznego Ed25519: public-key-malformed. W przeciwnym razie, jeśli jest klucz kontrolny, a podpis nie weryfikuje się ściśle po bajtach manifest.json (jakiekolwiek by były): signature-invalid. (Bez klucza kontrolnego podpis nie jest sprawdzany i nie zgłasza się z tego powodu żadnej porażki.)
  4. Jeśli manifestu nie dało się odczytać (krok 2 dał manifest-malformed): zatrzymaj się tutaj.
  5. Artefakty. Jeśli nazwy artifacts nie są dokładnie czterema powyższymi w kolejności: artifact-list-malformed. Następnie dla każdego wpisu manifestu, w kolejności: jeśli pakiet nie ma pliku o tej nazwie, file-missing (nazwa); w przeciwnym razie, jeśli jego długość różni się od bytes, file-size-mismatch (nazwa); i niezależnie, jeśli SHA-256 pliku różni się od sha256, file-hash-mismatch (nazwa).
  6. Pliki spoza listy: dla każdego pliku w pakiecie innego niż manifest.json, manifest.sig, timestamp.tsr i nazwy z artifacts manifestu: unlisted-file (nazwa).
  7. Łańcuch. Przejdź po artifacts manifestu w kolejności od link0. Jeśli sha256 wpisu nie jest 64 cyframi szesnastkowymi małymi literami: manifest-malformed i łańcuch jest porzucany (bez sprawdzania głowy). W przeciwnym razie oblicz ogniwo; jeśli różni się od link wpisu: chain-mismatch (nazwa). Po przejściu, jeśli łańcuch nie został porzucony, a ostatnie ogniwo różni się od chain_head: chain-head-mismatch.
  8. Wycinek i epoki. Zgłoś slice-record-inconsistent (co najwyżej raz na powód, a weryfikator zgłasza kod raz niezależnie od liczby zachodzących powodów), jeśli zachodzi którekolwiek z: start > end; end > full_bytes; sha256 wpisu log-slice.bin różni się od slice.sha256; bytes tego wpisu różni się od end - start; albo kind to whole-log i zachodzi którekolwiek z start != 0, end != full_bytes, slice.sha256 != full_sha256. Jeśli epochs.json istnieje i parsuje się jako tablica JSON, której długość różni się od epochs_in_window: epoch-count-mismatch.
  9. Pełny dziennik. Tylko jeśli weryfikatorowi podano oryginalne bajty dziennika: jeśli ich SHA-256 różni się od log.full_sha256, full-log-hash-mismatch; w przeciwnym razie, jeśli zakres start..end nie mieści się w dzienniku albo bajty dziennika w tym miejscu różnią się od log-slice.bin, slice-not-from-full-log.
  10. Znacznik czasu. Bez timestamp.tsr: jeśli weryfikatorowi kazano go wymagać, timestamp-missing; w przeciwnym razie nic. Z nim: jeśli nie da się go odczytać jako tokenu lub odpowiedzi RFC 3161 (zob. niżej), timestamp-malformed; w przeciwnym razie, jeśli jego odcisk komunikatu nie jest skrótem, w algorytmie własnym odcisku (SHA-256, SHA-384 lub SHA-512), bajtów manifest.json: timestamp-imprint-mismatch.

Pakiet jest zweryfikowany dokładnie wtedy, gdy zbiór porażek jest pusty. To, czy podpisujący był przypięty, jest zgłaszane osobno i nie zmienia zbioru porażek.

Token znacznika czasu. Token to DER ContentInfo, którego typ zawartości to CMS SignedData (1.2.840.113549.1.7.2), a typ zawartości zamkniętej to id-ct-TSTInfo (1.2.840.113549.1.9.16.1.4); odpowiedź to DER TimeStampResp (PKIStatusInfo po którym następuje token), której status to 0 lub 1. Algorytm odcisku komunikatu w TSTInfo musi być SHA-256, SHA-384 lub SHA-512 ze skrótem długości tego algorytmu, a jego genTime musi być rzeczywistym czasem kalendarzowym UTC. BER o nieokreślonej długości nie jest akceptowany. Podpis organu i łańcuch certyfikatów są sprawdzane tylko wtedy, gdy podano zaufane kotwice (--tsa-ca, niżej).

Etykieta dowodowa (0,40)#

Pakiet wykonany przez 0,40 lub nowszą wersję niesie, wewnątrz config.json, wpis evidence (poziom, VALIDATED, MODELLED lub PARTNER, czyli najsłabszy status wśród jego wierszy, oraz identyfikatory i wymagania wierszy macierzy weryfikacji, na których opiera się zawartość pakietu: wiersz integralności pakietu, wiersze receiver-trust oraz wiersze jammertest-scoring lub pełnej pętli dla tych pakietów) i config_version "1.1". Jest wewnątrz config.json, więc skrót pliku manifestu, łańcuch skrótów i podpis go obejmują: jego zmiana powoduje niepowodzenie weryfikacji. kshana evidence verify podaje poziom i identyfikatory wierszy.

Zmiana jest addytywna i tylko w przód. format manifestu pozostaje kshana-evidence/1: normatywny tekst powyżej mówi, że weryfikator MUSI znaleźć tę wartość, i weryfikator czystego pomieszczenia w scripts/ ją znajduje. Wersja podrzędna jest więc niesiona przez config_version (nieobecne w pakiecie wykonanym przed 0,40, co oznacza 1,0), a nie przez nowy ciąg format. Pakiet wykonany przed 0,40 nie ma etykiety i weryfikuje się bez zmian; kshana evidence verify mówi „no evidence label (pre-0.40 pack)”. Testy to tests/evidence_pack_label.rs (w tym zatwierdzone pakiety wzorcowe sprzed 0.40) i tests/evidence_labels_doc_sync.rs.

Znacznik czasu RFC 3161 (opcjonalny)#

Token znacznika czasu od organu znakowania czasem pokazuje, że manifest istniał w chwili, którą organ poświadcza. Token dotyczy manifest.json, więc żąda się go po utworzeniu pakietu (nie da się go dostarczyć przy tworzeniu pakietu, a create_bundle odrzuca token, który nie dotyczy dokładnie tego manifestu):

openssl ts -query -data pack/manifest.json -sha256 -cert -out req.tsq
# send req.tsq to your authority, get the response, then:
kshana evidence attach-timestamp pack/ response.tsr
openssl ts -verify -in response.tsr -data pack/manifest.json -CAfile authority-ca.pem

kshana evidence verify odczytuje token (sam token lub pełną odpowiedź), sprawdza, że został przyznany i że jego odcisk komunikatu równa się skrótowi manifest.json, i wypisuje podany w nim czas. Bez zaufanych kotwic dodaje „timestamp authority signature not verified by Kshana” i zgłasza authority_signature_verified: false; tę część sprawdza wiersz openssl ts -verify powyżej. Token, którego odcisk się różni, lub taki, który się nie parsuje, jest porażką. Typy zawartości tokenu, długość odcisku i czas wygenerowania są sprawdzane pod kątem sensowności.

Z --tsa-ca authority-ca.pem (jeden lub więcej certyfikatów PEM, wszystkie zaufane) verify sprawdza także organ, offline, tak jak robi to openssl ts -verify: skrót komunikatu w podpisanych atrybutach, podpis (RSA PKCS#1 v1.5, RSA-PSS, ECDSA P-256 lub P-384), powiązanie certyfikatu podpisującego ESS, krytyczne rozszerzone użycie klucza timeStamping podpisującego oraz łańcuch do samowystawionej kotwicy, przy czym każdy certyfikat jest ważny w genTime tokenu. Porażka jest zgłaszana jako timestamp-authority-invalid z pierwszą kontrolą, która zawiodła, a authority_signature_verified jest prawdą tylko wtedy, gdy wszystko przeszło. Unieważnienia (CRL lub OCSP) nie są sprawdzane. Ten weryfikator zgadza się z OpenSSL 3.0.13 w 27 samodzielnie wygenerowanych przypadkach (tests/fixtures/evidence_tsa/PREREGISTRATION.md).

Token leży obok podpisanego manifestu, a nie w nim. Nic w podpisie ani w łańcuchu go nie obejmuje, więc token można usunąć albo podmienić na inny ważny token, bez porażki podpisu. verify dlatego zauważa, gdy pakiet go nie ma, a --require-timestamp czyni brak tokenu porażką (timestamp-missing); podmieniony token jest wychwytywany tylko wtedy, gdy nie pasuje do manifestu. attach-timestamp odmawia nadpisania istniejącego tokenu, chyba że podasz --replace. Jeśli znacznik czasu ma dla ciebie znaczenie, przechowuj token i wynik weryfikacji we własnych zapisach i go wymagaj.

Z kodu#

kshana::evidence::build_receiver_trust_pack to jedyny punkt wejścia, który wywołuje wiersz poleceń i każda inna powierzchnia, by utworzyć pakiet: na wejściu scenariusz, bajty dziennika (i pliku nawigacyjnego dla RINEX), okno jako tekst, tytuł i opcjonalny czas utworzenia oraz ziarno (seed) podpisu; na wyjściu pliki, liczba epok, wycinek, skrót manifestu i odcisk podpisującego. Nie czyta plików ani zegara, więc te same dane wejściowe dają te same bajty. Poniżej create_bundle i verify_bundle są funkcjami czystymi: na wejściu bajty (EvidenceInput, 32-bajtowe ziarno, BTreeMap<String, Vec<u8>> plików), na wyjściu wyniki możliwe do serializacji (Files, VerifyReport). Nie używają plików, zegara ani stanu procesu i budują się dla wasm32, więc powierzchnie Pythona, WebAssembly i serwera wywołują je bez zmian. Wiersz poleceń jest cienką nakładką na nie.

Czego pakiet nie robi#

  • Nie powtarza oceny. Każdy, kto ma pełny dziennik i config.json, może ponownie uruchomić kshana receiver-trust i porównać z epochs.json; pakiet dowodzi, co zapisano, a nie że silnik się nie mylił.
  • Nie dowodzi, że dziennik jest autentyczny ani kompletny. Skrót pełnego dziennika wiąże zapis z jednym plikiem; skąd ten plik pochodzi, musi ustalić operator.
  • Nie niesie żadnego twierdzenia o skuteczności wykrywania ani odrzucania zakłóceń.
  • Jest zapisem technicznym, a nie opinią prawną ani certyfikacją.