public static void ReadCustomType() { byte[] input = ( "3033020103302E06092A864886F70D010701A021041F301D301B06092A864886" + "F70D010701A00E040C300A3008060100A003040102").HexToByteArray(); Pkcs12Info info = Pkcs12Info.Decode(input, out _, skipCopy: true); Assert.Equal(Pkcs12IntegrityMode.None, info.IntegrityMode); ReadOnlyCollection <Pkcs12SafeContents> allContents = info.AuthenticatedSafe; Assert.Equal(1, allContents.Count); Pkcs12SafeContents contents = allContents[0]; Assert.Equal(Pkcs12ConfidentialityMode.None, contents.ConfidentialityMode); List <Pkcs12SafeBag> bags = contents.GetBags().ToList(); Assert.Equal(1, bags.Count); Pkcs12SafeBag bag = bags[0]; Assert.IsNotType <Pkcs12CertBag>(bag); Assert.IsNotType <Pkcs12KeyBag>(bag); Assert.IsNotType <Pkcs12SecretBag>(bag); Assert.IsNotType <Pkcs12ShroudedKeyBag>(bag); CustomBagType customBag = new CustomBagType(bag.EncodedBagValue); Assert.Equal(2, customBag.Value); }
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 }); } }
private static void CheckOracleSecretBag( Pkcs12SafeBag safeBag, string key, string value, string keyId) { Pkcs12SecretBag secretBag = Assert.IsType <Pkcs12SecretBag>(safeBag); Assert.Equal("1.2.840.113549.1.16.12.12", secretBag.GetSecretType().Value); Assert.Equal( MakeOracleKeyValuePairHex(key, value), secretBag.SecretValue.ByteArrayToHex()); CryptographicAttributeObjectCollection attrs = secretBag.Attributes; Assert.Equal(1, attrs.Count); CryptographicAttributeObject firstAttr = attrs[0]; Assert.Equal(Oids.LocalKeyId, firstAttr.Oid.Value); Assert.Equal(1, firstAttr.Values.Count); Pkcs9LocalKeyId localKeyId = Assert.IsType <Pkcs9LocalKeyId>(firstAttr.Values[0]); Assert.Equal(keyId, localKeyId.KeyId.ByteArrayToHex()); }
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); } }
private static void ProcessAttributes( IndentedTextWriter writer, Pkcs12SafeBag bag, string scopeId, IDictionary <string, List <string> > keyMatches) { writer.WriteLine("Attributes:"); writer.Indent++; bool firstAttr = true; foreach (CryptographicAttributeObject attrGroup in bag.Attributes) { foreach (AsnEncodedData attr in attrGroup.Values) { if (!firstAttr) { writer.WriteLine(); } firstAttr = false; ProcessAttribute(writer, attr, scopeId, keyMatches); } } if (firstAttr) { writer.WriteLine("No attributes present."); } }
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); } }
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"); } }
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); } } }
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); } }
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); } }
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); } } } }
public static void CopyCustomType() { const string startHex = "3033020103302E06092A864886F70D010701A021041F301D301B06092A864886" + "F70D010701A00E040C300A3008060100A003040102"; Pkcs12Info info = Pkcs12Info.Decode(startHex.HexToByteArray(), out _, skipCopy: true); // This next line implicitly asserts no encryption, and a couple of Single Pkcs12SafeBag bag = info.AuthenticatedSafe.Single().GetBags().Single(); Pkcs12SafeContents contents = new Pkcs12SafeContents(); contents.AddSafeBag(bag); Pkcs12Builder builder = new Pkcs12Builder(); builder.AddSafeContentsUnencrypted(contents); builder.SealWithoutIntegrity(); byte[] encoded = builder.Encode(); Assert.Equal(startHex, encoded.ByteArrayToHex()); }
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); } }
private static void ProcessBagDetails( IndentedTextWriter writer, Pkcs12SafeBag bag, string scopeId, IDictionary <string, List <string> > keyMatches, ref string password) { if (bag is Pkcs12CertBag certBag) { writer.WriteLine($"IsX509Certificate: {certBag.IsX509Certificate}"); if (certBag.IsX509Certificate) { try { using (X509Certificate2 cert = certBag.GetCertificate()) { writer.WriteLine($"Subject: {cert.Subject}"); writer.WriteLine($" Issuer: {cert.Issuer}"); } } catch (CryptographicException) { WriteLineWithColor( ConsoleColor.Yellow, writer, "Certificate did not parse."); } } else { writer.WriteLine($"Certificate Type: {certBag.GetCertificateType().Value}"); } } else if (bag is Pkcs12KeyBag keyBag) { try { Pkcs8PrivateKeyInfo keyInfo = Pkcs8PrivateKeyInfo.Decode( keyBag.Pkcs8PrivateKey, out int keyRead, skipCopy: true); writer.WriteLine($"Private Key used {keyRead}/{keyBag.Pkcs8PrivateKey.Length} bytes."); writer.WriteLine( $"Private Key Algorithm: {keyInfo.AlgorithmId.Value} ({keyInfo.AlgorithmId.FriendlyName})"); } catch (CryptographicException) { WriteLineWithColor( ConsoleColor.Yellow, writer, "Private Key was not a valid PKCS#8 PrivateKeyInfo"); } } else if (bag is Pkcs12ShroudedKeyBag shroudedBag) { if (password == null) { try { Pkcs8PrivateKeyInfo.DecryptAndDecode( password, shroudedBag.EncryptedPkcs8PrivateKey, out _); } catch (CryptographicException) { writer.Write("Enter password: "******"Private Key used {privateKeyRead}/{shroudedBag.EncryptedPkcs8PrivateKey.Length} bytes."); writer.WriteLine( $"Private Key Algorithm: {keyInfo.AlgorithmId.Value} ({keyInfo.AlgorithmId.FriendlyName})"); } catch (CryptographicException) { WriteLineWithColor( ConsoleColor.Yellow, writer, "Private Key was not a valid PKCS#8 EncryptedPrivateKeyInfo or it did not decrypt."); } } else if (bag is Pkcs12SecretBag secretBag) { writer.WriteLine($"Secret Type: {secretBag.GetSecretType().Value}"); } else if (bag is Pkcs12SafeContentsBag safeContentsBag) { ProcessAttributes(writer, bag, scopeId, keyMatches); writer.WriteLine("Nested Contents:"); writer.Indent++; ProcessSafeContents( writer, safeContentsBag.SafeContents, scopeId, keyMatches, ref password); writer.Indent--; return; } ProcessAttributes(writer, bag, scopeId, keyMatches); }
public void OneCertWithOneKey(SingleCertOptions options) { bool sameContainer = (options & SingleCertOptions.KeyAndCertInSameContents) != 0; bool dontShroudKey = (options & SingleCertOptions.UnshroudedKey) != 0; bool keyContainerLast = (options & SingleCertOptions.KeyContentsLast) != 0; bool encryptCertSafeContents = (options & SingleCertOptions.PlaintextCertContents) == 0; bool encryptKeySafeContents = (options & SingleCertOptions.EncryptKeyContents) != 0; bool skipMac = (options & SingleCertOptions.SkipMac) != 0; string password = options.ToString(); using (var cert = new X509Certificate2(TestData.PfxData, TestData.PfxDataPassword, s_exportableImportFlags)) using (RSA key = cert.GetRSAPrivateKey()) { if (dontShroudKey && OperatingSystem.IsWindows()) { // CNG keys are only encrypted-exportable, so we need to export them encrypted. // Then we can import it into a new, fully-exportable key. (Sigh.) byte[] tmpPkcs8 = key.ExportEncryptedPkcs8PrivateKey(password, s_windowsPbe); key.ImportEncryptedPkcs8PrivateKey(password, tmpPkcs8, out _); } Pkcs12Builder builder = new Pkcs12Builder(); Pkcs12SafeContents certContents = new Pkcs12SafeContents(); Pkcs12SafeContents keyContents = sameContainer ? null : new Pkcs12SafeContents(); Pkcs12SafeContents keyEffectiveContents = keyContents ?? certContents; Pkcs12SafeBag certBag = certContents.AddCertificate(cert); Pkcs12SafeBag keyBag; if (dontShroudKey) { keyBag = keyEffectiveContents.AddKeyUnencrypted(key); } else { keyBag = keyEffectiveContents.AddShroudedKey(key, password, s_windowsPbe); } certBag.Attributes.Add(s_keyIdOne); keyBag.Attributes.Add(s_keyIdOne); if (sameContainer) { AddContents(certContents, builder, password, encryptCertSafeContents); } else if (keyContainerLast) { AddContents(certContents, builder, password, encryptCertSafeContents); AddContents(keyContents, builder, password, encryptKeySafeContents); } else { AddContents(keyContents, builder, password, encryptKeySafeContents); AddContents(certContents, builder, password, encryptCertSafeContents); } if (skipMac) { builder.SealWithoutIntegrity(); } else { builder.SealWithMac(password, s_digestAlgorithm, MacCount); } ReadPfx(builder.Encode(), password, cert); } }
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); } } }
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); } }