예제 #1
0
        public static void ReadCustomType()
        {
            byte[] input = (
                "3033020103302E06092A864886F70D010701A021041F301D301B06092A864886" +
                "F70D010701A00E040C300A3008060100A003040102").HexToByteArray();

            Pkcs12Info info = Pkcs12Info.Decode(input, out _, skipCopy: true);

            Assert.Equal(Pkcs12IntegrityMode.None, info.IntegrityMode);

            ReadOnlyCollection <Pkcs12SafeContents> allContents = info.AuthenticatedSafe;

            Assert.Equal(1, allContents.Count);

            Pkcs12SafeContents contents = allContents[0];

            Assert.Equal(Pkcs12ConfidentialityMode.None, contents.ConfidentialityMode);

            List <Pkcs12SafeBag> bags = contents.GetBags().ToList();

            Assert.Equal(1, bags.Count);

            Pkcs12SafeBag bag = bags[0];

            Assert.IsNotType <Pkcs12CertBag>(bag);
            Assert.IsNotType <Pkcs12KeyBag>(bag);
            Assert.IsNotType <Pkcs12SecretBag>(bag);
            Assert.IsNotType <Pkcs12ShroudedKeyBag>(bag);

            CustomBagType customBag = new CustomBagType(bag.EncodedBagValue);

            Assert.Equal(2, customBag.Value);
        }
예제 #2
0
        public void SameCertTwice_NoKeys(bool addLocalKeyId)
        {
            string pw = nameof(SameCertTwice_NoKeys);

            using (var cert = new X509Certificate2(TestData.MsCertificate))
            {
                Pkcs12Builder      builder      = new Pkcs12Builder();
                Pkcs12SafeContents certContents = new Pkcs12SafeContents();

                Pkcs12SafeBag certBag  = certContents.AddCertificate(cert);
                Pkcs12SafeBag certBag2 = certContents.AddCertificate(cert);

                if (addLocalKeyId)
                {
                    certBag.Attributes.Add(s_keyIdOne);
                    certBag2.Attributes.Add(s_keyIdOne);
                }

                AddContents(certContents, builder, pw, encrypt: true);
                builder.SealWithMac(pw, s_digestAlgorithm, MacCount);
                byte[] pfxBytes = builder.Encode();

                ReadMultiPfx(
                    pfxBytes,
                    pw,
                    cert,
                    new[] { cert, cert });
            }
        }
예제 #3
0
        private static void CheckOracleSecretBag(
            Pkcs12SafeBag safeBag,
            string key,
            string value,
            string keyId)
        {
            Pkcs12SecretBag secretBag = Assert.IsType <Pkcs12SecretBag>(safeBag);

            Assert.Equal("1.2.840.113549.1.16.12.12", secretBag.GetSecretType().Value);

            Assert.Equal(
                MakeOracleKeyValuePairHex(key, value),
                secretBag.SecretValue.ByteArrayToHex());

            CryptographicAttributeObjectCollection attrs = secretBag.Attributes;

            Assert.Equal(1, attrs.Count);
            CryptographicAttributeObject firstAttr = attrs[0];

            Assert.Equal(Oids.LocalKeyId, firstAttr.Oid.Value);
            Assert.Equal(1, firstAttr.Values.Count);
            Pkcs9LocalKeyId localKeyId = Assert.IsType <Pkcs9LocalKeyId>(firstAttr.Values[0]);

            Assert.Equal(keyId, localKeyId.KeyId.ByteArrayToHex());
        }
