javapdftimestampitextbouncycastle

Adding a timestamp to a PDF corrupts the file


I'm trying to add a timestamp to a PDF file using a TSA server but after the timestamp has been added Adobe Reader says that the document has been altered or corrupted since it was signed.

Test code:

@SpringBootApplication
public class TestTimestampApplication implements CommandLineRunner {

public static void main(String[] args) {
    SpringApplication.run(TestTimestampApplication.class, args);
}

@Override
public void run(String... arg0) throws Exception {
    TSAClient tsa = new TSAClientBouncyCastle("http://tsa.buenosaires.gob.ar/TSS/HttpTspServer");

    try (OutputStream os = new FileOutputStream("I:/output.pdf")) {
        PdfReader reader = new PdfReader("I:/input.pdf");
        PdfStamper stamper = PdfStamper.createSignature(reader, os, '\0', null, true);

        PdfSignatureAppearance sap = stamper.getSignatureAppearance();
        LtvTimestamp.timestamp(sap, tsa, "Atenea");
    }
}

}

I'm using these frameworks to do the timestamping:

    <dependency>
        <groupId>com.itextpdf</groupId>
        <artifactId>itextpdf</artifactId>
        <version>5.5.12</version>
    </dependency>
    <dependency>
        <groupId>org.bouncycastle</groupId>
        <artifactId>bcprov-jdk15on</artifactId>
        <version>1.58</version>
    </dependency>
    <dependency>
        <groupId>org.bouncycastle</groupId>
        <artifactId>bcpkix-jdk15on</artifactId>
        <version>1.58</version>
    </dependency>

And when I open the output file I get this:

enter image description here

Any idea what the problem might be??

Output file example: https://drive.google.com/file/d/0B5OSF4ESCy5gRU5xTXQxU2NEMmM/view?usp=sharing

Thanks, Julián


Solution

  • First of all, the MessageImprint in the TSTInfo of the time stamp contains the correct hash value of the time stamped byte range. Thus, the problem must be something different.

    Extended Key Usage

    The ASN.1 representation of the Extended Key Usage extension of the TSA certificate looks like this:

     951   49: . . . . . . . . SEQUENCE {
     953    3: . . . . . . . . . OBJECT IDENTIFIER extKeyUsage (2 5 29 37)
             : . . . . . . . . . . (X.509 extension)
     958   42: . . . . . . . . . OCTET STRING, encapsulates {
     960   40: . . . . . . . . . . SEQUENCE {
     962    8: . . . . . . . . . . . OBJECT IDENTIFIER
             : . . . . . . . . . . . . serverAuth (1 3 6 1 5 5 7 3 1)
             : . . . . . . . . . . . . (PKIX key purpose)
     972    8: . . . . . . . . . . . OBJECT IDENTIFIER
             : . . . . . . . . . . . . codeSigning (1 3 6 1 5 5 7 3 3)
             : . . . . . . . . . . . . (PKIX key purpose)
     982    8: . . . . . . . . . . . OBJECT IDENTIFIER
             : . . . . . . . . . . . . timeStamping (1 3 6 1 5 5 7 3 8)
             : . . . . . . . . . . . . (PKIX key purpose)
     992    8: . . . . . . . . . . . OBJECT IDENTIFIER
             : . . . . . . . . . . . . ocspSigning (1 3 6 1 5 5 7 3 9)
             : . . . . . . . . . . . . (PKIX key purpose)
             : . . . . . . . . . . . }
             : . . . . . . . . . . }
             : . . . . . . . . . }
    

    This in particular means that the certificate is marked for use in server authentication, code signing, time stamping, and OCSP signing. Furthermore, the extension is not marked critical.

    RFC 3161, on the other hand, requires:

    2.3. Identification of the TSA

    The TSA MUST sign each time-stamp message with a key reserved specifically for that purpose. A TSA MAY have distinct private keys, e.g., to accommodate different policies, different algorithms, different private key sizes or to increase the performance. The corresponding certificate MUST contain only one instance of the extended key usage field extension as defined in [RFC2459] Section 4.2.1.13 with KeyPurposeID having value:

    id-kp-timeStamping. This extension MUST be critical.

    (RFC 3161 section 2.3)

    Thus, the certificate of that TSA must not be used to generate RFC 3161 time stamps, so all time stamps generated with it are not valid.