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 }); } }
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); } }
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 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 }); } }
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 static void AddCertificateDisallowedInReadOnly() { Pkcs12SafeContents contents = MakeReadonly(new Pkcs12SafeContents()); X509Certificate2 cert = new X509Certificate2(stackalloc byte[0]); Assert.Throws <InvalidOperationException>(() => contents.AddCertificate(cert)); }
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"); } }
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); } }
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()); }
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); } } }
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 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"); } }
public static void AddCertificateDisallowsNull(bool forReadOnly) { Pkcs12SafeContents contents = new Pkcs12SafeContents(); if (forReadOnly) { contents = MakeReadonly(contents); } AssertExtensions.Throws <ArgumentNullException>( "certificate", () => contents.AddCertificate(null)); }
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)); } } }
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"); } }
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); } }
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 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); }
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 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); } }
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"); } }
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); } } }
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 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); } }
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); } }
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); } } }