예제 #1
0
        private void VerifySimpleDecrypt(byte[] encodedMessage, CertLoader certLoader, ContentInfo expectedContent)
        {
            EnvelopedCms ecms = new EnvelopedCms();

            ecms.Decode(encodedMessage);

            using (X509Certificate2 cert = certLoader.TryGetCertificateWithPrivateKey())
            {
                if (cert == null)
                {
                    return; // Sorry - CertLoader is not configured to load certs with private keys - we've tested as much as we can.
                }
#if netcoreapp              // API not present on netfx
                if (_useExplicitPrivateKey)
                {
                    using (X509Certificate2 pubCert = certLoader.GetCertificate())
                    {
                        RecipientInfo recipient = ecms.RecipientInfos.Cast <RecipientInfo>().Where((r) => r.RecipientIdentifier.MatchesCertificate(cert)).Single();
                        ecms.Decrypt(recipient, cert.PrivateKey);
                    }
                }
                else
#endif
                {
                    X509Certificate2Collection extraStore = new X509Certificate2Collection(cert);
                    ecms.Decrypt(extraStore);
                }
                ContentInfo contentInfo = ecms.ContentInfo;
                Assert.Equal(expectedContent.ContentType.Value, contentInfo.ContentType.Value);
                Assert.Equal(expectedContent.Content.ByteArrayToHex(), contentInfo.Content.ByteArrayToHex());
            }
        }
예제 #2
0
        private static void Assert_Certificate_Roundtrip(CertLoader certificateLoader)
        {
            ContentInfo  contentInfo = new ContentInfo(new byte[] { 1, 2, 3 });
            EnvelopedCms ecms        = new EnvelopedCms(contentInfo);

            using (X509Certificate2 cert = certificateLoader.GetCertificate())
            {
                CmsRecipient recipient = new CmsRecipient(cert);
                ecms.Encrypt(recipient);
            }

            byte[] encodedMessage = ecms.Encode();

            ecms = new EnvelopedCms();
            ecms.Decode(encodedMessage);

            using (X509Certificate2 privateCert = certificateLoader.TryGetCertificateWithPrivateKey())
            {
                if (privateCert == null)
                {
                    return; // CertLoader can't load the private certificate.
                }
                ecms.Decrypt(new X509Certificate2Collection(privateCert));
            }
            Assert.Equal(contentInfo.ContentType.Value, ecms.ContentInfo.ContentType.Value);
            Assert.Equal <byte>(contentInfo.Content, ecms.ContentInfo.Content);
        }
        public static void DecryptMultipleRecipients()
        {
            // Force Decrypt() to try multiple recipients. Ensure that a failure to find a matching cert in one doesn't cause it to quit early.

            CertLoader[] certLoaders = new CertLoader[]
            {
                Certificates.RSAKeyTransfer1,
                Certificates.RSAKeyTransfer2,
                Certificates.RSAKeyTransfer3,
            };

            byte[]                 content    = { 6, 3, 128, 33, 44 };
            EnvelopedCms           ecms       = new EnvelopedCms(new ContentInfo(content), new AlgorithmIdentifier(new Oid(Oids.Aes256)));
            CmsRecipientCollection recipients = new CmsRecipientCollection();

            foreach (CertLoader certLoader in certLoaders)
            {
                recipients.Add(new CmsRecipient(certLoader.GetCertificate()));
            }
            ecms.Encrypt(recipients);
            byte[] encodedMessage = ecms.Encode();

            ecms = new EnvelopedCms();
            ecms.Decode(encodedMessage);

            // How do we know that Decrypt() tries receipients in the order they appear in ecms.RecipientInfos? Because we wrote the implementation.
            // Not that some future implementation can't ever change it but it's the best guess we have.
            RecipientInfo me = ecms.RecipientInfos[2];

            CertLoader matchingCertLoader = null;

            for (int index = 0; index < recipients.Count; index++)
            {
                if (recipients[index].Certificate.Issuer == ((X509IssuerSerial)(me.RecipientIdentifier.Value)).IssuerName)
                {
                    matchingCertLoader = certLoaders[index];
                    break;
                }
            }
            Assert.NotNull(matchingCertLoader);

            using (X509Certificate2 cert = matchingCertLoader.TryGetCertificateWithPrivateKey())
            {
                if (cert == null)
                {
                    return; // Sorry - CertLoader is not configured to load certs with private keys - we've tested as much as we can.
                }
                X509Certificate2Collection extraStore = new X509Certificate2Collection();
                extraStore.Add(cert);
                ecms.Decrypt(extraStore);
            }

            ContentInfo contentInfo = ecms.ContentInfo;

            Assert.Equal <byte>(content, contentInfo.Content);
        }
