Пример #1
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 });
            }
        }
Пример #2
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);
                }
        }
Пример #3
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);
                    }
        }
Пример #4
0
        public void TwoCerts_TwentyKeys_NoMatches(bool msCertFirst)
        {
            string pw = nameof(OneCert_NoKey_WithLocalKeyId);

            using (var certWithKey = new X509Certificate2(TestData.PfxData, TestData.PfxDataPassword))
                using (var cert = new X509Certificate2(certWithKey.RawData))
                    using (var cert2 = new X509Certificate2(TestData.MsCertificate))
                        using (RSA rsa = RSA.Create(TestData.RsaBigExponentParams))
                        {
                            Pkcs12Builder      builder      = new Pkcs12Builder();
                            Pkcs12SafeContents certContents = new Pkcs12SafeContents();
                            Pkcs12SafeContents keyContents  = new Pkcs12SafeContents();
                            Pkcs12CertBag      certBag;

                            if (msCertFirst)
                            {
                                certBag = certContents.AddCertificate(cert2);
                                certBag.Attributes.Add(s_keyIdOne);
                            }

                            certBag = certContents.AddCertificate(cert);
                            certBag.Attributes.Add(new Pkcs9LocalKeyId(cert.GetCertHash()));

                            if (!msCertFirst)
                            {
                                certBag = certContents.AddCertificate(cert2);
                                certBag.Attributes.Add(s_keyIdOne);
                            }

                            byte[] keyExport = rsa.ExportEncryptedPkcs8PrivateKey(pw, s_windowsPbe);

                            for (int i = 0; i < 20; i++)
                            {
                                Pkcs12SafeBag keyBag = new Pkcs12ShroudedKeyBag(keyExport, skipCopy: true);
                                keyContents.AddSafeBag(keyBag);

                                // Even with i=1 this won't match, because { 0x01 } != { 0x01, 0x00, 0x00, 0x00 } and
                                // { 0x01 } != { 0x00, 0x00, 0x00, 0x01 } (binary comparison, not "equivalence" comparison).
                                keyBag.Attributes.Add(new Pkcs9LocalKeyId(BitConverter.GetBytes(i)));
                            }

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

                            ReadMultiPfx(
                                pfxBytes,
                                pw,
                                msCertFirst ? cert : cert2,
                                msCertFirst ? new[] { cert, cert2 } : new[] { cert2, cert });
                        }
        }
Пример #5
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);
                    }
                }
        }
Пример #6
0
        public static void AddCertificateDisallowedInReadOnly()
        {
            Pkcs12SafeContents contents = MakeReadonly(new Pkcs12SafeContents());
            X509Certificate2   cert     = new X509Certificate2(stackalloc byte[0]);

            Assert.Throws <InvalidOperationException>(() => contents.AddCertificate(cert));
        }
Пример #7
0
        public static void WriteOneCertNoKeys_Encrypted()
        {
            Pkcs12SafeContents contents = new Pkcs12SafeContents();

            byte[] rawData;

            using (X509Certificate2 cert = Certificates.RSAKeyTransferCapi1.GetCertificate())
            {
                contents.AddCertificate(cert);
                rawData = cert.RawData;
            }

            const string password = nameof(WriteOneCertNoKeys_NoEncryption);

            Pkcs12Builder builder = new Pkcs12Builder();

            builder.AddSafeContentsEncrypted(
                contents,
                password,
                s_win7Pbe);

            builder.SealWithMac(password, HashAlgorithmName.SHA1, 1024);
            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.False(coll.Collection[0].HasPrivateKey, "coll.Collection[0].HasPrivateKey");
            }
        }
Пример #8
0
        public static X509Certificate2 CreateCertificateWithPrivateKey(
            X509Certificate2 certificate,
            AsymmetricAlgorithm privateKey,
            string password = null)
        {
            var builder  = new Pkcs12Builder();
            var contents = new Pkcs12SafeContents();

            contents.AddCertificate(certificate);
            contents.AddKeyUnencrypted(privateKey);
            builder.AddSafeContentsUnencrypted(contents);

            // OpenSSL requires the file to have a mac, without mac this will run on Windows but not on Linux
            builder.SealWithMac(password, HashAlgorithmName.SHA256, 1);
            var pkcs12bytes = builder.Encode();

            if (string.IsNullOrEmpty(password))
            {
                var certificateOut = new X509Certificate2(pkcs12bytes);
                return(certificateOut);
            }
            else
            {
                var certificateOut = new X509Certificate2(pkcs12bytes, password);
                return(certificateOut);
            }
        }