예제 #4
0
        public void CertTwice_KeyOnce(bool addLocalKeyId)
        {
            string pw = nameof(CertTwice_KeyOnce);

            using (var cert = new X509Certificate2(TestData.PfxData, TestData.PfxDataPassword, s_exportableImportFlags))
                using (RSA key = cert.GetRSAPrivateKey())
                {
                    Pkcs12Builder      builder      = new Pkcs12Builder();
                    Pkcs12SafeContents keyContents  = new Pkcs12SafeContents();
                    Pkcs12SafeContents certContents = new Pkcs12SafeContents();

                    Pkcs12SafeBag keyBag   = keyContents.AddShroudedKey(key, pw, s_windowsPbe);
                    Pkcs12SafeBag certBag  = certContents.AddCertificate(cert);
                    Pkcs12SafeBag certBag2 = certContents.AddCertificate(cert);

                    if (addLocalKeyId)
                    {
                        certBag.Attributes.Add(s_keyIdOne);
                        certBag2.Attributes.Add(s_keyIdOne);
                        keyBag.Attributes.Add(s_keyIdOne);
                    }

                    AddContents(keyContents, builder, pw, encrypt: false);
                    AddContents(certContents, builder, pw, encrypt: true);
                    builder.SealWithMac(pw, s_digestAlgorithm, MacCount);
                    byte[] pfxBytes = builder.Encode();

                    ReadUnreadablePfx(
                        pfxBytes,
                        pw,
                        // NTE_BAD_DATA
                        -2146893819);
                }
        }
예제 #5
0
        private static void ProcessAttributes(
            IndentedTextWriter writer,
            Pkcs12SafeBag bag,
            string scopeId,
            IDictionary <string, List <string> > keyMatches)
        {
            writer.WriteLine("Attributes:");
            writer.Indent++;
            bool firstAttr = true;

            foreach (CryptographicAttributeObject attrGroup in bag.Attributes)
            {
                foreach (AsnEncodedData attr in attrGroup.Values)
                {
                    if (!firstAttr)
                    {
                        writer.WriteLine();
                    }

                    firstAttr = false;

                    ProcessAttribute(writer, attr, scopeId, keyMatches);
                }
            }

            if (firstAttr)
            {
                writer.WriteLine("No attributes present.");
            }
        }
예제 #6
0
        public void TwoCerts_CrossedKeys()
        {
            string pw = nameof(SameCertTwice_NoKeys);

            using (var cert = new X509Certificate2(TestData.PfxData, TestData.PfxDataPassword, s_exportableImportFlags))
                using (var cert2 = new X509Certificate2(TestData.MsCertificate))
                    using (RSA key = cert.GetRSAPrivateKey())
                    {
                        Pkcs12Builder      builder      = new Pkcs12Builder();
                        Pkcs12SafeContents keyContents  = new Pkcs12SafeContents();
                        Pkcs12SafeContents certContents = new Pkcs12SafeContents();

                        Pkcs12SafeBag keyBag   = keyContents.AddShroudedKey(key, pw, s_windowsPbe);
                        Pkcs12SafeBag certBag  = certContents.AddCertificate(cert);
                        Pkcs12SafeBag certBag2 = certContents.AddCertificate(cert2);

                        keyBag.Attributes.Add(s_keyIdOne);
                        certBag2.Attributes.Add(s_keyIdOne);

                        AddContents(keyContents, builder, pw, encrypt: false);
                        AddContents(certContents, builder, pw, encrypt: true);
                        builder.SealWithMac(pw, s_digestAlgorithm, MacCount);
                        byte[] pfxBytes = builder.Encode();

                        // Windows seems to be applying both the implicit match and the LocalKeyId match,
                        // so it detects two hits against the same key and fails.
                        ReadUnreadablePfx(
                            pfxBytes,
                            pw,
                            // NTE_BAD_DATA
                            -2146893819);
                    }
        }
