PDFiumPas zapisuje szyfrowanie ISO/TS 32003 przez SaveAsEncrypted: ustaw Revision na erR7, a każdy łańcuch znaków i strumień zostaje zabezpieczony AES-256 w trybie GCM, uwierzytelnionym szyfrze, który PDF 2.0 otrzymał w 2023 roku. Ustaw również EnableIntegrityProtection, a dokument niesie także samodzielny token PDF MAC, który ValidatePdfMac sprawdza po stronie odczytu
To dwie różne ochrony, które ludzie regularnie mylą. GCM uwierzytelnia każdą zaszyfrowaną wartość. MAC uwierzytelnia dokument jako całość. Chcesz obu, z różnych powodów
Co daje GCM, czego CBC nigdy nie dawał?
Uwierzytelnienie szyfrogramu. AES-256 w trybie CBC, schemat AESV3 w ISO 32000-2, zachowuje poufność treści i nic nie mówi o tym, czy dotarła niezmodyfikowana. CBC jest podatny na manipulację w konkretny, dobrze zbadany sposób: atakujący, który potrafi odwracać bity w szyfrogramie, wywołuje przewidywalne zmiany w tekście jawnym następnego bloku, i nic w formacie tego nie zauważa
GCM to zamyka. Każda zaszyfrowana wartość niesie 16-bajtowy znacznik uwierzytelniający, serializowany w całości zgodnie z wymaganiami ISO/TS 32003, a odszyfrowanie kończy się niepowodzeniem, zamiast zwrócić zmieniony tekst jawny, gdy znacznik się nie zgadza. W kategoriach PDF zmanipulowany łańcuch znaków albo strumień w dokumencie AESV4 to twardy błąd w miejscu użycia, a nie dziwna wartość rozprzestrzeniająca się w twojej aplikacji. Słownik Encrypt zaznacza to jako /CFM /AESV4 i V 6 / R 7, obok wpisu rozszerzeń deklarującego /ExtensionLevel 32003 i /ExtensionRevision (:2023)
Trzy rewizje, trzy ekosystemy
TPdfEncryptionRevision oferuje erR5, erR6 i erR7, a wybór jest bardziej decyzją o zgodności niż kryptograficzną. R5 to oryginalny schemat AES-256 opublikowany jako rozszerzenie PDF 1.7, z pojedynczym haszem hasła SHA-256, i otwiera się w praktycznie wszystkim z ostatnich piętnastu lat. R6 to wzmocnione wyprowadzanie klucza znormalizowane w ISO 32000-2, wykorzystujące iterującą konstrukcję SHA-256/384/512 z algorytmu 2.B, i jest tym, czego oczekuje bieżący przepływ pracy PDF 2.0 albo PDF/A-4. R7 to ISO/TS 32003, wykorzystujące to samo wyprowadzanie 2.B z AES-GCM jako szyfrem
Obsługa czytników przebiega dokładnie w tej kolejności, a obsługa R7 jest wciąż wąska poza bieżącymi głównymi przeglądarkami. To ten sam kompromis, który rządzi każdą funkcją PDF 2.0: najnowsza opcja to najlepszy inżynieryjnie wybór i najwęższa publiczność. Decyduj według tego, kto musi otworzyć plik, a jeśli tą odpowiedzią jest „system archiwizacji, którego nikt nie aktualizował od 2019 roku”, odpowiedzią jest R5, niezależnie od tego, czego wolałaby polityka bezpieczeństwa
uses
PDFium, FPdfEncrypt;
var
Pdf: TPdf;
Opts: TPdfEncryptOptions;
begin
Pdf := TPdf.Create(nil);
try
Pdf.FileName := 'quarterly-report.pdf';
Pdf.LoadDocument;
Opts := TPdfEncryptOptions.Default;
Opts.UserPassword := 'open-secret';
Opts.OwnerPassword := 'admin-secret';
Opts.EncryptMetadata := True;
Opts.Revision := erR7; // ISO/TS 32003 AESV4-GCM
Opts.EnableIntegrityProtection := True; // samodzielny token PDF MAC
if not Pdf.SaveAsEncrypted('quarterly-report.enc.pdf', Opts) then
raise Exception.Create('Encrypted save failed');
finally
Pdf.Free;
end;
end;
Po co dokumentowy MAC na wierzchu uwierzytelnionego szyfru?
Ponieważ znaczniki GCM chronią wartości, nie układ wartości. Każdy łańcuch znaków i strumień w dokumencie AESV4 jest indywidualnie uwierzytelniony, a mimo to tablica odsyłaczy krzyżowych, numeracja obiektów i trailer to struktura, nie zaszyfrowana treść. Atakujący nie może sfałszować strumienia, ale nic w samym szyfrze nie powstrzymuje go przed przestawieniem, na które obiekty wskazuje dokument, albo posklejaniem obiektów z wcześniejszej rewizji tego samego pliku
Samodzielny token PDF MAC adresuje właśnie tę warstwę. PDFiumPas wyprowadza go z klucza szyfrowania pliku przy użyciu dedykowanej 32-bajtowej wartości /KDFSalt zapisanej w słowniku Encrypt, więc to posiadanie hasła pozwala czytnikowi potwierdzić token. Wynikiem jest jedna odpowiedź na jedno pytanie: czy ten dokument, jako całość, jest dokumentem, który został zapisany
var
Pdf: TPdf;
Mac: TPdfMacValidationResult;
begin
Pdf := TPdf.Create(nil);
try
Pdf.Password := 'open-secret';
Pdf.FileName := 'quarterly-report.enc.pdf';
Pdf.LoadDocument;
Mac := Pdf.ValidatePdfMac('open-secret');
case Mac.Status of
pmvsValid: ProcessDocument(Pdf);
pmvsNotPresent: ProcessWithWarning(Pdf); // brak tokenu w tym pliku
pmvsInvalid: Quarantine(Mac.MessageText); // zmanipulowany albo obcięty
pmvsUnsupported: RouteForManualReview(Mac.MessageText);
end;
finally
Pdf.Free;
end;
end;
Cztery wartości statusu wymagają czterech różnych reakcji, a zredukowanie ich do wartości logicznej gubi rozróżnienie, które ma znaczenie. pmvsNotPresent oznacza, że plik po prostu nie ma tokenu, co opisuje niemal każdy zaszyfrowany plik PDF napisany przed 2024 rokiem i nie jest dowodem niczego. pmvsInvalid oznacza, że token jest obecny i się nie weryfikuje, co jest prawdziwym odkryciem i powinno zatrzymać przetwarzanie. pmvsUnsupported oznacza, że token istnieje w kształcie, którego ta kompilacja nie implementuje, co jest luką zgodności, nie atakiem. Traktowanie „nieobecnego” jako „nieprawidłowego” zakwarantowałoby cały twój dotychczasowy zbiór już pierwszego dnia
Czego szyfrowanie wciąż nie robi
Flagi uprawnień pozostają tym, czym zawsze były: żądaniem skierowanym do zgodnego oprogramowania, nie kontrolą. Bity /P z tabeli 22 ISO 32000-1, które zabraniają drukowania albo wyodrębniania treści, są honorowane przez dobrze zachowujące się przeglądarki i ignorowane przez wszystko inne, a każdy posiadający hasło użytkownika już ma odszyfrowaną treść. Szyfrowanie to granica; uprawnienia opisują intencję wewnątrz niej
Dwa szczegóły operacyjne warto zaplanować. Po pierwsze, szyfrowanie i późniejsza modyfikacja wchodzą w interakcję: dopisanie aktualizacji przyrostowej do zaszyfrowanego dokumentu ma własne zasady, omówione w aktualizacjach przyrostowych w zaszyfrowanych plikach PDF, a token MAC to stwierdzenie na poziomie dokumentu, które nieostrożne dopisanie unieważni. Po drugie, konstrukcja GCM używa deterministycznego licznika IV, a PDFiumPas zgłasza wyjątek zamiast ponownie użyć wartości licznika, gdyby ta przestrzeń kiedykolwiek się wyczerpała, ponieważ ponowne użycie nonce w GCM jest katastrofalne w sposób, który ciche przepełnienie by ukryło
Wybór między trzema rewizjami w praktyce
Zapisz, kto otwiera plik, a potem wybierz. Do dystrybucji wewnętrznej, gdzie każdy czytnik to bieżąca przeglądarka pod twoją kontrolą, R7 z ochroną integralności to najsilniejsza dostępna opcja i nie ma powodu, by z niej nie skorzystać. Dla dokumentów opuszczających organizację R6 jest rozsądną wartością domyślną: jest znormalizowany w ISO 32000-2, a nie w specyfikacji technicznej na nim nadbudowanej, a obsługa jest szeroka. Dla archiwów i przestarzałych odbiorców R5 jest jedynym wyborem, który niezawodnie się otworzy, i warto zapisać dlaczego w tym samym miejscu, gdzie zapisujesz resztę polityki retencji
Niezależnie od wyboru, zweryfikuj wyjście zamiast ufać, że wywołanie się powiodło. Otwórz ponownie zaszyfrowany plik, sprawdź ValidatePdfMac i potwierdź, że zadeklarowana wersja jest tą, której oczekujesz, korzystając z kontroli zgodności wersji opisanych w dokładnej zgodności wersji PDF. Szersza lista kontrolna dla niezaufanych dokumentów jest w audycie ryzyk bezpieczeństwa PDF
PDFiumPas to komponent Delphi i Lazarus wokół silnika PDFium, z natywnie zaimplementowanym w Pascalu stosem szyfrowania PDF 2.0, więc AES-256, GCM i token MAC nie potrzebują żadnej zewnętrznej biblioteki DLL kryptograficznej. API szyfrowania jest udokumentowane na stronie komponentu PDFium dla Delphi