Пример #9
0
        public void Setup()
        {
            _certPath = $"{PathName}/bundle.p12";

            using var rsa = 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);
            builder.AddSafeContentsEncrypted(safeContents, Password, pbeParams);
            builder.SealWithMac(Password, HashAlgorithmName.SHA1, 2048);             //openssl defaults

            File.WriteAllBytes(_certPath, builder.Encode());
        }
Пример #10
0
        public void OneCert_ExtraKeyBadEncoding(bool badTag)
        {
            string pw = nameof(OneCert_ExtraKeyBadEncoding);

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

                // SEQUENCE { INTEGER(1) } is not a valid RSAPrivateKey, it should be
                // SEQUENCE { INTEGER(N), INTEGER(E), ... (D, P, Q, DP, DQ, QInv) }
                // So the conclusion is "unexpected end of data"
                byte[] badKeyBytes = { 0x30, 0x03, 0x02, 0x01, 0x01 };

                // In "badTag" we make the INTEGER be OCTET STRING, triggering a different
                // "uh, I can't read this..." error.
                if (badTag)
                {
                    badKeyBytes[2] = 0x04;
                }

                Pkcs8PrivateKeyInfo pk8 = new Pkcs8PrivateKeyInfo(
                    // The correct RSA OID.
                    new Oid("1.2.840.113549.1.1.1", null),
                    null,
                    badKeyBytes,
                    skipCopies: true);

                // Note that neither the cert nor the key have a LocalKeyId attribute.
                // The existence of this unreadable key is enough to abort the load on older Windows
                keyContents.AddSafeBag(new Pkcs12ShroudedKeyBag(pk8.Encrypt(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();

                if (s_loaderFailsKeysEarly)
                {
                    // CRYPT_E_ASN1_BADTAG or CRYPT_E_ASN1_EOD
                    int expectedWin32Error = badTag ? -2146881269 : -2146881278;

                    ReadUnreadablePfx(
                        pfxBytes,
                        pw,
                        expectedWin32Error);
                }
                else
                {
                    ReadPfx(pfxBytes, pw, cert);
                }
            }
        }
Пример #11
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);
                    }
        }
Пример #12
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");
            }
        }
Пример #13
0
        public static void AddCertificateDisallowsNull(bool forReadOnly)
        {
            Pkcs12SafeContents contents = new Pkcs12SafeContents();

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

            AssertExtensions.Throws <ArgumentNullException>(
                "certificate",
                () => contents.AddCertificate(null));
        }
Пример #14
0
        public static void CertificateReadsSuccessfully()
        {
            using (X509Certificate2 cert = Certificates.RSAKeyTransferCapi1.GetCertificate())
            {
                Pkcs12SafeContents contents = new Pkcs12SafeContents();
                Pkcs12CertBag      certBag  = contents.AddCertificate(cert);

                using (X509Certificate2 extracted = certBag.GetCertificate())
                {
                    Assert.True(extracted.RawData.AsSpan().SequenceEqual(cert.RawData));
                }
            }
        }
Пример #15
0
        public static void WriteTwoCertsNoKeys_NoEncryption()
        {
            Pkcs12SafeContents contents = new Pkcs12SafeContents();

            byte[] rawData1;
            byte[] rawData2;

            using (X509Certificate2 cert1 = Certificates.RSAKeyTransferCapi1.GetCertificate())
                using (X509Certificate2 cert2 = Certificates.RSAKeyTransfer2.GetCertificate())
                {
                    // Windows seems to treat these as a stack.  (LIFO)
                    contents.AddCertificate(cert2);
                    contents.AddCertificate(cert1);
                    rawData1 = cert1.RawData;
                    rawData2 = cert2.RawData;
                }

            Pkcs12Builder builder = new Pkcs12Builder();

            builder.AddSafeContentsUnencrypted(contents);

            const string password = nameof(WriteOneCertNoKeys_NoEncryption);

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

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

            using (coll)
            {
                Assert.Equal(2, coll.Collection.Count);
                Assert.Equal(rawData1, coll.Collection[0].RawData);
                Assert.Equal(rawData2, coll.Collection[1].RawData);
                Assert.False(coll.Collection[0].HasPrivateKey, "coll.Collection[0].HasPrivateKey");
                Assert.False(coll.Collection[1].HasPrivateKey, "coll.Collection[1].HasPrivateKey");
            }
        }