예제 #4
0
        public void EncryptToNegativeSerialNumber()
        {
            CertLoader negativeSerial = Certificates.NegativeSerialNumber;

            const string expectedSerial = "FD319CB1514B06AF49E00522277E43C8";

            byte[]       content     = { 1, 2, 3 };
            ContentInfo  contentInfo = new ContentInfo(content);
            EnvelopedCms cms         = new EnvelopedCms(contentInfo);

            using (X509Certificate2 cert = negativeSerial.GetCertificate())
            {
                Assert.Equal(expectedSerial, cert.SerialNumber);

                CmsRecipient recipient = new CmsRecipient(SubjectIdentifierType.IssuerAndSerialNumber, cert);
                cms.Encrypt(recipient);
            }

            EnvelopedCms cms2 = new EnvelopedCms();

            cms2.Decode(cms.Encode());

            RecipientInfoCollection recipients = cms2.RecipientInfos;

            Assert.Equal(1, recipients.Count);

            RecipientInfo recipientInfo = recipients[0];

            Assert.Equal(SubjectIdentifierType.IssuerAndSerialNumber, recipientInfo.RecipientIdentifier.Type);

            X509IssuerSerial issuerSerial = (X509IssuerSerial)recipientInfo.RecipientIdentifier.Value;

            Assert.Equal(expectedSerial, issuerSerial.SerialNumber);

            using (X509Certificate2 cert = negativeSerial.TryGetCertificateWithPrivateKey())
            {
                Assert.Equal(expectedSerial, cert.SerialNumber);

                cms2.Decrypt(new X509Certificate2Collection(cert));
            }

            Assert.Equal(content, cms2.ContentInfo.Content);
        }
예제 #5
0
        private static void VerifySimpleDecrypt(byte[] encodedMessage, CertLoader certLoader, ContentInfo expectedContent)
        {
            EnvelopedCms ecms = new EnvelopedCms();

            ecms.Decode(encodedMessage);

            using (X509Certificate2 cert = certLoader.TryGetCertificateWithPrivateKey())
            {
                if (cert == null)
                {
                    return; // Sorry - CertLoader is not configured to load certs with private keys - we've tested as much as we can.
                }
                X509Certificate2Collection extraStore = new X509Certificate2Collection(cert);
                ecms.Decrypt(extraStore);
                ContentInfo contentInfo = ecms.ContentInfo;
                Assert.Equal(expectedContent.ContentType.Value, contentInfo.ContentType.Value);
                Assert.Equal <byte>(expectedContent.Content, contentInfo.Content);
            }
        }
