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:
Any idea what the problem might be??
Output file example: https://drive.google.com/file/d/0B5OSF4ESCy5gRU5xTXQxU2NEMmM/view?usp=sharing
Thanks, Julián
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.
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.
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.