예제 #7
0
        public static void ReadSerializedData(bool encryptSafe)
        {
            Pkcs12SafeContents container = new Pkcs12SafeContents();

            Pkcs12SafeContents builtContents = new Pkcs12SafeContents();

            builtContents.AddSecret(s_zeroOid, s_derNull);

            builtContents.AddSecret(s_zeroOid, new byte[] { 4, 1, 2 }).Attributes.Add(
                new Pkcs9LocalKeyId(s_derNull.Span));

            builtContents.AddSecret(s_zeroOid, new byte[] { 4, 1, 3 });
            container.AddNestedContents(builtContents);

            Pkcs12Builder builder = new Pkcs12Builder();

            if (encryptSafe)
            {
                builder.AddSafeContentsEncrypted(container, s_derNull.Span, s_pbkdf2Parameters);
            }
            else
            {
                builder.AddSafeContentsUnencrypted(container);
            }

            builder.SealWithoutIntegrity();
            byte[] encoded = builder.Encode();

            Pkcs12Info         info     = Pkcs12Info.Decode(encoded, out _, skipCopy: true);
            Pkcs12SafeContents onlySafe = info.AuthenticatedSafe.Single();

            if (encryptSafe)
            {
                onlySafe.Decrypt(s_derNull.Span);
            }

            Pkcs12SafeBag         onlyBag         = onlySafe.GetBags().Single();
            Pkcs12SafeContentsBag safeContentsBag = Assert.IsType <Pkcs12SafeContentsBag>(onlyBag);
            Pkcs12SafeContents    readContents    = safeContentsBag.SafeContents;

            Assert.Equal(
                Pkcs12ConfidentialityMode.None,
                readContents.ConfidentialityMode);

            Assert.True(readContents.IsReadOnly);

            List <Pkcs12SafeBag> bags1 = builtContents.GetBags().ToList();
            List <Pkcs12SafeBag> bags2 = readContents.GetBags().ToList();

            Assert.Equal(bags1.Count, bags2.Count);

            for (int i = 0; i < bags2.Count; i++)
            {
                byte[] encoded1 = bags1[i].Encode();
                byte[] encoded2 = bags1[i].Encode();

                Assert.True(encoded1.AsSpan().SequenceEqual(encoded2), $"Bag {i} encodes the same");
            }
        }
예제 #8
0
        public void CertAndKeyTwice(bool addLocalKeyId, bool crossIdentifiers)
        {
            string pw = nameof(CertAndKeyTwice);

            using (var cert = new X509Certificate2(TestData.PfxData, TestData.PfxDataPassword, s_exportableImportFlags))
                using (RSA key = cert.GetRSAPrivateKey())
                {
                    Pkcs12Builder      builder      = new Pkcs12Builder();
                    Pkcs12SafeContents keyContents  = new Pkcs12SafeContents();
                    Pkcs12SafeContents certContents = new Pkcs12SafeContents();

                    Pkcs12SafeBag key1  = keyContents.AddShroudedKey(key, pw, s_windowsPbe);
                    Pkcs12SafeBag key2  = keyContents.AddShroudedKey(key, pw, s_windowsPbe);
                    Pkcs12SafeBag cert1 = certContents.AddCertificate(cert);
                    Pkcs12SafeBag cert2 = certContents.AddCertificate(cert);

                    if (addLocalKeyId)
                    {
                        (crossIdentifiers ? key2 : key1).Attributes.Add(s_keyIdOne);
                        cert1.Attributes.Add(s_keyIdOne);

                        Pkcs9LocalKeyId id2 = new Pkcs9LocalKeyId(cert.GetCertHash());
                        (crossIdentifiers ? key1 : key2).Attributes.Add(id2);
                        cert2.Attributes.Add(id2);
                    }

                    AddContents(keyContents, builder, pw, encrypt: false);
                    AddContents(certContents, builder, pw, encrypt: true);
                    builder.SealWithMac(pw, s_digestAlgorithm, MacCount);
                    byte[] pfxBytes = builder.Encode();

                    if (addLocalKeyId)
                    {
                        ReadMultiPfx(
                            pfxBytes,
                            pw,
                            cert,
                            new[] { cert, cert },
                            CheckKeyConsistency);
                    }
                    else
                    {
                        ReadUnreadablePfx(
                            pfxBytes,
                            pw,
                            // NTE_BAD_DATA
                            -2146893819);
                    }
                }
        }
예제 #9
0
        public void OneCert_MismatchedKey()
        {
            string pw = nameof(OneCert_MismatchedKey);

            // Build the PFX in the normal Windows style, except the private key doesn't match.
            using (var cert = new X509Certificate2(TestData.PfxData, TestData.PfxDataPassword, s_exportableImportFlags))
                using (RSA realKey = cert.GetRSAPrivateKey())
                    using (RSA key = RSA.Create(realKey.KeySize))
                    {
                        Pkcs12Builder      builder      = new Pkcs12Builder();
                        Pkcs12SafeContents keyContents  = new Pkcs12SafeContents();
                        Pkcs12SafeBag      keyBag       = keyContents.AddShroudedKey(key, pw, s_windowsPbe);
                        Pkcs12SafeContents certContents = new Pkcs12SafeContents();
                        Pkcs12SafeBag      certBag      = certContents.AddCertificate(cert);

                        keyBag.Attributes.Add(s_keyIdOne);
                        certBag.Attributes.Add(s_keyIdOne);

                        builder.AddSafeContentsUnencrypted(keyContents);
                        builder.AddSafeContentsEncrypted(certContents, pw, s_windowsPbe);
                        builder.SealWithoutIntegrity();
                        byte[] pfxBytes = builder.Encode();

                        // On macOS the cert will come back with HasPrivateKey being false.
                        if (OperatingSystem.IsMacOS())
                        {
                            using (var publicCert = new X509Certificate2(cert.RawData))
                            {
                                ReadPfx(
                                    pfxBytes,
                                    pw,
                                    publicCert);
                            }

                            return;
                        }

                        ReadPfx(
                            pfxBytes,
                            pw,
                            cert,
                            CheckKeyConsistencyFails);
                    }
        }
