public async Task <Rfc3161TimestampToken> GetAndSetRfc3161Timestamp(SignedCms signedData, Uri timeStampAuthorityUri) { if (timeStampAuthorityUri == null) { throw new ArgumentNullException(nameof(timeStampAuthorityUri)); } // This example figures out which signer is new by it being "the only signer" if (signedData.SignerInfos.Count > 1) { throw new ArgumentException(Resources.TooManySignInfos, nameof(signedData)); } var newSignerInfo = signedData.SignerInfos[0]; byte[] nonce = new byte[8]; using (var rng = RandomNumberGenerator.Create()) { rng.GetBytes(nonce); } var request = Rfc3161TimestampRequest.CreateFromSignerInfo( newSignerInfo, HashAlgorithmName.SHA384, requestSignerCertificates: true, nonce: nonce); var client = _httpClientFunc.Invoke(); var content = new ReadOnlyMemoryContent(request.Encode()); content.Headers.ContentType = new MediaTypeHeaderValue("application/timestamp-query"); var httpResponse = await client.PostAsync(timeStampAuthorityUri, content).ConfigureAwait(false); if (!httpResponse.IsSuccessStatusCode) { throw new SignClientException( $"There was a error from the timestamp authority. It responded with {httpResponse.StatusCode} {(int)httpResponse.StatusCode}"); } if (httpResponse.Content.Headers.ContentType.MediaType != "application/timestamp-reply") { throw new SignClientException(Resources.InvalidTimestampReply); } var data = await httpResponse.Content.ReadAsByteArrayAsync().ConfigureAwait(false); var timestampToken = request.ProcessResponse(data, out _); newSignerInfo.UnsignedAttributes.Add(new AsnEncodedData(CertificateHelper.SignatureTimeStampOin, timestampToken.AsSignedCms().Encode())); return(timestampToken); }
public static async Task <byte[]> SignWithRfc3161(byte[] bytesToSign, bool isDetached, X509Certificate2 certificate, Uri timeStampAuthorityUri) { // Sign our contents. var contentInfo = new ContentInfo(bytesToSign); var cms = new SignedCms(contentInfo, isDetached); var signer = new CmsSigner(certificate); // { IncludeOption = X509IncludeOption.WholeChain }; //X509IncludeOption.EndCertOnly; signer.SignedAttributes.Add(new Pkcs9SigningTime()); cms.ComputeSignature(signer, false); // Generate our nonce byte[] nonce = new byte[8]; using (var rng = RandomNumberGenerator.Create()) { rng.GetBytes(nonce); } // Get our signing information and create the RFC3161 request SignerInfo newSignerInfo = cms.SignerInfos[0]; // Now we generate our request for us to send to our RFC3161 signing authority. Rfc3161TimestampRequest request = Rfc3161TimestampRequest.CreateFromSignerInfo(newSignerInfo, HashAlgorithmName.SHA256, requestSignerCertificates: true, nonce: nonce); // You can use your own web request system, in this example we are just going to use a `HttpClient` class. var client = new HttpClient(); var content = new ReadOnlyMemoryContent(request.Encode()); content.Headers.ContentType = new MediaTypeHeaderValue("application/timestamp-query"); var httpResponse = await client.PostAsync(timeStampAuthorityUri, content).ConfigureAwait(false); // Process our response if (!httpResponse.IsSuccessStatusCode) { throw new CryptographicException("There was a error from the timestamp authority. It responded with {httpResponse.StatusCode} {(int)httpResponse.StatusCode}: {httpResponse.Content}"); } if (httpResponse.Content.Headers.ContentType.MediaType != "application/timestamp-reply") { throw new CryptographicException("The reply from the time stamp server was in a invalid format."); } var data = await httpResponse.Content.ReadAsByteArrayAsync().ConfigureAwait(false); var timestampToken = request.ProcessResponse(data, out _); // The RFC3161 sign certificate is separate to the contents that was signed, we need to add it to the unsigned attributes. newSignerInfo.UnsignedAttributes.Add(new AsnEncodedData(SignatureTimeStampOin, timestampToken.AsSignedCms().Encode())); return(cms.Encode()); }
private async Task CreateTimeStamp(SignedCms signedCms) { // See: https://www.glennwatson.net/posts/rfc-3161-signing const string timeStampAuthorityUri = "http://time.certum.pl/"; byte[] nonce = new byte[8]; using (RandomNumberGenerator rng = RandomNumberGenerator.Create()) { rng.GetBytes(nonce); } SignerInfo newSignerInfo = signedCms.SignerInfos[0]; Rfc3161TimestampRequest?request = Rfc3161TimestampRequest.CreateFromSignerInfo( newSignerInfo, HashAlgorithmName.SHA256, requestSignerCertificates: true, nonce: nonce); using HttpClient client = new HttpClient(); using ReadOnlyMemoryContent content = new ReadOnlyMemoryContent(request.Encode()); content.Headers.ContentType = new MediaTypeHeaderValue("application/timestamp-query"); using HttpResponseMessage? httpResponse = await client.PostAsync(timeStampAuthorityUri, content).ConfigureAwait(false); if (!httpResponse.IsSuccessStatusCode) { throw new CryptographicException($"There was a error from the timestamp authority. It responded with {httpResponse.StatusCode} {(int)httpResponse.StatusCode}: {httpResponse.Content}"); } if (httpResponse.Content.Headers.ContentType.MediaType != "application/timestamp-reply") { throw new CryptographicException("The reply from the time stamp server was in a invalid format."); } byte[]? data = await httpResponse.Content.ReadAsByteArrayAsync().ConfigureAwait(false); Rfc3161TimestampToken?timestampToken = request.ProcessResponse(data, out _); Oid signatureTimeStampOid = new Oid("1.2.840.113549.1.9.16.2.14"); newSignerInfo.AddUnsignedAttribute(new AsnEncodedData(signatureTimeStampOid, timestampToken.AsSignedCms().Encode())); }
public static void BuildFromSignerInfo() { ContentInfo content = new ContentInfo(new byte[] { 1, 2, 3, 4 }); SignedCms cms = new SignedCms(content, false); using (X509Certificate2 signerCert = Certificates.RSAKeyTransferCapi1.TryGetCertificateWithPrivateKey()) { CmsSigner signer = new CmsSigner(SubjectIdentifierType.SubjectKeyIdentifier, signerCert); signer.SignedAttributes.Add(new Pkcs9SigningTime()); cms.ComputeSignature(signer); } SignerInfo signerInfo = cms.SignerInfos[0]; byte[] sig = signerInfo.GetSignature(); Rfc3161TimestampRequest fromSigner = Rfc3161TimestampRequest.CreateFromSignerInfo(signerInfo, HashAlgorithmName.SHA256); Rfc3161TimestampRequest fromData = Rfc3161TimestampRequest.CreateFromData(sig, HashAlgorithmName.SHA256); Assert.Equal(fromData.Encode().ByteArrayToHex(), fromSigner.Encode().ByteArrayToHex()); }
public static void BuildFromNullSignerInfo() { AssertExtensions.Throws <ArgumentNullException>( "signerInfo", () => Rfc3161TimestampRequest.CreateFromSignerInfo(null, HashAlgorithmName.SHA256)); }