コード例 #1
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");
            }
        }
コード例 #2
0
        public static void AddContentsAfterSealing()
        {
            Pkcs12SafeContents contents = new Pkcs12SafeContents();

            contents.AddSecret(s_zeroOid, s_derNull);

            Pkcs12Builder builder = new Pkcs12Builder();

            builder.SealWithoutIntegrity();

            Assert.Throws <InvalidOperationException>(
                () => builder.AddSafeContentsUnencrypted(contents));

            Assert.Throws <InvalidOperationException>(
                () => builder.AddSafeContentsEncrypted(contents, Array.Empty <byte>(), s_pbkdf2Parameters));

            Assert.Throws <InvalidOperationException>(
                () => builder.AddSafeContentsEncrypted(contents, ReadOnlySpan <byte> .Empty, s_pbkdf2Parameters));

            Assert.Throws <InvalidOperationException>(
                () => builder.AddSafeContentsEncrypted(contents, string.Empty, s_pbkdf2Parameters));

            Assert.Throws <InvalidOperationException>(
                () => builder.AddSafeContentsEncrypted(contents, ReadOnlySpan <char> .Empty, s_pbkdf2Parameters));
        }
コード例 #3
0
        public static void EncryptEncryptedSafeContents()
        {
            Pkcs12Builder builder1 = new Pkcs12Builder();
            Pkcs12Builder builder2 = new Pkcs12Builder();

            Pkcs12SafeContents contents = new Pkcs12SafeContents();

            contents.AddSecret(s_zeroOid, s_derNull);

            builder1.AddSafeContentsEncrypted(contents, ReadOnlySpan <byte> .Empty, s_pbkdf2Parameters);
            builder1.SealWithoutIntegrity();

            byte[]     encoded = builder1.Encode();
            Pkcs12Info info    = Pkcs12Info.Decode(encoded, out _, skipCopy: true);

            Assert.Equal(Pkcs12IntegrityMode.None, info.IntegrityMode);
            Assert.Equal(1, info.AuthenticatedSafe.Count);

            AssertExtensions.Throws <ArgumentException>(
                "safeContents",
                () => builder2.AddSafeContentsEncrypted(
                    info.AuthenticatedSafe[0],
                    "nope",
                    s_pbkdf2Parameters));

            AssertExtensions.Throws <ArgumentException>(
                "safeContents",
                () => builder2.AddSafeContentsEncrypted(
                    info.AuthenticatedSafe[0],
                    s_derNull.Span,
                    s_pbkdf2Parameters));
        }
コード例 #4
0
        public static void CopyEncryptedSafeContents(bool withSpan)
        {
            Pkcs12Builder builder1 = new Pkcs12Builder();
            Pkcs12Builder builder2 = new Pkcs12Builder();

            Pkcs12SafeContents contents = new Pkcs12SafeContents();

            contents.AddSecret(s_zeroOid, s_derNull);

            if (withSpan)
            {
                builder1.AddSafeContentsEncrypted(contents, ReadOnlySpan <byte> .Empty, s_pbkdf2Parameters);
            }
            else
            {
                builder1.AddSafeContentsEncrypted(contents, (byte[])null, s_pbkdf2Parameters);
            }

            builder1.SealWithoutIntegrity();

            byte[]     encoded1 = builder1.Encode();
            Pkcs12Info info     = Pkcs12Info.Decode(encoded1, out _, skipCopy: true);

            Assert.Equal(Pkcs12IntegrityMode.None, info.IntegrityMode);
            Assert.Equal(1, info.AuthenticatedSafe.Count);

            builder2.AddSafeContentsUnencrypted(info.AuthenticatedSafe[0]);
            builder2.SealWithoutIntegrity();

            byte[] encoded2 = builder2.Encode();
            Assert.Equal(encoded1.ByteArrayToHex(), encoded2.ByteArrayToHex());
        }
コード例 #5
0
        public static void OidRequired()
        {
            Pkcs12SafeContents contents = new Pkcs12SafeContents();

            AssertExtensions.Throws <ArgumentNullException>(
                "secretType",
                () => contents.AddSecret(null, ReadOnlyMemory <byte> .Empty));
        }
コード例 #6
0
        public static void BadOidFails()
        {
            string payloadHex = "0403090807";

            Pkcs12SafeContents contents = new Pkcs12SafeContents();

            Assert.ThrowsAny <CryptographicException>(
                () => contents.AddSecret(new Oid("Hi", "There"), payloadHex.HexToByteArray()));
        }
コード例 #7
0
        public static void EncryptPkcs12KdfWithBytes()
        {
            Pkcs12SafeContents contents = new Pkcs12SafeContents();

            contents.AddSecret(s_zeroOid, s_derNull);

            Pkcs12Builder builder = new Pkcs12Builder();

            Assert.ThrowsAny <CryptographicException>(
                () => builder.AddSafeContentsEncrypted(contents, s_derNull.Span, s_win7Pbe));
        }
