Пример #1
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);
                    }
                }
        }
Пример #2
0
        public static void BuildWithBytesFactoryReadDirect()
        {
            using (RSA rsa = RSA.Create())
            {
                Pkcs12SafeContents contents      = new Pkcs12SafeContents();
                byte[]             encryptionKey = new byte[] { 1, 2, 3, 4, 5 };

                Pkcs12ShroudedKeyBag keyBag = contents.AddShroudedKey(rsa, encryptionKey, s_pbkdf2Pbe);

                using (RSA rsa2 = RSA.Create())
                {
                    rsa2.ImportEncryptedPkcs8PrivateKey(
                        encryptionKey,
                        keyBag.EncryptedPkcs8PrivateKey.Span,
                        out _);

                    byte[] sig = new byte[rsa.KeySize / 8];

                    Assert.True(rsa2.TrySignData(
                                    keyBag.EncryptedPkcs8PrivateKey.Span,
                                    sig,
                                    HashAlgorithmName.MD5,
                                    RSASignaturePadding.Pkcs1,
                                    out int sigLen));

                    Assert.Equal(sig.Length, sigLen);

                    Assert.True(rsa.VerifyData(
                                    keyBag.EncryptedPkcs8PrivateKey.Span,
                                    sig,
                                    HashAlgorithmName.MD5,
                                    RSASignaturePadding.Pkcs1));
                }
            }
        }
Пример #3
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);
                }
        }
Пример #4
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);
                    }
        }
Пример #5
0
        public static void BuildWithCharsFactoryReadDirect()
        {
            using (RSA rsa = RSA.Create())
            {
                Pkcs12SafeContents   contents = new Pkcs12SafeContents();
                Pkcs12ShroudedKeyBag keyBag   = contents.AddShroudedKey(rsa, nameof(rsa), s_win7Pbe);

                using (RSA rsa2 = RSA.Create())
                {
                    rsa2.ImportEncryptedPkcs8PrivateKey(
                        (ReadOnlySpan <char>)nameof(rsa),
                        keyBag.EncryptedPkcs8PrivateKey.Span,
                        out _);

                    byte[] sig = new byte[rsa.KeySize / 8];

                    Assert.True(rsa2.TrySignData(
                                    keyBag.EncryptedPkcs8PrivateKey.Span,
                                    sig,
                                    HashAlgorithmName.MD5,
                                    RSASignaturePadding.Pkcs1,
                                    out int sigLen));

                    Assert.Equal(sig.Length, sigLen);

                    Assert.True(rsa.VerifyData(
                                    keyBag.EncryptedPkcs8PrivateKey.Span,
                                    sig,
                                    HashAlgorithmName.MD5,
                                    RSASignaturePadding.Pkcs1));
                }
            }
        }
Пример #6
0
        public static void AddShroudedKeyWithBytesDisallowsNull(bool forReadOnly)
        {
            Pkcs12SafeContents contents = new Pkcs12SafeContents();

            if (forReadOnly)
            {
                contents = MakeReadonly(contents);
            }

            AssertExtensions.Throws <ArgumentNullException>(
                "key",
                () => contents.AddShroudedKey(null, ReadOnlySpan <byte> .Empty, s_pbeParameters));

            AssertExtensions.Throws <ArgumentNullException>(
                "key",
                () => contents.AddShroudedKey(null, Array.Empty <byte>(), s_pbeParameters));
        }
Пример #7
0
        public static void AddShroudedKeyWithCharsDisallowedInReadOnly()
        {
            Pkcs12SafeContents contents = MakeReadonly(new Pkcs12SafeContents());

            using (RSA rsa = RSA.Create())
            {
                Assert.Throws <InvalidOperationException>(
                    () => contents.AddShroudedKey(rsa, ReadOnlySpan <char> .Empty, s_pbeParameters));
            }
        }
