/// <summary> /// Attaches a timestamp to signed CMS object. /// </summary> /// <param name="timestamp">TSP response returned from Time-Stamping Authority.</param> /// <param name="signerInfoIndex">Signature index to attach the timestamp.</param> /// <exception cref="NotSupportedException"> /// Time-Stamp Response contains invalid content type. /// </exception> /// <exception cref="ArgumentException"> /// Data returned from Time-Stamping Authority does not contain valid response. /// </exception> /// <exception cref="ArgumentNullException"> /// <strong>response</strong> parameter is null. /// </exception> /// <exception cref="IndexOutOfRangeException"> /// <strong>signerInfoIndex</strong> value exceeds the number of attached signatures. /// </exception> /// <remarks>Call <see cref="Encode"/> method to get timestamped object.</remarks> public void AddTimestamp(TspResponse timestamp, Int32 signerInfoIndex) { if (timestamp == null) { throw new ArgumentNullException(nameof(timestamp)); } if (timestamp.Status.ResponseStatus != TspResponseStatus.Granted || timestamp.Status.ErrorCode != TspFailureStatus.None) { throw new ArgumentException("The time-stamp response is not successful."); } X509Attribute attribute; DefaultSignedPkcs7 tspCms = timestamp.GetSignedCms(); switch (timestamp.ResponseType.Value) { case PKCS_7_DATA: // add timestamp signing certs to original CMS foreach (X509Certificate2 tspCert in tspCms.Certificates) { if (!Certificates.Contains(tspCert)) { Certificates.Add(tspCert); } } // for Authenticode timestamp, we add SignerInfo from timestamp CMS var asn = new Asn1Reader(tspCms.SignerInfos.Encode()); attribute = new X509Attribute(new Oid(COUNTER_SIGN), asn.GetPayload()); break; case TST_TOKEN_INFO: attribute = new X509Attribute(new Oid(RFC_COUNTER_SIGN), tspCms.RawData); break; default: throw new NotSupportedException("Time-Stamp response contains invalid content type."); } var signerInfoBuilder = new PkcsSignerInfoBuilder(SignerInfos[signerInfoIndex]); X509Attribute attr = signerInfoBuilder.UnauthenticatedAttributes[COUNTER_SIGN]; if (attr != null) { signerInfoBuilder.UnauthenticatedAttributes.Remove(attr); } attr = signerInfoBuilder.UnauthenticatedAttributes[RFC_COUNTER_SIGN]; if (attr != null) { signerInfoBuilder.UnauthenticatedAttributes.Remove(attr); } signerInfoBuilder.AddUnauthenticatedAttribute(attribute); SignerInfos[signerInfoIndex] = signerInfoBuilder.Encode(); }
/// <summary> /// Initializes a new instance of <strong>SignedCmsBuilder</strong> from existing Signed CMS. Data from existing CMS /// is copied to builder and can be modified. /// </summary> /// <param name="cms">Existing Signed CMS message.</param> /// <exception cref="ArgumentNullException"> /// <srong>cms</srong> parameter is null. /// </exception> public SignedCmsBuilder(DefaultSignedPkcs7 cms) { if (cms == null) { throw new ArgumentNullException(nameof(cms)); } _contentType = cms.ContentType; _content = cms.Content; DigestAlgorithms.AddRange(cms.DigestAlgorithms); Certificates.AddRange(cms.Certificates); RevocationLists.AddRange(cms.RevocationLists); SignerInfos.AddRange(cms.SignerInfos); }