Question:
When signing our digest of signedAttrs our Signature Provider returns a Timestamp Token (since they are also our Time Stamp Authority).
According to the RFC-5652 and RFC-3161 standards the TimeStamp token must be added as an Unsigned Attribute in the unsignedAttrs field of the SignerInfo.
How can we accomplish this?
Answer:
You do not need to add generic unsigned attributes in order to embed a timestamp token. Please note that generally speaking, unsigned attributes can and should be inserted after signing.
With our SDK, it is done as follows (after a user-type signature has already been signed, the embedded timestamp is inserted into it):
TimestampingConfiguration tst_config(g_timestamping_URL);
VerificationOptions opts(VerificationOptions::e_compatibility_and_archiving);
/* It is necessary to add to the VerificationOptions a trusted root certificate corresponding to
the chain used by the timestamp authority to sign the timestamp token, in order for the timestamp
response to be verifiable during DocTimeStamp signing. */
opts.AddTrustedCertificate(g_timestamping_trusted_root_cert_path);
/* By default, we only check online for revocation of certificates using the newer and lighter
OCSP protocol as opposed to CRL, due to lower resource usage and greater reliability. However,
it may be necessary to enable online CRL revocation checking in order to verify some timestamps
(i.e. those that do not have an OCSP responder URL for all non-trusted certificates). */
opts.EnableOnlineCRLRevocationChecking(true);
TimestampingResult result(certification_sig_field.GenerateContentsWithEmbeddedTimestamp(tst_config, opts);
vector<UChar> cms_with_timestamp(result.GetData());
if (result.GetStatus())
{
doc.SaveCustomSignature(cms_with_timestamp.data(), cms_with_timestamp.size(),
certification_sig_field, in_outpath);
}
else
{
cout << "Embedded timestamping failed: " << result.GetString() << "\n";
return false;
}
I am trying this idea out and it worked out perfectly for timestamping.
But also want to add LTV and that part it’s not working, well better put. The LTV activation works, but it is not being saved. This code works for saving an embedded time stamp, the LTV although enabled it’s not part of the data sent to SaveCustomSignature. But if I do a regular incremental save, the signature will become corrupt (at least for the Abode Reader), because the document has the no_changes_allowed flag. If I change that flag to allow some changes, it works fine. But my requirement is to HAVE that flag.
PDF::TimestampingConfiguration timeStampConfiguration("TIMESTAMP_SERVER");
PDF::VerificationOptions verificationOpts(VerificationOptions::e_compatibility_and_archiving);
verificationOpts.AddTrustedCertificate("CERT_ROOT", VerificationOptions::e_default_trust | VerificationOptions::e_certification_trust);
verificationOpts.EnableOnlineCRLRevocationChecking(true);
verificationOpts.EnableOnlineOCSPRevocationChecking(true);
verificationOpts.EnableTrustVerification(true);
verificationOpts.EnableOnlineRevocationChecking(true);
// LTV stuff configuration check & set
PDF::VerificationResult verificationResultsLTV = digsig_field.Verify(verificationOpts);
digsig_field.EnableLTVOfflineVerification(verificationResultsLTV);
//if I do the saving, invalidates the signature, but enables LTV, if I don't LTV is not enabled
//doc.Save(in_docpath, SDFDoc::e_incremental);
//look how to save only signature
PDF::TimestampingResult resultTimeStamp(digsig_field.GenerateContentsWithEmbeddedTimestamp(timeStampConfiguration, verificationOpts));
if (resultTimeStamp.GetStatus()) {
std::vector<UChar> cms_with_timestamp(resultTimeStamp.GetData());
doc.SaveCustomSignature(cms_with_timestamp.data(), cms_with_timestamp.size(), digsig_field, in_docpath);
cout << "Timestamping Locked and loaded" << endl;
}
Do you have any idea how to accomplish this?
Santiago G.