Пример #8
0
        public void Setup()
        {
            _certPath = $"{PathName}/bundle.p12";

            using var rsa = RSA.Create();
            rsa.ImportRSAPrivateKey(_leaf.GetRSAPrivateKey() !.ExportRSAPrivateKey(), out _);

            using var rsa2 = RSA.Create();
            var builder      = new Pkcs12Builder();
            var safeContents = new Pkcs12SafeContents();
            var pbeParams    = new PbeParameters(PbeEncryptionAlgorithm.TripleDes3KeyPkcs12, HashAlgorithmName.SHA1, 2048);          // openssl defaults

            safeContents.AddCertificate(_intermediate);
            safeContents.AddCertificate(_leaf);
            safeContents.AddShroudedKey(rsa, Password, pbeParams);
            safeContents.AddShroudedKey(rsa2, Password, pbeParams);
            builder.AddSafeContentsEncrypted(safeContents, Password, pbeParams);
            builder.SealWithMac(Password, HashAlgorithmName.SHA1, 2048);             //openssl defaults

            File.WriteAllBytes(_certPath, builder.Encode());
        }
Пример #9
0
        public static void WriteOneCertWithKey_LikeWindows()
        {
            Pkcs12SafeContents safe1 = new Pkcs12SafeContents();
            Pkcs12SafeContents safe2 = new Pkcs12SafeContents();

            byte[] rawData;

            Pkcs9LocalKeyId localKeyId = new Pkcs9LocalKeyId(new byte[] { 1 });
            const string    password   = nameof(WriteOneCertWithKey_LikeWindows);

            using (X509Certificate2 cert = Certificates.RSAKeyTransferCapi1.TryGetCertificateWithPrivateKey(true))
            {
                Pkcs12CertBag certBag = safe1.AddCertificate(cert);
                certBag.Attributes.Add(localKeyId);

                rawData = cert.RawData;

                Pkcs12ShroudedKeyBag keyBag;

                using (RSA rsa = cert.GetRSAPrivateKey())
                {
                    keyBag = safe2.AddShroudedKey(
                        rsa,
                        password,
                        s_win7Pbe);
                }

                keyBag.Attributes.Add(localKeyId);
            }

            Pkcs12Builder builder = new Pkcs12Builder();

            builder.AddSafeContentsEncrypted(
                safe1,
                password,
                s_win7Pbe);

            builder.AddSafeContentsUnencrypted(safe2);

            builder.SealWithMac(password, HashAlgorithmName.SHA1, 2068);
            byte[] pfx = builder.Encode();

            ImportedCollection coll =
                ImportedCollection.Import(pfx, password, X509KeyStorageFlags.EphemeralKeySet);

            using (coll)
            {
                Assert.Equal(1, coll.Collection.Count);
                Assert.Equal(rawData, coll.Collection[0].RawData);
                Assert.True(coll.Collection[0].HasPrivateKey, "coll.Collection[0].HasPrivateKey");
            }
        }
Пример #10
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);
                }
        }
Пример #11
0
        public void Setup()
        {
            _certPath = $"{PathName}/leaf.p12";

            using var wrongKey = RSA.Create();
            var builder      = new Pkcs12Builder();
            var safeContents = new Pkcs12SafeContents();
            var pbeParams    = new PbeParameters(PbeEncryptionAlgorithm.TripleDes3KeyPkcs12, HashAlgorithmName.SHA1, 2048);          // openssl defaults

            safeContents.AddCertificate(_leaf);
            safeContents.AddShroudedKey(wrongKey, Password, pbeParams);
            builder.AddSafeContentsEncrypted(safeContents, Password, pbeParams);
            builder.SealWithMac(Password, HashAlgorithmName.SHA1, 2048);             //openssl defaults

            File.WriteAllBytes(_certPath, builder.Encode());
        }
Пример #12
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);
                    }
        }
Пример #13
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);
                    }
        }
Пример #14
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);
                        }
                    }
                }
        }
Пример #15
0
        public void CertAndKey_NoLocalKeyId()
        {
            string pw = nameof(CertAndKey_NoLocalKeyId);

            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();

                    keyContents.AddShroudedKey(key, pw, s_windowsPbe);
                    certContents.AddCertificate(cert);

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

                    ReadPfx(pfxBytes, pw, cert, CheckKeyConsistency);
                }
        }
        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);
                }
        }
Пример #17
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);
                    }
            }
        }
Пример #18
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);
                    }
        }