public Stream Complete(Stream sealedData, out TimemarkKey timemarkKey) { #if NETFRAMEWORK trace.TraceEvent(TraceEventType.Information, 0, "Completing the provided sealed message with revocation and time info according to the level {0}", this.level); #else logger.LogInformation("Completing the provided sealed message with revocation and time info according to the level {0}", this.level); #endif ITempStreamFactory factory = NewFactory(sealedData); Stream completed = factory.CreateNew(); Complete(this.level, completed, sealedData, null, null, out timemarkKey); completed.Position = 0; return(completed); }
protected void Complete(Level?level, Stream embedded, Stream signed, Stream content, X509Certificate2 providedSigner, out TimemarkKey timemarkKey) { #if NETFRAMEWORK trace.TraceEvent(TraceEventType.Information, 0, "Completing the message with of {0} bytes to level {1}", signed.Length, level); #else logger.LogInformation("Completing the message with of {0} bytes to level {1}", signed.Length, level); #endif //Create the objects we need var gen = new CmsSignedDataStreamGenerator(); var parser = new CmsSignedDataParser(signed); timemarkKey = new TimemarkKey(); //preset the digests so we can add the signers afterwards gen.AddDigests(parser.DigestOids); //Copy the content to the output Stream contentOut = gen.Open(embedded, parser.SignedContentType.Id, true); if (content != null) { content.CopyTo(contentOut); } else { parser.GetSignedContent().ContentStream.CopyTo(contentOut); } //Extract the various data from outer layer SignerInformation signerInfo = ExtractSignerInfo(parser); IX509Store embeddedCerts = parser.GetCertificates("Collection"); //Extract the various data from signer info timemarkKey.SignatureValue = signerInfo.GetSignature(); timemarkKey.SigningTime = ExtractSigningTime(signerInfo); timemarkKey.Signer = ExtractSignerCert(embeddedCerts, signerInfo, providedSigner); if (timemarkKey.Signer != null) { timemarkKey.SignerId = DotNetUtilities.FromX509Certificate(timemarkKey.Signer).GetSubjectKeyIdentifier(); } else { timemarkKey.SignerId = signerInfo.SignerID.ExtractSignerId(); } //Extract the various data from unsiged attributes of signer info IDictionary unsignedAttributes = signerInfo.UnsignedAttributes != null?signerInfo.UnsignedAttributes.ToDictionary() : new Hashtable(); TimeStampToken tst = ExtractTimestamp(unsignedAttributes); RevocationValues revocationInfo = ExtractRevocationInfo(unsignedAttributes); //quick check for an expected error and extrapolate some info if (timemarkKey.SignerId == null) { #if NETFRAMEWORK trace.TraceEvent(TraceEventType.Error, 0, "We could not find any signer information"); #else logger.LogError("We could not find any signer information"); #endif throw new InvalidMessageException("The message does not contain any valid signer info"); } if (timemarkKey.SigningTime == default && tst != null) { #if NETFRAMEWORK trace.TraceEvent(TraceEventType.Information, 0, "Implicit signing time is replaced with time-stamp time {1}", tst.TimeStampInfo.GenTime); #else logger.LogInformation("Implicit signing time is replaced with time-stamp time {1}", tst.TimeStampInfo.GenTime); #endif timemarkKey.SigningTime = tst.TimeStampInfo.GenTime; } //Are we missing embedded certs and should we add them? if ((embeddedCerts == null || embeddedCerts.GetMatches(null).Count <= 1) && timemarkKey.Signer != null && level != null) { embeddedCerts = GetEmbeddedCerts(timemarkKey); } if (embeddedCerts != null) { gen.AddCertificates(embeddedCerts); //add the existing or new embedded certs to the output. } //Are we missing timestamp and should we add them (not that time-mark authorities do not require a timestamp provider) if (tst == null && (level & Level.T_Level) == Level.T_Level && timestampProvider != null) { tst = GetTimestamp(timemarkKey); AddTimestamp(unsignedAttributes, tst); } //should be make sure we have the proper revocation info (it is hard to tell if we have everything, just go for it) if ((level & Level.L_Level) == Level.L_Level) { if (embeddedCerts != null && embeddedCerts.GetMatches(null).Count > 0) { //extend the revocation info with info about the embedded certs revocationInfo = GetRevocationValues(timemarkKey, embeddedCerts, revocationInfo); } if (tst != null) { //extend the revocation info with info about the TST revocationInfo = GetRevocationValues(tst, revocationInfo); } //update the unsigned attributes AddRevocationValues(unsignedAttributes, revocationInfo); } //Update the unsigned attributes of the signer info signerInfo = SignerInformation.ReplaceUnsignedAttributes(signerInfo, new BC::Asn1.Cms.AttributeTable(unsignedAttributes)); //Copy the signer gen.AddSigners(new SignerInformationStore(new SignerInformation[] { signerInfo })); contentOut.Close(); }