예제 #10
0
        public void TwoCerts_OneKey(bool certWithKeyFirst)
        {
            string pw = nameof(TwoCerts_OneKey);

            // Build the PFX in the normal Windows style, except the private key doesn't match.
            using (var cert = new X509Certificate2(TestData.PfxData, TestData.PfxDataPassword, s_exportableImportFlags))
                using (var cert2 = new X509Certificate2(TestData.MsCertificate))
                    using (RSA key = cert.GetRSAPrivateKey())
                    {
                        Pkcs12Builder      builder      = new Pkcs12Builder();
                        Pkcs12SafeContents certContents = new Pkcs12SafeContents();
                        Pkcs12SafeContents keyContents  = new Pkcs12SafeContents();

                        Pkcs12SafeBag      certBag;
                        Pkcs12SafeBag      keyBag = keyContents.AddShroudedKey(key, pw, s_windowsPbe);
                        X509Certificate2[] expectedOrder;

                        if (certWithKeyFirst)
                        {
                            certBag = certContents.AddCertificate(cert);
                            certContents.AddCertificate(cert2);

                            expectedOrder = new[] { cert2, cert };
                        }
                        else
                        {
                            certContents.AddCertificate(cert2);
                            certBag = certContents.AddCertificate(cert);

                            expectedOrder = new[] { cert, cert2 };
                        }

                        certBag.Attributes.Add(s_keyIdOne);
                        keyBag.Attributes.Add(s_keyIdOne);

                        AddContents(keyContents, builder, pw, encrypt: false);
                        AddContents(certContents, builder, pw, encrypt: true);

                        builder.SealWithMac(pw, s_digestAlgorithm, MacCount);
                        ReadMultiPfx(builder.Encode(), pw, cert, expectedOrder);
                    }
        }
예제 #11
0
        public void OneCert_EncryptedEmptyPassword_OneKey_EncryptedNullPassword_NoMac(bool encryptKeySafe, bool associateKey)
        {
            // This test shows that while a null or empty password will result in both
            // types being tested, the PFX contents have to be the same throughout.
            using (var cert = new X509Certificate2(TestData.PfxData, TestData.PfxDataPassword, s_exportableImportFlags))
                using (AsymmetricAlgorithm key = cert.GetRSAPrivateKey())
                {
                    Pkcs12Builder      builder      = new Pkcs12Builder();
                    Pkcs12SafeContents keyContents  = new Pkcs12SafeContents();
                    Pkcs12SafeBag      keyBag       = keyContents.AddShroudedKey(key, (string)null, s_windowsPbe);
                    Pkcs12SafeContents certContents = new Pkcs12SafeContents();
                    Pkcs12SafeBag      certBag      = certContents.AddCertificate(cert);

                    if (associateKey)
                    {
                        keyBag.Attributes.Add(s_keyIdOne);
                        certBag.Attributes.Add(s_keyIdOne);
                    }

                    AddContents(keyContents, builder, null, encryptKeySafe);
                    AddContents(certContents, builder, string.Empty, encrypt: true);
                    builder.SealWithoutIntegrity();
                    byte[] pfxBytes = builder.Encode();

                    if (s_loaderFailsKeysEarly || associateKey || encryptKeySafe)
                    {
                        // NTE_FAIL, falling back to CRYPT_E_BAD_ENCODE if padding happened to work out.
                        ReadUnreadablePfx(pfxBytes, null, altWin32Error: -2146885630);
                        ReadUnreadablePfx(pfxBytes, string.Empty, altWin32Error: -2146885630);
                    }
                    else
                    {
                        using (var publicOnlyCert = new X509Certificate2(cert.RawData))
                        {
                            ReadPfx(pfxBytes, string.Empty, publicOnlyCert);
                        }
                    }
                }
        }
