Bramka MF / Kryptografia
Błąd HashValue albo ContentLength w InitUpload JPK
Objaw / komunikat błędu
Odrzucenie InitUpload.xml albo sesji: niezgodna suma kontrolna HashValue lub rozmiar ContentLength (dokument albo FileSignature).
InitUpload opisuje dwa różne byty. Document to surowy XML przed ZIP i AES: jego rozmiar i SHA-256. FileSignature to już zaszyfrowana paczka: jej rozmiar i MD5. Podmiana tych pól albo szyfrowanie klucza przez RSA-OAEP kończy się odrzuceniem sesji.
Przyczyna techniczna
- Document/ContentLength jest liczbą bajtów jawnego XML. Document/HashValue jest SHA-256 tego samego ciągu bajtów, zakodowanym Base64 i ma 44 znaki (32 bajty skrótu). Liczenie skrótu po kompresji daje inny wynik.
- FileSignature/ContentLength jest rozmiarem jednej paczki .enc. FileSignature/HashValue jest MD5 tej paczki w Base64 i ma 24 znaki (16 bajtów). Wstawienie SHA-256 do podpisu paczki nie przejdzie schematu ani kontroli bramki.
- Klucz AES i IV szyfruje się kluczem publicznym MF algorytmem RSAES-PKCS1-V1_5. RSA-OAEP jest nowszy, ale ta bramka go nie odpakuje, więc sesja upada mimo poprawnych skrótów.
- Certyfikat testowy i produkcyjny są różne. Skrót pliku może być dobry, a klucz AES zaszyfrowany cudzym certyfikatem. Bramka produkcyjna nie otworzy klucza spod certyfikatu testowego.
Jak naprawić błąd krok po kroku
- 1
Policz SHA-256 na surowych bajtach, przed ZIP
Hash dokumentu powstaje na oknie odczytu oryginału, zanim ZipDeflate i AES dotkną danych. Wynik do XML wchodzi jako Base64, 44 znaki.
- 2
Dla każdej paczki policz osobny MD5
Po zamknięciu paczki 60 MiB (ostatnia może być krótsza) licz MD5 jej bajtów i wpisz FileSignature/HashValue (24 znaki Base64) oraz jej ContentLength.
- 3
Zaszyfruj klucz AES przez PKCS#1 v1.5
Użyj certyfikatu właściwego środowiska, algorytmu RSAES-PKCS1-V1_5, i wpisz wynik do InitUpload. Nie podmieniaj go na OAEP.
- 4
Podpisz InitUpload dopiero gdy liczby są ostateczne
Każda zmiana pliku źródłowego unieważnia ContentLength, oba rodzaje skrótów i podpis XAdES. Najpierw plik, potem metryka, potem podpis.
Jak rozwiązuje to architektura SecureJPK
Worker liczy SHA-256 strumieniowo na surowych bajtach (node-forge) i MD5 każdej paczki po AES (spark-md5, Base64). Document/ContentLength bierze się z rozmiaru oryginału, a przy podpisanym InitUpload serwer potrafi odczytać go z pierwszego Document/ContentLength, żeby nie pomylić go z długością paczki. Klucz szyfruje node-forge jako RSA PKCS#1 v1.5 certyfikatem TEST albo PROD zależnie od środowiska. Jawny XML i klucz nie są wysyłane na serwer SecureJPK.
Najczęstsze pytania (FAQ)
- Ile znaków ma HashValue dokumentu, a ile paczki?
- Skrót dokumentu to SHA-256 w Base64, 44 znaki. Skrót paczki to MD5 w Base64, 24 znaki. Inna długość prawie zawsze oznacza zły algorytm.
- Czy ContentLength w Document obejmuje ZIP?
- Nie. To rozmiar jawnego XML przed kompresją i szyfrowaniem. Rozmiar paczki .enc jest w FileSignature/ContentLength i bywa mniejszy albo, przy narzucie AES, nieporównywalny 1:1 z plikiem źródłowym.
- Dlaczego nie RSA-OAEP?
- Bramka MF odpakowuje klucz algorytmem RSAES-PKCS1-V1_5. OAEP jest poprawnym RSA, ale nie tym, którego oczekuje ten interfejs. Sesja z OAEP nie wstanie mimo dobrego SHA-256.