Пример #16
0
        public void OneCert_NoKeys_EncryptedEmptyPassword_NoMac()
        {
            using (X509Certificate2 cert = new X509Certificate2(TestData.MsCertificate))
            {
                Pkcs12Builder      builder      = new Pkcs12Builder();
                Pkcs12SafeContents certContents = new Pkcs12SafeContents();
                certContents.AddCertificate(cert);
                builder.AddSafeContentsEncrypted(certContents, string.Empty, s_windowsPbe);
                builder.SealWithoutIntegrity();
                byte[] pfxBytes = builder.Encode();

                ReadPfx(pfxBytes, null, cert);
                ReadPfx(pfxBytes, string.Empty, cert);
            }
        }
Пример #17
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);
                }
        }
Пример #18
0
        private static X509Certificate2 CreateCertificateWithPrivateKey(X509Certificate2 certificate, AsymmetricAlgorithm privateKey)
        {
            var builder  = new Pkcs12Builder();
            var contents = new Pkcs12SafeContents();

            contents.AddCertificate(certificate);
            contents.AddKeyUnencrypted(privateKey);
            builder.AddSafeContentsUnencrypted(contents);

            // OpenSSL requires the file to have a mac, without mac this will run on Windows but not on Linux
            builder.SealWithMac("temp", HashAlgorithmName.SHA256, 1);
            var pkcs12bytes = builder.Encode();

            var certificateWithKey = new X509Certificate2(pkcs12bytes, "temp");

            return(certificateWithKey);
        }
Пример #19
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);
                    }
        }
Пример #20
0
        public void OneCert_NoKey_WithLocalKeyId()
        {
            string pw = nameof(OneCert_NoKey_WithLocalKeyId);

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

                Pkcs12CertBag certBag = certContents.AddCertificate(cert);
                certBag.Attributes.Add(s_keyIdOne);

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

                ReadPfx(pfxBytes, pw, cert);
            }
        }
Пример #21
0
        public static void WriteOneCertWithKey_Encrypted_SameSafe()
        {
            Pkcs12SafeContents contents = new Pkcs12SafeContents();

            byte[] rawData;

            Pkcs9LocalKeyId localKeyId = new Pkcs9LocalKeyId(new byte[] { 1 });

            using (X509Certificate2 cert = Certificates.RSAKeyTransferCapi1.TryGetCertificateWithPrivateKey(true))
                using (RSA certKey = cert.GetRSAPrivateKey())
                    using (RSA exportableKey = certKey.MakeExportable())
                    {
                        Pkcs12CertBag certBag = contents.AddCertificate(cert);
                        certBag.Attributes.Add(localKeyId);

                        rawData = cert.RawData;

                        Pkcs12KeyBag keyBag = contents.AddKeyUnencrypted(exportableKey);
                        keyBag.Attributes.Add(localKeyId);
                    }

            const string password = nameof(WriteOneCertWithKey_Encrypted_SameSafe);

            Pkcs12Builder builder = new Pkcs12Builder();

            builder.AddSafeContentsEncrypted(
                contents,
                password,
                s_win7Pbe);

            builder.SealWithMac(password, HashAlgorithmName.SHA1, 1024);
            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");
            }
        }
Пример #22
0
        public void OneCert_ExtraKeyWithUnknownAlgorithm()
        {
            string pw = nameof(OneCert_ExtraKeyWithUnknownAlgorithm);

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

                Pkcs8PrivateKeyInfo pk8 = new Pkcs8PrivateKeyInfo(
                    // The Microsoft organization OID, not an algorithm.
                    new Oid("1.3.6.1.4.1.311", null),
                    null,
                    new byte[] { 0x05, 0x00 });

                // Note that neither the cert nor the key have a LocalKeyId attribute.
                // The existence of this unknown key is enough to abort the load on older Windows.
                keyContents.AddSafeBag(new Pkcs12ShroudedKeyBag(pk8.Encrypt(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();

                if (s_loaderFailsKeysEarly)
                {
                    ReadUnreadablePfx(
                        pfxBytes,
                        pw,
                        //NTE_BAD_ALGID,
                        win32Error: -2146893816);
                }
                else
                {
                    ReadPfx(pfxBytes, pw, cert);
                }
            }
        }
Пример #23
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);
                        }
                    }
                }
        }
Пример #24
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);
                }
        }
Пример #26
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);
                    }
        }
Пример #27
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);
                    }
            }
        }