private static DateTime GetValidationTime(this Timestamp value, DateTime?trustedTime) { return(trustedTime != null ? trustedTime.Value : value.Time); }
/// <summary> /// Validates the time-stamp token in case of arbitration or with a specified trusted time. /// </summary> /// <param name="tst"></param> /// <param name="crls"></param> /// <param name="ocsps"></param> /// <param name="trustedTime">The trusted time, <c>null</c> for the current time in case of Arbitration</param> /// <returns>The validation chain of the signing certificate</returns> /// <exception cref="InvalidTokenException">When the token isn't signed by the indicated certificate</exception> public static Timestamp Validate(this TimeStampToken tst, ref IList<CertificateList> crls, ref IList<BasicOcspResponse> ocsps, DateTime? trustedTime) { var value = new Timestamp(); value.TimestampStatus = new List<X509ChainStatus>(); //check if the indicated certificate is the signer BC::X509Certificate signerBc = tst.GetSigner(); if (signerBc == null) { trace.TraceEvent(TraceEventType.Warning, 0, "The signer of the time-stamp {0} isn't found", tst.TimeStampInfo.SerialNumber); X509ChainStatus status = new X509ChainStatus(); status.Status = X509ChainStatusFlags.NotSignatureValid; status.StatusInformation = "Signer not found"; X509CertificateHelper.AddErrorStatus(value.TimestampStatus, status); } else { try { tst.Validate(signerBc); } catch (Exception e) { trace.TraceEvent(TraceEventType.Warning, 0, "The signature from {1} of the time-stamp {0} is invalid: {2}", tst.TimeStampInfo.SerialNumber, signerBc.SubjectDN, e.Message); X509ChainStatus status = new X509ChainStatus(); status.Status = X509ChainStatusFlags.NotSignatureValid; status.StatusInformation = "Time-stamp not signed by indicated certificate: " + e.Message; X509CertificateHelper.AddErrorStatus(value.TimestampStatus, status); } } //Get some info DateTime now = DateTime.UtcNow; value.Time = tst.TimeStampInfo.GenTime; //allow for some clock skewness DateTime signingTime = value.Time > now && (value.Time - ClockSkewness) < now ? now : value.Time; DateTime validationTime = trustedTime != null ? trustedTime.Value : signingTime; var extraStore = new X509Certificate2Collection(); foreach (Org.BouncyCastle.X509.X509Certificate cert in tst.GetCertificates("Collection").GetMatches(null)) { extraStore.Add(new X509Certificate2(cert.GetEncoded())); } //Check the chain value.CertificateChain = (new X509Certificate2(signerBc.GetEncoded())).BuildChain(signingTime, extraStore, ref crls, ref ocsps, validationTime); //we assume time-stamp signers aren't suspended, only permanently revoked //get the renewal time value.RenewalTime = DateTime.MaxValue; foreach (ChainElement chainE in value.CertificateChain.ChainElements) { if (chainE.Certificate.NotAfter < value.RenewalTime) { value.RenewalTime = chainE.Certificate.NotAfter; } } //check if the certificate may be used for time-stamping IList signerExtKeyUsage = signerBc.GetExtendedKeyUsage(); if (!signerExtKeyUsage.Contains("1.3.6.1.5.5.7.3.8")) { trace.TraceEvent(TraceEventType.Warning, 0, "The signer {1} of the time-stamp {0} isn't allowed to sign timestamps", tst.TimeStampInfo.SerialNumber, signerBc.SubjectDN); X509ChainStatus status = new X509ChainStatus(); status.Status = X509ChainStatusFlags.NotValidForUsage; status.StatusInformation = "The certificate may not be used for timestamps"; X509CertificateHelper.AddErrorStatus(value.TimestampStatus, status); } if (value.TimestampStatus.Count == 0) { X509ChainStatus status = new X509ChainStatus(); status.Status = X509ChainStatusFlags.NoError; value.TimestampStatus.Add(status); } return value; }