예제 #12
0
        public static void CopyCustomType()
        {
            const string startHex =
                "3033020103302E06092A864886F70D010701A021041F301D301B06092A864886" +
                "F70D010701A00E040C300A3008060100A003040102";

            Pkcs12Info info = Pkcs12Info.Decode(startHex.HexToByteArray(), out _, skipCopy: true);
            // This next line implicitly asserts no encryption, and a couple of Single
            Pkcs12SafeBag bag = info.AuthenticatedSafe.Single().GetBags().Single();

            Pkcs12SafeContents contents = new Pkcs12SafeContents();

            contents.AddSafeBag(bag);

            Pkcs12Builder builder = new Pkcs12Builder();

            builder.AddSafeContentsUnencrypted(contents);
            builder.SealWithoutIntegrity();
            byte[] encoded = builder.Encode();

            Assert.Equal(startHex, encoded.ByteArrayToHex());
        }
예제 #13
0
        public void CertAndKeyTwice_KeysUntagged()
        {
            string pw = nameof(CertAndKeyTwice);

            using (var cert = new X509Certificate2(TestData.PfxData, TestData.PfxDataPassword, s_exportableImportFlags))
                using (RSA key = cert.GetRSAPrivateKey())
                {
                    Pkcs12Builder      builder      = new Pkcs12Builder();
                    Pkcs12SafeContents keyContents  = new Pkcs12SafeContents();
                    Pkcs12SafeContents certContents = new Pkcs12SafeContents();

                    Pkcs12SafeBag key1  = keyContents.AddShroudedKey(key, pw, s_windowsPbe);
                    Pkcs12SafeBag key2  = keyContents.AddShroudedKey(key, pw, s_windowsPbe);
                    Pkcs12SafeBag cert1 = certContents.AddCertificate(cert);
                    Pkcs12SafeBag cert2 = certContents.AddCertificate(cert);

                    Pkcs9LocalKeyId id2 = new Pkcs9LocalKeyId(cert.GetCertHash());
                    Pkcs9LocalKeyId id3 = new Pkcs9LocalKeyId(BitConverter.GetBytes(3));
                    Pkcs9LocalKeyId id4 = new Pkcs9LocalKeyId(BitConverter.GetBytes(4));
                    cert1.Attributes.Add(s_keyIdOne);
                    cert2.Attributes.Add(id2);
                    key1.Attributes.Add(id3);
                    key2.Attributes.Add(id4);

                    AddContents(keyContents, builder, pw, encrypt: false);
                    AddContents(certContents, builder, pw, encrypt: true);
                    builder.SealWithMac(pw, s_digestAlgorithm, MacCount);
                    byte[] pfxBytes = builder.Encode();

                    ReadUnreadablePfx(
                        pfxBytes,
                        pw,
                        // NTE_BAD_DATA
                        -2146893819);
                }
        }