예제 #6
0
        private static byte[] BuildCustomToken(
            CertLoader cert,
            DateTimeOffset timestamp,
            SigningCertificateOption v1Option,
            SigningCertificateOption v2Option,
            HashAlgorithmName v2DigestAlg        = default,
            X509IncludeOption includeOption      = X509IncludeOption.ExcludeRoot,
            SubjectIdentifierType identifierType = SubjectIdentifierType.IssuerAndSerialNumber)
        {
            long accuracyMicroSeconds = (long)(TimeSpan.FromMinutes(1).TotalMilliseconds * 1000);

            byte[] serialNumber = BitConverter.GetBytes(DateTimeOffset.UtcNow.Ticks);
            Array.Reverse(serialNumber);

            Rfc3161TimestampTokenInfo info = new Rfc3161TimestampTokenInfo(
                new Oid("0.0", "0.0"),
                new Oid(Oids.Sha384),
                new byte[384 / 8],
                serialNumber,
                timestamp,
                accuracyMicroSeconds,
                isOrdering: true);

            ContentInfo contentInfo = new ContentInfo(new Oid(Oids.TstInfo, Oids.TstInfo), info.Encode());
            SignedCms   cms         = new SignedCms(contentInfo);

            using (X509Certificate2 tsaCert = cert.TryGetCertificateWithPrivateKey())
            {
                CmsSigner signer = new CmsSigner(identifierType, tsaCert)
                {
                    IncludeOption = includeOption
                };

                if (v1Option != SigningCertificateOption.Omit)
                {
                    ExpandOption(v1Option, out bool validHash, out bool skipIssuerSerial, out bool validName, out bool validSerial);

                    // simple SigningCertificate
                    byte[] signingCertificateV1Bytes =
                        "301A3018301604140000000000000000000000000000000000000000".HexToByteArray();

                    if (validHash)
                    {
                        byte[] hash = SHA1.HashData(tsaCert.RawData);

                        Buffer.BlockCopy(
                            hash,
                            0,
                            signingCertificateV1Bytes,
                            signingCertificateV1Bytes.Length - hash.Length,
                            hash.Length);
                    }

                    if (!skipIssuerSerial)
                    {
                        byte[] footer = BuildIssuerAndSerialNumber(tsaCert, validName, validSerial);

                        signingCertificateV1Bytes[1] += (byte)footer.Length;
                        signingCertificateV1Bytes[3] += (byte)footer.Length;
                        signingCertificateV1Bytes[5] += (byte)footer.Length;

                        Assert.InRange(signingCertificateV1Bytes[1], 0, 127);

                        signingCertificateV1Bytes = signingCertificateV1Bytes.Concat(footer).ToArray();
                    }

                    signer.SignedAttributes.Add(
                        new AsnEncodedData("1.2.840.113549.1.9.16.2.12", signingCertificateV1Bytes));
                }

                if (v2Option != SigningCertificateOption.Omit)
                {
                    byte[] attrBytes;
                    byte[] algBytes = Array.Empty <byte>();
                    byte[] hashBytes;
                    byte[] issuerNameBytes = Array.Empty <byte>();

                    if (v2DigestAlg != default)
                    {
                        switch (v2DigestAlg.Name)
                        {
                        case "MD5":
                            algBytes = "300C06082A864886F70D02050500".HexToByteArray();
                            break;

                        case "SHA1":
                            algBytes = "300906052B0E03021A0500".HexToByteArray();
                            break;

                        case "SHA256":
                            // Invalid under DER, because it's the default.
                            algBytes = "300D06096086480165030402010500".HexToByteArray();
                            break;

                        case "SHA384":
                            algBytes = "300D06096086480165030402020500".HexToByteArray();
                            break;

                        case "SHA512":
                            algBytes = "300D06096086480165030402030500".HexToByteArray();
                            break;

                        default:
                            throw new NotSupportedException(v2DigestAlg.Name);
                        }
                    }
                    else
                    {
                        v2DigestAlg = HashAlgorithmName.SHA256;
                    }

                    hashBytes = tsaCert.GetCertHash(v2DigestAlg);

                    ExpandOption(v2Option, out bool validHash, out bool skipIssuerSerial, out bool validName, out bool validSerial);

                    if (!validHash)
                    {
                        hashBytes[0] ^= 0xFF;
                    }

                    if (!skipIssuerSerial)
                    {
                        issuerNameBytes = BuildIssuerAndSerialNumber(tsaCert, validName, validSerial);
                    }

                    // hashBytes hasn't been wrapped in an OCTET STRING yet, so add 2 more.
                    int payloadSize = algBytes.Length + hashBytes.Length + issuerNameBytes.Length + 2;
                    Assert.InRange(payloadSize, 0, 123);

                    attrBytes = new byte[payloadSize + 6];

                    int index = 0;

                    // SEQUENCE (SigningCertificateV2)
                    attrBytes[index++] = 0x30;
                    attrBytes[index++] = (byte)(payloadSize + 4);

                    // SEQUENCE OF => certs
                    attrBytes[index++] = 0x30;
                    attrBytes[index++] = (byte)(payloadSize + 2);

                    // SEQUENCE (ESSCertIdV2)
                    attrBytes[index++] = 0x30;
                    attrBytes[index++] = (byte)payloadSize;

                    Buffer.BlockCopy(algBytes, 0, attrBytes, index, algBytes.Length);
                    index += algBytes.Length;

                    // OCTET STRING (Hash)
                    attrBytes[index++] = 0x04;
                    attrBytes[index++] = (byte)hashBytes.Length;
                    Buffer.BlockCopy(hashBytes, 0, attrBytes, index, hashBytes.Length);
                    index += hashBytes.Length;

                    Buffer.BlockCopy(issuerNameBytes, 0, attrBytes, index, issuerNameBytes.Length);

                    signer.SignedAttributes.Add(
                        new AsnEncodedData("1.2.840.113549.1.9.16.2.47", attrBytes));
                }

                cms.ComputeSignature(signer);
            }

            return(cms.Encode());
        }