Question:
I am suddenly getting Timestamp token verification failed
error when trying to sign. How do I diagnose further?
Answer:
The Apryse PDFNet SDK offers functions to test a TSA.
The following C# code will test a TSA using the provided URL and TSA public certificates.
For example
TestTSA("http://tsaToTest", "tsaToTest.crt");
static void PrintTrustVerificationResult(TrustVerificationResult trustVerificationResult)
{
Console.WriteLine("=======================================================================================================");
Console.WriteLine("TrustVerificationResult Begin");
Console.WriteLine("=======================================================================================================");
Console.WriteLine($"WasSuccessful: {trustVerificationResult.WasSuccessful()}");
Console.WriteLine($"{trustVerificationResult.GetResultString()}");
var timeOfTrustVerification = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc).AddSeconds(trustVerificationResult.GetTimeOfTrustVerification());
Console.WriteLine($"TimeOfTrustVerificationEnum: {trustVerificationResult.GetTimeOfTrustVerificationEnum()}");
Console.WriteLine($"TimeOfTrustVerification: {timeOfTrustVerification.ToString()} UTC");
if (trustVerificationResult.HasEmbeddedTimestampVerificationResult())
{
EmbeddedTimestampVerificationResult embeddedTimestampVerificationResult = trustVerificationResult.GetEmbeddedTimestampVerificationResult();
PrintEmbeddedTimestampVerificationResult(embeddedTimestampVerificationResult);
}
else
{
Console.WriteLine("EmbeddedTimestampVerificationResult: None");
}
var certPath = trustVerificationResult.GetCertPath();
if (certPath.Length > 0)
{
for (int i = 0; i < certPath.Length; ++i)
{
var cert = certPath[i];
Console.WriteLine("=======================================================================================================");
Console.WriteLine($"Certificate [{i + 1}]");
Console.WriteLine($"\t{cert.ToString()}");
Console.WriteLine("=======================================================================================================");
}
}
Console.WriteLine("=======================================================================================================");
Console.WriteLine("TrustVerificationResult End");
Console.WriteLine("=======================================================================================================");
}
private static void PrintEmbeddedTimestampVerificationResult(EmbeddedTimestampVerificationResult embeddedTimestampVerificationResult)
{
Console.WriteLine("=======================================================================================================");
Console.WriteLine("EmbeddedTimestampVerificationResult Begin");
Console.WriteLine("=======================================================================================================");
Console.WriteLine($"Verification status: {embeddedTimestampVerificationResult.GetVerificationStatus()}");
Console.WriteLine($"TrustStatus: {embeddedTimestampVerificationResult.GetTrustStatus()} : {embeddedTimestampVerificationResult.GetTrustStatusAsString()}");
Console.WriteLine($"CMSDigestStatus: {embeddedTimestampVerificationResult.GetCMSDigestStatus()} : {embeddedTimestampVerificationResult.GetCMSDigestStatusAsString()}");
Console.WriteLine($"CMSSignatureDigestAlgorithm: {embeddedTimestampVerificationResult.GetCMSSignatureDigestAlgorithm()}");
Console.WriteLine($"MessageImprintDigestStatus: {embeddedTimestampVerificationResult.GetMessageImprintDigestStatus()} : {embeddedTimestampVerificationResult.GetMessageImprintDigestStatusAsString()}");
Console.WriteLine($"MessageImprintDigestAlgorithm: {embeddedTimestampVerificationResult.GetMessageImprintDigestAlgorithm()}");
if (embeddedTimestampVerificationResult.HasTrustVerificationResult())
{
TrustVerificationResult trustVerificationResult = embeddedTimestampVerificationResult.GetTrustVerificationResult();
PrintTrustVerificationResult(trustVerificationResult);
}
string[] unsupportedFeatures = embeddedTimestampVerificationResult.GetUnsupportedFeatures();
if (unsupportedFeatures.Length > 0)
{
foreach (string s in unsupportedFeatures)
{
Console.WriteLine(s);
}
}
Console.WriteLine("=======================================================================================================");
Console.WriteLine("EmbeddedTimestampVerificationResult End");
Console.WriteLine("=======================================================================================================");
}
static void TestTSA(string tsaUrl, string[] tsaCertPaths, string tsaUsername, string tsaPassword)
{
TimestampingConfiguration timestampingConfiguration = new TimestampingConfiguration(tsaUrl);
if (!String.IsNullOrWhiteSpace(tsaUsername)) timestampingConfiguration.SetTimestampAuthorityServerUsername(tsaUsername);
if (!String.IsNullOrWhiteSpace(tsaPassword)) timestampingConfiguration.SetTimestampAuthorityServerPassword(tsaPassword);
VerificationOptions verificationOptions = new VerificationOptions(VerificationOptions.SignatureVerificationSecurityLevel.e_compatibility_and_archiving);
foreach (var tsaCertPath in tsaCertPaths)
{
var ext = System.IO.Path.GetExtension(tsaCertPath).ToLower();
if (ext.CompareTo(".fdf") == 0)
{
pdftron.FDF.FDFDoc fdfDoc = new pdftron.FDF.FDFDoc(tsaCertPath);
verificationOptions.LoadTrustList(fdfDoc);
}
if (ext.CompareTo(".cer") == 0 || ext.CompareTo(".crt") == 0)
{
verificationOptions.AddTrustedCertificate(tsaCertPath, (ushort)(VerificationOptions.CertificateTrustFlag.e_default_trust | VerificationOptions.CertificateTrustFlag.e_certification_trust));
}
}
/* 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). */
verificationOptions.SetRevocationTimeout(3000); // arbitrary 3 second time limit
var sw = new System.Diagnostics.Stopwatch();
sw.Start();
TimestampingResult timestampingResult = timestampingConfiguration.TestConfiguration(verificationOptions);
sw.Stop();
Console.WriteLine($"TimestampingConfiguration.TestConfiguration took {sw.ElapsedMilliseconds}ms");
Console.WriteLine("====================");
Console.WriteLine("TimestampingResult");
Console.WriteLine($"Result: [{timestampingResult.GetStatus()}] {timestampingResult.GetString()}");
if (timestampingResult.HasResponseVerificationResult())
{
EmbeddedTimestampVerificationResult embeddedTimestampVerificationResult = timestampingResult.GetResponseVerificationResult();
PrintEmbeddedTimestampVerificationResult(embeddedTimestampVerificationResult);
}
Console.WriteLine("====================");
}