コード例 #8
0
        public static void CreatingBagSerializesInput()
        {
            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 });

            Pkcs12SafeContentsBag safeContentsBag = container.AddNestedContents(builtContents);

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

            Pkcs12SafeContents readContents = safeContentsBag.SafeContents;

            Assert.NotSame(readContents, builtContents);

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

            Assert.True(readContents.IsReadOnly);

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

            Assert.Equal(4, bags1.Count);
            Assert.Equal(3, 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");
            }
        }
コード例 #9
0
        public static void LegalBerPayloadRequired(string inputHex, bool expectSuccess)
        {
            Pkcs12SafeContents contents = new Pkcs12SafeContents();

            Action addAction =
                () => contents.AddSecret(new Oid("0.0", "0.0"), inputHex.HexToByteArray());

            if (expectSuccess)
            {
                addAction();
            }
            else
            {
                Assert.ThrowsAny <CryptographicException>(addAction);
            }
        }
コード例 #10
0
        public static void HasExpectedEncode(bool withAttribute)
        {
            string expectedHexWithAttribute =
                "303F060B2A864886F70D010C0A0105A01C301A060100A0150C1353776F726466" +
                "6973682E20436C6561726C792E3112301006092A864886F70D01091531030401" +
                "01";

            string expectedHexNoAttribute =
                "302B060B2A864886F70D010C0A0105A01C301A060100A0150C1353776F726466" +
                "6973682E20436C6561726C792E";

            string expectedHex = withAttribute ? expectedHexWithAttribute : expectedHexNoAttribute;

            // UTF8String ("Swordfish. Clearly.")
            string payloadHex = "0C1353776F7264666973682E20436C6561726C792E";

            Pkcs12SafeContents contents = new Pkcs12SafeContents();
            Pkcs12SecretBag    bag      = contents.AddSecret(new Oid("0.0", "0.0"), payloadHex.HexToByteArray());

            if (withAttribute)
            {
                bag.Attributes.Add(new Pkcs9LocalKeyId(new byte[] { 0x01 }));
            }

            byte[] encoded = bag.Encode();
            Assert.Equal(expectedHex, encoded.ByteArrayToHex());

            Span <byte> tooBig = new byte[encoded.Length + 10];

            tooBig.Fill(0xCA);

            Assert.False(bag.TryEncode(tooBig.Slice(0, encoded.Length - 1), out int bytesWritten));
            Assert.Equal(0, bytesWritten);
            Assert.Equal(0xCA, tooBig[0]);

            Assert.True(bag.TryEncode(tooBig.Slice(3), out bytesWritten));
            Assert.Equal(encoded.Length, bytesWritten);
            Assert.Equal(expectedHex, tooBig.Slice(3, bytesWritten).ByteArrayToHex());

            tooBig.Fill(0xCA);
            bytesWritten = 0;

            Assert.True(bag.TryEncode(tooBig.Slice(3, encoded.Length), out bytesWritten));
            Assert.Equal(encoded.Length, bytesWritten);
            Assert.Equal(expectedHex, tooBig.Slice(3, bytesWritten).ByteArrayToHex());
        }
コード例 #11
0
        public static void AddEncryptedNestedContents()
        {
            Pkcs12Builder      builder  = new Pkcs12Builder();
            Pkcs12SafeContents contents = new Pkcs12SafeContents();

            contents.AddSecret(s_zeroOid, s_derNull);

            builder.AddSafeContentsEncrypted(contents, "hi", s_pbeParameters);
            builder.SealWithoutIntegrity();

            byte[]     encoded = builder.Encode();
            Pkcs12Info info    = Pkcs12Info.Decode(encoded, out _, skipCopy: true);

            Assert.Equal(Pkcs12IntegrityMode.None, info.IntegrityMode);
            Assert.Equal(1, info.AuthenticatedSafe.Count);

            Pkcs12SafeContents newContents = new Pkcs12SafeContents();

            AssertExtensions.Throws <ArgumentException>(
                "safeContents",
                () => newContents.AddNestedContents(info.AuthenticatedSafe[0]));
        }