예제 #14
0
        private static void ProcessBagDetails(
            IndentedTextWriter writer,
            Pkcs12SafeBag bag,
            string scopeId,
            IDictionary <string, List <string> > keyMatches,
            ref string password)
        {
            if (bag is Pkcs12CertBag certBag)
            {
                writer.WriteLine($"IsX509Certificate: {certBag.IsX509Certificate}");

                if (certBag.IsX509Certificate)
                {
                    try
                    {
                        using (X509Certificate2 cert = certBag.GetCertificate())
                        {
                            writer.WriteLine($"Subject: {cert.Subject}");
                            writer.WriteLine($" Issuer: {cert.Issuer}");
                        }
                    }
                    catch (CryptographicException)
                    {
                        WriteLineWithColor(
                            ConsoleColor.Yellow,
                            writer,
                            "Certificate did not parse.");
                    }
                }
                else
                {
                    writer.WriteLine($"Certificate Type: {certBag.GetCertificateType().Value}");
                }
            }
            else if (bag is Pkcs12KeyBag keyBag)
            {
                try
                {
                    Pkcs8PrivateKeyInfo keyInfo = Pkcs8PrivateKeyInfo.Decode(
                        keyBag.Pkcs8PrivateKey,
                        out int keyRead,
                        skipCopy: true);

                    writer.WriteLine($"Private Key used {keyRead}/{keyBag.Pkcs8PrivateKey.Length} bytes.");

                    writer.WriteLine(
                        $"Private Key Algorithm: {keyInfo.AlgorithmId.Value} ({keyInfo.AlgorithmId.FriendlyName})");
                }
                catch (CryptographicException)
                {
                    WriteLineWithColor(
                        ConsoleColor.Yellow,
                        writer,
                        "Private Key was not a valid PKCS#8 PrivateKeyInfo");
                }
            }
            else if (bag is Pkcs12ShroudedKeyBag shroudedBag)
            {
                if (password == null)
                {
                    try
                    {
                        Pkcs8PrivateKeyInfo.DecryptAndDecode(
                            password,
                            shroudedBag.EncryptedPkcs8PrivateKey,
                            out _);
                    }
                    catch (CryptographicException)
                    {
                        writer.Write("Enter password: "******"Private Key used {privateKeyRead}/{shroudedBag.EncryptedPkcs8PrivateKey.Length} bytes.");

                    writer.WriteLine(
                        $"Private Key Algorithm: {keyInfo.AlgorithmId.Value} ({keyInfo.AlgorithmId.FriendlyName})");
                }
                catch (CryptographicException)
                {
                    WriteLineWithColor(
                        ConsoleColor.Yellow,
                        writer,
                        "Private Key was not a valid PKCS#8 EncryptedPrivateKeyInfo or it did not decrypt.");
                }
            }
            else if (bag is Pkcs12SecretBag secretBag)
            {
                writer.WriteLine($"Secret Type: {secretBag.GetSecretType().Value}");
            }
            else if (bag is Pkcs12SafeContentsBag safeContentsBag)
            {
                ProcessAttributes(writer, bag, scopeId, keyMatches);

                writer.WriteLine("Nested Contents:");
                writer.Indent++;

                ProcessSafeContents(
                    writer,
                    safeContentsBag.SafeContents,
                    scopeId,
                    keyMatches,
                    ref password);

                writer.Indent--;
                return;
            }

            ProcessAttributes(writer, bag, scopeId, keyMatches);
        }
        public void OneCertWithOneKey(SingleCertOptions options)
        {
            bool   sameContainer           = (options & SingleCertOptions.KeyAndCertInSameContents) != 0;
            bool   dontShroudKey           = (options & SingleCertOptions.UnshroudedKey) != 0;
            bool   keyContainerLast        = (options & SingleCertOptions.KeyContentsLast) != 0;
            bool   encryptCertSafeContents = (options & SingleCertOptions.PlaintextCertContents) == 0;
            bool   encryptKeySafeContents  = (options & SingleCertOptions.EncryptKeyContents) != 0;
            bool   skipMac  = (options & SingleCertOptions.SkipMac) != 0;
            string password = options.ToString();

            using (var cert = new X509Certificate2(TestData.PfxData, TestData.PfxDataPassword, s_exportableImportFlags))
                using (RSA key = cert.GetRSAPrivateKey())
                {
                    if (dontShroudKey && OperatingSystem.IsWindows())
                    {
                        // CNG keys are only encrypted-exportable, so we need to export them encrypted.
                        // Then we can import it into a new, fully-exportable key. (Sigh.)
                        byte[] tmpPkcs8 = key.ExportEncryptedPkcs8PrivateKey(password, s_windowsPbe);
                        key.ImportEncryptedPkcs8PrivateKey(password, tmpPkcs8, out _);
                    }

                    Pkcs12Builder builder = new Pkcs12Builder();

                    Pkcs12SafeContents certContents         = new Pkcs12SafeContents();
                    Pkcs12SafeContents keyContents          = sameContainer ? null : new Pkcs12SafeContents();
                    Pkcs12SafeContents keyEffectiveContents = keyContents ?? certContents;

                    Pkcs12SafeBag certBag = certContents.AddCertificate(cert);
                    Pkcs12SafeBag keyBag;

                    if (dontShroudKey)
                    {
                        keyBag = keyEffectiveContents.AddKeyUnencrypted(key);
                    }
                    else
                    {
                        keyBag = keyEffectiveContents.AddShroudedKey(key, password, s_windowsPbe);
                    }

                    certBag.Attributes.Add(s_keyIdOne);
                    keyBag.Attributes.Add(s_keyIdOne);

                    if (sameContainer)
                    {
                        AddContents(certContents, builder, password, encryptCertSafeContents);
                    }
                    else if (keyContainerLast)
                    {
                        AddContents(certContents, builder, password, encryptCertSafeContents);
                        AddContents(keyContents, builder, password, encryptKeySafeContents);
                    }
                    else
                    {
                        AddContents(keyContents, builder, password, encryptKeySafeContents);
                        AddContents(certContents, builder, password, encryptCertSafeContents);
                    }

                    if (skipMac)
                    {
                        builder.SealWithoutIntegrity();
                    }
                    else
                    {
                        builder.SealWithMac(password, s_digestAlgorithm, MacCount);
                    }

                    ReadPfx(builder.Encode(), password, cert);
                }
        }
예제 #16
0
        public void TwoCerts_TwoKeys_ManySafeContentsValues(bool invertCertOrder, bool invertKeyOrder)
        {
            string pw = nameof(TwoCerts_TwoKeys_ManySafeContentsValues);

            using (ImportedCollection ic = Cert.Import(TestData.MultiPrivateKeyPfx, null, s_exportableImportFlags))
            {
                X509Certificate2Collection certs  = ic.Collection;
                X509Certificate2           first  = certs[0];
                X509Certificate2           second = certs[1];

                if (invertCertOrder)
                {
                    X509Certificate2 tmp = first;
                    first  = second;
                    second = tmp;
                }

                using (AsymmetricAlgorithm firstKey = first.GetRSAPrivateKey())
                    using (AsymmetricAlgorithm secondKey = second.GetRSAPrivateKey())
                    {
                        AsymmetricAlgorithm firstAdd  = firstKey;
                        AsymmetricAlgorithm secondAdd = secondKey;

                        if (invertKeyOrder != invertCertOrder)
                        {
                            AsymmetricAlgorithm tmp = firstKey;
                            firstAdd  = secondAdd;
                            secondAdd = tmp;
                        }

                        Pkcs12Builder      builder            = new Pkcs12Builder();
                        Pkcs12SafeContents firstKeyContents   = new Pkcs12SafeContents();
                        Pkcs12SafeContents secondKeyContents  = new Pkcs12SafeContents();
                        Pkcs12SafeContents firstCertContents  = new Pkcs12SafeContents();
                        Pkcs12SafeContents secondCertContents = new Pkcs12SafeContents();

                        Pkcs12SafeContents irrelevant = new Pkcs12SafeContents();
                        irrelevant.AddSecret(new Oid("0.0"), new byte[] { 0x05, 0x00 });

                        Pkcs12SafeBag firstAddedKeyBag  = firstKeyContents.AddShroudedKey(firstAdd, pw, s_windowsPbe);
                        Pkcs12SafeBag secondAddedKeyBag = secondKeyContents.AddShroudedKey(secondAdd, pw, s_windowsPbe);
                        Pkcs12SafeBag firstCertBag      = firstCertContents.AddCertificate(first);
                        Pkcs12SafeBag secondCertBag     = secondCertContents.AddCertificate(second);
                        Pkcs12SafeBag firstKeyBag       = firstAddedKeyBag;
                        Pkcs12SafeBag secondKeyBag      = secondAddedKeyBag;

                        if (invertKeyOrder != invertCertOrder)
                        {
                            Pkcs12SafeBag tmp = firstKeyBag;
                            firstKeyBag  = secondKeyBag;
                            secondKeyBag = tmp;
                        }

                        firstCertBag.Attributes.Add(s_keyIdOne);
                        firstKeyBag.Attributes.Add(s_keyIdOne);

                        Pkcs9LocalKeyId secondKeyId = new Pkcs9LocalKeyId(second.GetCertHash());
                        secondCertBag.Attributes.Add(secondKeyId);
                        secondKeyBag.Attributes.Add(secondKeyId);

                        // 2C, 1K, 1C, 2K
                        // With some non-participating contents values sprinkled in for good measure.
                        AddContents(irrelevant, builder, pw, encrypt: true);
                        AddContents(secondCertContents, builder, pw, encrypt: true);
                        AddContents(irrelevant, builder, pw, encrypt: false);
                        AddContents(firstKeyContents, builder, pw, encrypt: false);
                        AddContents(firstCertContents, builder, pw, encrypt: true);
                        AddContents(irrelevant, builder, pw, encrypt: false);
                        AddContents(secondKeyContents, builder, pw, encrypt: true);
                        AddContents(irrelevant, builder, pw, encrypt: true);

                        builder.SealWithMac(pw, s_digestAlgorithm, MacCount);
                        byte[] pfxBytes = builder.Encode();

                        X509Certificate2[] expectedOrder = { first, second };

                        Action <X509Certificate2> followup = CheckKeyConsistency;

                        // For unknown reasons, CheckKeyConsistency on this test fails
                        // on Windows 7 with an Access Denied in all variations for
                        // Collections, and in invertCertOrder: true for Single.
                        //
                        // Obviously this hit some sort of weird corner case in the Win7
                        // loader, but it's not important to the test.

                        if (OperatingSystem.IsWindows() &&
                            !PlatformDetection.IsWindows8xOrLater)
                        {
                            followup = null;
                        }

                        ReadMultiPfx(
                            pfxBytes,
                            pw,
                            first,
                            expectedOrder,
                            followup);
                    }
            }
        }
예제 #17
0
        public void OneCert_TwoKeys_FirstWins(bool correctKeyFirst)
        {
            string pw = nameof(OneCert_TwoKeys_FirstWins);

            // Build the PFX in the normal Windows style, except the private key doesn't match.
            using (var cert = new X509Certificate2(TestData.PfxData, TestData.PfxDataPassword, s_exportableImportFlags))
                using (RSA key = cert.GetRSAPrivateKey())
                    using (RSA unrelated = RSA.Create(key.KeySize))
                    {
                        Pkcs12Builder      builder      = new Pkcs12Builder();
                        Pkcs12SafeContents keyContents  = new Pkcs12SafeContents();
                        Pkcs12SafeContents certContents = new Pkcs12SafeContents();
                        Pkcs12SafeBag      keyBag;
                        Pkcs12SafeBag      keyBag2;
                        Pkcs12SafeBag      certBag = certContents.AddCertificate(cert);

                        if (correctKeyFirst)
                        {
                            keyBag  = keyContents.AddShroudedKey(key, pw, s_windowsPbe);
                            keyBag2 = keyContents.AddShroudedKey(unrelated, pw, s_windowsPbe);
                        }
                        else
                        {
                            keyBag  = keyContents.AddShroudedKey(unrelated, pw, s_windowsPbe);
                            keyBag2 = keyContents.AddShroudedKey(key, pw, s_windowsPbe);
                        }

                        keyBag.Attributes.Add(s_keyIdOne);
                        keyBag2.Attributes.Add(s_keyIdOne);
                        certBag.Attributes.Add(s_keyIdOne);

                        builder.AddSafeContentsUnencrypted(keyContents);
                        builder.AddSafeContentsEncrypted(certContents, pw, s_windowsPbe);
                        builder.SealWithoutIntegrity();
                        byte[] pfxBytes = builder.Encode();

                        // On macOS the cert will come back with HasPrivateKey being false when the
                        // incorrect key comes first
                        if (!correctKeyFirst && OperatingSystem.IsMacOS())
                        {
                            using (var publicCert = new X509Certificate2(cert.RawData))
                            {
                                ReadPfx(
                                    pfxBytes,
                                    pw,
                                    publicCert);
                            }

                            return;
                        }

                        // The RSA "self-test" should pass when the correct key is first,
                        // and fail when the unrelated key is first.
                        Action <X509Certificate2> followup = CheckKeyConsistency;

                        if (!correctKeyFirst)
                        {
                            followup = CheckKeyConsistencyFails;
                        }

                        ReadPfx(
                            pfxBytes,
                            pw,
                            cert,
                            followup);
                    }
        }