Timestamped digital signature in Java

I have a problem creating a valid CMS signature with Bouncy Castle using a reliable timestamp. Creating a signature works well (I want to include the signature in the PDF file), the signature is valid. But after including a reliable timestamp in the unsigned attribute table, the signature still remains valid, but Reader reports that the signature contains a built-in timestamp, but it is not valid. This leads me to believe that the hash timestamp is not correct, but I cannot figure out what the problem is with it.

Signature Code:

Store store = new JcaCertStore(Arrays.asList(certContainer.getChain()));

CMSSignedDataGenerator signedDataGenerator = new CMSSignedDataGenerator();
JcaSignerInfoGeneratorBuilder infoGeneratorBuilder = new JcaSignerInfoGeneratorBuilder(new JcaDigestCalculatorProviderBuilder().setProvider("BC").build());
JcaContentSignerBuilder contentSignerBuilder = new JcaContentSignerBuilder("SHA1withRSA");
signedDataGenerator.addSignerInfoGenerator(
                       infoGeneratorBuilder.build(contentSignerBuilder.build(certContainer.getPrivateKey()), (X509Certificate)certContainer.getSignatureCertificate()));
signedDataGenerator.addCertificates(store);
CMSTypedData cmsData = new CMSProcessableByteArray(data);
signedData = signedDataGenerator.generate(cmsData, false);
Collection<SignerInformation> ss = signedData.getSignerInfos().getSigners();
SignerInformation si = ss.iterator().next(); // get first signer (should be only one)
ASN1EncodableVector timestampVector = new ASN1EncodableVector();
Attribute token = createTSToken(si.getSignature());
timestampVector.add(token);
AttributeTable at = new AttributeTable(timestampVector);
si = SignerInformation.replaceUnsignedAttributes(si, at);
ss.clear();
ss.add(si);
SignerInformationStore newSignerStore = new SignerInformationStore(ss);
CMSSignedData newSignedData = CMSSignedData.replaceSigners(signedData, newSignerStore);

Code createTSToken:

public Attribute createTSToken(byte[] data) throws NoSuchProviderException, NoSuchAlgorithmException, IOException {
    // Generate timestamp
    MessageDigest digest = MessageDigest.getInstance("SHA1", "BC");
    TimeStampResponse response = timestampData(digest.digest(data));
    TimeStampToken timestampToken = response.getTimeStampToken();
    // Create timestamp attribute

    Attribute a = new Attribute(PKCSObjectIdentifiers.id_aa_signatureTimeStampToken, new DERSet(ASN1Primitive.fromByteArray(timestampToken.getEncoded())));
    return a;
}

timestampData:

TimeStampRequestGenerator reqgen = new TimeStampRequestGenerator();
TimeStampRequest req = reqgen.generate(TSPAlgorithms.SHA1, data);
byte request[] = req.getEncoded();

URL url = new URL("http://time.certum.pl");
HttpURLConnection con = (HttpURLConnection) url.openConnection();

con.setDoOutput(true);
con.setDoInput(true);
con.setRequestMethod("POST");
con.setRequestProperty("Content-type", "application/timestamp-query");
con.setRequestProperty("Content-length", String.valueOf(request.length));

OutputStream out = con.getOutputStream();
out.write(request);
out.flush();

if (con.getResponseCode() != HttpURLConnection.HTTP_OK) {
    throw new IOException("Received HTTP error: " + con.getResponseCode() + " - " +                 con.getResponseMessage());
}
InputStream in = con.getInputStream();
TimeStampResp resp = TimeStampResp.getInstance(new ASN1InputStream(in).readObject());
response = new TimeStampResponse(resp);
response.validate(req);
if(response.getStatus() != 0) {
    System.out.println(response.getStatusString());
    return null;
}
return response;

Thank you for your help!

Sample files:

Signed PDF

Unsigned PDF

Signed PDF with iText

Signed PDF with LTV - Edited

+1
1

signed_lipsum.pdf,

signer some

CN = e-Szigno Test TSA2, OU = e-Szigno CA, O = Microsec Ltd., L = , C = HU

CN = Microsec e-Szigno Test Root CA 2008, OU = e-Szigno CA, O = Microsec Ltd., L = , C = HU

7.

, CMS , PDF, .

, , Adobe Reader , .

, Adobe Reader? , , . , .

, , , .

signed_lipsum.pdf,

signed_lipsum.pdf TSA, !

,

  • CN = e-Szigno Test TSA2, OU = e-Szigno CA, O = Microsec Ltd., L = , C = HU
  • CN = Microsec e-Szigno Test Root CA 2008, OU = e-Szigno CA, O = Microsec Ltd., L = , C = HU
  • 7.

, ,

  • CN = e-Szigno Test TSA2, OU = e-Szigno CA, O = Microsec Ltd., L = , C = HU
  • CN = Microsec e-Szigno Test Root CA 2008, OU = e-Szigno CA, O = Microsec Ltd., L = , C = HU
  • 5.

, TSA /soft -tokens , OP .

, .

, PDF, iText, , ...

RFC 3161 TSA . Bouncy Castle :

TimeStampRequestGenerator reqgen = new TimeStampRequestGenerator();
reqgen.setCertReq(true); // <<<<<<<<<<<<<<<<<<<<<<<<<<
TimeStampRequest req = reqgen.generate(TSPAlgorithms.SHA1, data);

, , .

LTV

:

, , PDF LTV ?

(PDF- Adobe):

LTV enabled , , ( ), . , [...] .

PDF , CRL OSCP

(10 2013 , 7:07 ; -)

+2

Source: https://habr.com/ru/post/1570800/


All Articles