2014-10-09 27 views
7

Korzystam z iTextSharp 5.5.1 w celu cyfrowego podpisywania plików PDF za pomocą oddzielnego podpisu (uzyskanego od organu zewnętrznego). Wszystko wydaje się działać poprawnie, plik jest ważny i np. Adobe Reader nie zgłasza problemów, wyświetla podpisy jako ważne itp.Usunąć znak zamówienia bajtów z podpisanego pliku PDF?

Problem polega na tym, że klienci Java mają najwyraźniej pewne problemy z tymi plikami - plik nie może być ani otwarty, ani przeanalizowany.
Pliki mają znacznik kolejności bajtów w nagłówku, który wydaje się powodować zachowanie (\ x00EF \ x00BB \ x00BF).

mogłem zidentyfikować BOM takiego:

PdfReader reader = new PdfReader(path); 
byte[] metadata = reader.Metadata; 
// metadata[0], metadata[1], metadata[2] contain the BOM 

Jak mogę albo usunąć BOM (bez utraty ważności podpisu), albo zmusić biblioteki iTextSharp nie Dołącz te bajty do plików?

+0

Właśnie sprawdziłem i iTextSharp nie dodaje samodzielnie LM. Oryginalne pliki PDF miały je przed podpisaniem lub w pewnym momencie dodajesz BOM. – divanov

+0

Metadane (które są osadzone gdzieś w pliku PDF) zwykle mają LM i to jest w porządku. * Problem polega na tym, że klienci Java mają najwyraźniej problemy z tymi plikami * - które klienty Java? – mkl

+0

@mkl: po pierwsze, InputStream odczytuje tablicę bajtów, a następnie XMLPullParse (android) zgłasza XmlPullParserException podczas analizowania xml. Używanie BOMInputStream usuwa BOM z łańcucha, tak aby XMLPullParser mógł go odczytać w każdym przypadku. Ale moim wymaganiem jest posiadanie oryginalnego pliku bez BOM. – lukasz

Odpowiedz

6

Pierwsze rzeczy pierwsze: kiedy zostanie podpisana PDF, nie należy zmieniać żadnych bajt tym PDF, ponieważ jeśli to zrobisz, unieważnisz podpis.

Druga uwaga: znacznik kolejności bajtów to , a nie część nagłówka PDF (plik PDF zawsze zaczyna się od %PDF-1.). W tym kontekście jest to wartość atrybutu begin w instrukcji przetwarzania metadanych XMP. Nie znam żadnego klienta Java, który ma problem z tą sekwencją bajtów w dowolnym miejscu pliku. Jeśli mają z tym jakiś problem, jest problem z tym klientem, a nie z plikiem.

Numer Byte Order Mark wskazuje na obecność znaków UTF-8. W kontekście XMP mamy strumień wewnątrz pliku PDF, który zawiera wyraźny plik tekstowy XML, który może być wykorzystany przez oprogramowanie, które nie jest "świadome PDF". Na przykład:

2 0 obj 
<</Type/Metadata/Subtype/XML/Length 3492>>stream 
<?xpacket begin="" id="W5M0MpCehiHzreSzNTczkc9d"?> 
<x:xmpmeta xmlns:x="adobe:ns:meta/" x:xmptk="Adobe XMP Core 5.1.0-jc003"> 
    <rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"> 
    <rdf:Description rdf:about="" 
     xmlns:dc="http://purl.org/dc/elements/1.1/" 
     xmlns:pdf="http://ns.adobe.com/pdf/1.3/" 
     xmlns:xmp="http://ns.adobe.com/xap/1.0/" 
     dc:format="application/pdf" 
     pdf:Keywords="Metadata, iText, PDF" 
     pdf:Producer="iText® 5.5.4-SNAPSHOT ©2000-2014 iText Group NV (AGPL-version); modified using iText® 5.5.4-SNAPSHOT ©2000-2014 iText Group NV (AGPL-version)" 
     xmp:CreateDate="2014-11-07T16:36:55+01:00" 
     xmp:CreatorTool="My program using iText" 
     xmp:ModifyDate="2014-11-07T16:36:56+01:00" 
     xmp:MetadataDate="2014-11-07T16:36:56+01:00"> 
     <dc:description> 
     <rdf:Alt> 
      <rdf:li xml:lang="x-default">This example shows how to add metadata</rdf:li> 
     </rdf:Alt> 
     </dc:description> 
     <dc:creator> 
     <rdf:Seq> 
      <rdf:li>Bruno Lowagie</rdf:li> 
     </rdf:Seq> 
     </dc:creator> 
     <dc:subject> 
     <rdf:Bag> 
      <rdf:li>Metadata</rdf:li> 
      <rdf:li>iText</rdf:li> 
      <rdf:li>PDF</rdf:li> 
     </rdf:Bag> 
     </dc:subject> 
     <dc:title> 
     <rdf:Alt> 
      <rdf:li xml:lang="x-default">Hello World example</rdf:li> 
     </rdf:Alt> 
     </dc:title> 
    </rdf:Description> 
    </rdf:RDF> 