コード例 #12
0
        public static void EncryptDecryptMixBytesAndChars(bool encryptBytes, bool withSpan)
        {
            Pkcs12SafeContents contents = new Pkcs12SafeContents();

            contents.AddSecret(s_zeroOid, s_derNull);

            string      password          = nameof(EncryptDecryptMixBytesAndChars);
            Span <byte> passwordUtf8Bytes = stackalloc byte[password.Length];

            Encoding.UTF8.GetBytes(password, passwordUtf8Bytes);

            Pkcs12Builder builder = new Pkcs12Builder();

            if (encryptBytes)
            {
                builder.AddSafeContentsEncrypted(contents, passwordUtf8Bytes, s_pbkdf2Parameters);
            }
            else
            {
                builder.AddSafeContentsEncrypted(contents, password, s_pbkdf2Parameters);
            }

            builder.SealWithMac(password, HashAlgorithmName.SHA1, 2048);

            byte[]     encoded = builder.Encode();
            Pkcs12Info info    = Pkcs12Info.Decode(encoded, out _, skipCopy: true);

            Assert.True(info.VerifyMac(password));
            ReadOnlyCollection <Pkcs12SafeContents> authSafe = info.AuthenticatedSafe;

            Assert.Equal(1, authSafe.Count);

            Pkcs12SafeContents readContents = authSafe[0];

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

            if (encryptBytes)
            {
                if (withSpan)
                {
                    readContents.Decrypt(password.AsSpan());
                }
                else
                {
                    readContents.Decrypt(password);
                }
            }
            else
            {
                if (withSpan)
                {
                    readContents.Decrypt(passwordUtf8Bytes);
                }
                else
                {
                    readContents.Decrypt(passwordUtf8Bytes.ToArray());
                }
            }

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

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

            Assert.Equal(1, bags.Count);
            Pkcs12SecretBag secretBag = Assert.IsType <Pkcs12SecretBag>(bags[0]);

            Assert.Equal(s_zeroOid.Value, secretBag.GetSecretType().Value);
            Assert.Equal(s_derNull.ByteArrayToHex(), secretBag.SecretValue.ByteArrayToHex());
        }
コード例 #13
0
        public static void EncodeAndTryEncode(Pkcs12IntegrityMode mode)
        {
            Pkcs12Builder builder1 = new Pkcs12Builder();
            Pkcs12Builder builder2 = new Pkcs12Builder();

            Pkcs12SafeContents contents = new Pkcs12SafeContents();

            contents.AddSecret(s_zeroOid, s_derNull);

            builder1.AddSafeContentsUnencrypted(contents);
            builder2.AddSafeContentsUnencrypted(contents);

            int macTrailerLength = 0;

            if (mode == Pkcs12IntegrityMode.Password)
            {
                builder1.SealWithMac(ReadOnlySpan <char> .Empty, HashAlgorithmName.SHA1, 2);
                builder2.SealWithMac(ReadOnlySpan <char> .Empty, HashAlgorithmName.SHA1, 2);

                // Two OCTET STRINGs of 20 bytes, and the INTEGER 2
                macTrailerLength = 2 + 20 + 2 + 20 + 2 + 3;
            }
            else if (mode == Pkcs12IntegrityMode.None)
            {
                builder1.SealWithoutIntegrity();
                builder2.SealWithoutIntegrity();
            }

            Assert.True(builder1.IsSealed, "builder1.IsSealed");
            Assert.True(builder2.IsSealed, "builder2.IsSealed");

            byte[]      encoded = builder1.Encode();
            byte[]      buf     = new byte[encoded.Length + 40];
            Span <byte> bufSpan = buf;

            // Span too small
            Assert.False(builder2.TryEncode(buf.AsSpan(0, encoded.Length - 1), out int bytesWritten));
            Assert.Equal(0, bytesWritten);

            // Span exactly right
            bufSpan.Fill(0xCA);
            Assert.True(builder2.TryEncode(buf.AsSpan(1, encoded.Length), out bytesWritten));
            Assert.Equal(encoded.Length, bytesWritten);
            Assert.Equal(0xCA, buf[0]);
            Assert.Equal(0xCA, buf[bytesWritten + 1]);

            if (mode == Pkcs12IntegrityMode.Password)
            {
                Assert.Equal(0x02, buf[bytesWritten]);
            }

            // The same contents except the MAC (different random salt)
            Assert.Equal(
                encoded.AsSpan(0, bytesWritten - macTrailerLength).ByteArrayToHex(),
                buf.AsSpan(1, bytesWritten - macTrailerLength).ByteArrayToHex());

            if (macTrailerLength > 0)
            {
                Assert.NotEqual(
                    encoded.AsSpan(bytesWritten - macTrailerLength).ByteArrayToHex(),
                    buf.AsSpan(1 + bytesWritten - macTrailerLength, macTrailerLength).ByteArrayToHex());
            }

            // Span larger than needed
            bufSpan.Fill(0xCA);
            Assert.True(builder2.TryEncode(buf.AsSpan(2), out bytesWritten));
            Assert.Equal(encoded.Length, bytesWritten);
            Assert.Equal(0xCA, buf[0]);
            Assert.Equal(0xCA, buf[1]);
            Assert.Equal(0xCA, buf[bytesWritten + 2]);

            if (mode == Pkcs12IntegrityMode.Password)
            {
                Assert.Equal(0x02, buf[bytesWritten + 1]);
            }

            // The same contents except the MAC (different random salt)
            Assert.Equal(
                encoded.AsSpan(0, bytesWritten - macTrailerLength).ByteArrayToHex(),
                buf.AsSpan(2, bytesWritten - macTrailerLength).ByteArrayToHex());

            if (macTrailerLength > 0)
            {
                Assert.NotEqual(
                    encoded.AsSpan(bytesWritten - macTrailerLength).ByteArrayToHex(),
                    buf.AsSpan(2 + bytesWritten - macTrailerLength, macTrailerLength).ByteArrayToHex());
            }
        }
コード例 #14
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);
                    }
            }
        }