Exemplo n.º 1
0
    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());
    }
Exemplo n.º 2
0
        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());
        }
Exemplo n.º 3
0
        private static void VerifyExpectedRequest(Rfc3161TimestampRequest request, bool viaSpan)
        {
            // Captured with Fiddler from a CryptRetrieveTimestamp call
            const string ExpectedHex =
                "30390201013031300D06096086480165030402010500042011806C2441295EA6" +
                "97EA96EE4247C0F9C71EE7638863CB8E29CD941A488FCB5A0101FF";

            Assert.Equal(1, request.Version);
            Assert.Equal(
                "11806C2441295EA697EA96EE4247C0F9C71EE7638863CB8E29CD941A488FCB5A",
                request.GetMessageHash().ByteArrayToHex());

            Assert.False(request.GetNonce().HasValue, "request.GetNonce().HasValue");
            Assert.Equal("2.16.840.1.101.3.4.2.1", request.HashAlgorithmId.Value);
            Assert.Null(request.RequestedPolicyId);
            Assert.True(request.RequestSignerCertificate, "request.RequestSignerCertificate");
            Assert.False(request.HasExtensions);

            if (viaSpan)
            {
                // Twice as big as it needs to be.
                byte[] buf = new byte[ExpectedHex.Length];

                const byte FillByte = 0x55;
                buf.AsSpan().Fill(FillByte);

                // Too small
                Assert.False(request.TryEncode(Span <byte> .Empty, out int bytesWritten));
                Assert.Equal(0, bytesWritten);

                const int WriteOffset = 7;

                // Too small
                Span <byte> dest = new Span <byte>(buf, WriteOffset, (ExpectedHex.Length / 2) - 1);
                Assert.False(request.TryEncode(dest, out bytesWritten));
                Assert.Equal(0, bytesWritten);

                Assert.Equal(new string('5', buf.Length * 2), buf.ByteArrayToHex());

                // Bigger than needed
                dest = new Span <byte>(buf, WriteOffset, buf.Length - WriteOffset);
                Assert.True(request.TryEncode(dest, out bytesWritten));
                Assert.Equal(ExpectedHex.Length / 2, bytesWritten);
                Assert.Equal(ExpectedHex, dest.Slice(0, bytesWritten).ByteArrayToHex());

                Assert.Equal(FillByte, buf[WriteOffset - 1]);
                Assert.Equal(FillByte, buf[WriteOffset + bytesWritten]);

                // Reset
                dest.Fill(FillByte);

                // Perfectly sized
                dest = dest.Slice(0, bytesWritten);
                Assert.True(request.TryEncode(dest, out bytesWritten));
                Assert.Equal(ExpectedHex.Length / 2, bytesWritten);
                Assert.Equal(ExpectedHex, dest.ByteArrayToHex());

                Assert.Equal(FillByte, buf[WriteOffset - 1]);
                Assert.Equal(FillByte, buf[WriteOffset + bytesWritten]);
            }
            else
            {
                byte[] encoded = request.Encode();

                Assert.Equal(ExpectedHex, encoded.ByteArrayToHex());
            }
        }