</x:xmpmeta>                
<?xpacket end="w"?> 
endstream 

Taki zakaz PDF-aware oprogramowanie będzie szukać sekwencji W5M0MpCehiHzreSzNTczkc9d, który jest sekwencja, która jest mało prawdopodobne, aby pojawić się przez przypadek w strumieniu danych.

Atrybut begin wskazuje, że znaki w strumieniu używają kodowania UTF-8. Są tam, ponieważ jest to dobra praktyka dla nich, ale nie są one obowiązkowe (ISO-16684-1).

Można było pobierać metadane tak jak ty (byte[] metadata = reader.Metadata;), usunąć bajtów i zmienić strumień z PdfStamper przykład jak ten:

stamper.XmpMetadata = metadata; 

Po zmianie metadane, można podpisać PDF.

Zauważ, że jeden aspekt twojego pytania zaskakuje mnie. Piszesz:

// metadata[0], metadata[1], metadata[2] contain the BOM 

To bardzo dziwne, że pierwsze trzy bajty metadanych XMP zawierają BOM. Metadane XMP mają zaczynać się od <?xpacket. Jeśli tak nie jest, robisz to, co trzeba, usuwając te bajty.

Zastrzeżenie: Plik PDF może zawierać metadane XMP na różnych poziomach. W tej chwili analizujesz najczęściej spotykany: metadane na poziomie dokumentu. Możesz napotkać pliki PDF z metadanymi XMP na poziomie strony, z XMP wewnątrz obrazu, itp ...

+0

* Druga obserwacja: znacznik kolejności bajtów nie jest częścią nagłówka. Jest to wartość atrybutu begin * - tak powinno być. Ale jeśli dobrze pamiętam, próbka OP podpisanego i zaszyfrowanego pliku rzeczywiście miała BOM, zobacz [tutaj] (http://i.stack.imgur.com/nrj3t.png). (Właściwie to chciałem zajrzeć do tego, ale straciłem z oczu problem.) – mkl

+0

To znaczy: nie jest częścią nagłówka PDF. Nagłówek PDF wygląda następująco: '% PDF-1.'. Wyjaśnię. –

+0

Ponownie przeczytałem pytanie. Jest niejednoznaczny. Mówi, że zestawienie komponentów jest częścią nagłówka pliku *, * ale przykład pokazuje, że nie jest to prawdą: zestawienie komponentów znajduje się w metadanych XMP. Metadane XMP są pakowane wewnątrz strumienia w pliku PDF. –

1

Po prostu szybkie podejście:

Po pierwsze: zapisz oba pliki niezaszyfrowane. Po drugie: usuń metadane od 0 do 2 przed zapisaniem pliku

Istnieją jednak następujące kwestie: czy metoda podpisywania wymaga LM? Czy metoda szyfrowania wymaga BOM?

Należy również sprawdzić, na jakim etapie dodawana jest specyfikacja materiałowa, aby ustalić, czy można/należy usunąć zestawienie komponentów.

Będę miał szybkie polowanie na moje dokumenty dotyczące struktury plików PDF i zobaczę, co mogę uzyskać, jednak najprostszy sposób będzie (untried) załadować całość jako tablicę bajtów i po prostu usunąć xEF xBB xBF od początku pliku , następnie wykonaj dowolne podpisywanie/szyfrowanie. Jednak mogą one dodać go ponownie ...

będę po aktualizacji na weekend :)