From f2fb5012a42cb47bc7c8a3547f7021da23416499 Mon Sep 17 00:00:00 2001 From: Kevin Jones Date: Mon, 23 Mar 2020 10:22:54 -0400 Subject: [PATCH 01/18] Import PEM encoded keys. --- .config/CredScanSuppressions.json | 1 + .../Cryptography/PemKeyImportHelpers.cs | 157 +++++++ .../DSA/DSAKeyPemTests.cs | 302 ++++++++++++++ .../EC/ECKeyPemTests.cs | 295 ++++++++++++++ .../ECDiffieHellmanKeyPemTests.cs | 15 + .../ECDsa/ECDsaKeyPemTests.cs | 15 + .../RSA/RSAKeyPemTests.cs | 384 ++++++++++++++++++ ...System.Security.Cryptography.Algorithms.cs | 6 + .../src/Resources/Strings.resx | 11 +- ...em.Security.Cryptography.Algorithms.csproj | 5 +- .../src/System/Security/Cryptography/DSA.cs | 28 ++ .../Security/Cryptography/ECDiffieHellman.cs | 33 ++ .../src/System/Security/Cryptography/ECDsa.cs | 32 ++ .../src/System/Security/Cryptography/RSA.cs | 36 ++ ...urity.Cryptography.Algorithms.Tests.csproj | 17 +- ...tem.Security.Cryptography.Cng.Tests.csproj | 15 + ...tem.Security.Cryptography.Csp.Tests.csproj | 6 + ...Security.Cryptography.OpenSsl.Tests.csproj | 17 +- ...System.Security.Cryptography.Primitives.cs | 3 + .../Cryptography/AsymmetricAlgorithm.cs | 9 + 20 files changed, 1383 insertions(+), 4 deletions(-) create mode 100644 src/libraries/Common/src/Internal/Cryptography/PemKeyImportHelpers.cs create mode 100644 src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/DSA/DSAKeyPemTests.cs create mode 100644 src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/EC/ECKeyPemTests.cs create mode 100644 src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/ECDiffieHellman/ECDiffieHellmanKeyPemTests.cs create mode 100644 src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/ECDsa/ECDsaKeyPemTests.cs create mode 100644 src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/RSA/RSAKeyPemTests.cs diff --git a/.config/CredScanSuppressions.json b/.config/CredScanSuppressions.json index ce1383f883293..bd93ae7e1a77d 100644 --- a/.config/CredScanSuppressions.json +++ b/.config/CredScanSuppressions.json @@ -16,6 +16,7 @@ "/src/libraries/Common/tests/System/Net/Prerequisites/Deployment/setup_certificates.ps1", "/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/EC/ECKeyFileTests.cs", "/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/RSA/RSAKeyFileTests.cs", + "/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/RSA/RSAKeyPemTests.cs", "/src/libraries/System.Data.Common/tests/System/Data/Common/DbConnectionStringBuilderTest.cs", "/src/libraries/System.Diagnostics.Process/tests/ProcessStartInfoTests.cs", "/src/libraries/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/constants.cs", diff --git a/src/libraries/Common/src/Internal/Cryptography/PemKeyImportHelpers.cs b/src/libraries/Common/src/Internal/Cryptography/PemKeyImportHelpers.cs new file mode 100644 index 0000000000000..d385785d13843 --- /dev/null +++ b/src/libraries/Common/src/Internal/Cryptography/PemKeyImportHelpers.cs @@ -0,0 +1,157 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#nullable enable +using System; +using System.Diagnostics; +using System.Security.Cryptography; + +namespace Internal.Cryptography +{ + internal static class PemKeyImportHelpers + { + public delegate void ImportKeyAction(ReadOnlySpan source, out int bytesRead); + public delegate ImportKeyAction? FindImportActionFunc(ReadOnlySpan label); + public delegate void ImportEncryptedKeyAction( + ReadOnlySpan password, + ReadOnlySpan source, + out int bytesRead); + + public static void ImportEncryptedPem( + ReadOnlySpan input, + ReadOnlySpan password, + ImportEncryptedKeyAction importAction) + { + bool foundEncryptedPem = false; + PemFields foundFields = default; + ReadOnlySpan foundSlice = default; + + ReadOnlySpan pem = input; + while (PemEncoding.TryFind(pem, out PemFields fields)) + { + ReadOnlySpan label = pem[fields.Label]; + + if (label.SequenceEqual("ENCRYPTED PRIVATE KEY")) + { + if (foundEncryptedPem) + { + throw new ArgumentException(SR.Argument_PemImport_AmbiguousPem, nameof(input)); + } + + foundEncryptedPem = true; + foundFields = fields; + foundSlice = pem; + } + + Index offset = fields.Location.End; + pem = pem[offset..]; + } + + if (!foundEncryptedPem) + { + throw new ArgumentException(SR.Argument_PemImport_NoPemFound, nameof(input)); + } + + ReadOnlySpan base64Contents = foundSlice[foundFields.Base64Data]; + int base64size = foundFields.DecodedDataLength; + byte[] decodeBuffer = CryptoPool.Rent(base64size); + + try + { + if (!Convert.TryFromBase64Chars(base64Contents, decodeBuffer, out int bytesWritten)) + { + // Couldn't decode base64. We shouldn't get here since the + // contents are pre-validated. + Debug.Fail("Base64 decoding failed on already validated contents."); + throw new ArgumentException(); + } + + Debug.Assert(bytesWritten == base64size); + Span decodedBase64 = decodeBuffer.AsSpan(0, base64size); + importAction(password, decodedBase64, out _); + } + finally + { + CryptoPool.Return(decodeBuffer, clearSize: base64size); + } + } + + public static void ImportPem(ReadOnlySpan input, FindImportActionFunc callback) + { + ImportKeyAction? importAction = null; + PemFields foundFields = default; + ReadOnlySpan foundSlice = default; + bool containsEncryptedPem = false; + + ReadOnlySpan pem = input; + while (PemEncoding.TryFind(pem, out PemFields fields)) + { + ReadOnlySpan label = pem[fields.Label]; + ImportKeyAction? action = callback(label); + + // Caller knows how to handle this PEM by label. + if (action != null) + { + // There was a previous PEM that could have been handled, + // which means this is ambiguous and contains multiple + // importable keys. Or, this contained an encrypted PEM. + // For purposes of encrypted PKCS8 with another actionable + // PEM, we will throw a duplicate exception. + if (importAction != null || containsEncryptedPem) + { + throw new ArgumentException(SR.Argument_PemImport_AmbiguousPem, nameof(input)); + } + + importAction = action; + foundFields = fields; + foundSlice = pem; + } + else if (label.SequenceEqual("ENCRYPTED PRIVATE KEY")) + { + containsEncryptedPem = true; + } + + Index offset = fields.Location.End; + pem = pem[offset..]; + } + + // The only PEM found that could potentially be used is encrypted PKCS8, + // but we won't try to import it with a null or blank password, so + // throw. + if (containsEncryptedPem) + { + throw new ArgumentException(SR.Argument_PemImport_EncryptedPem, nameof(input)); + } + + // We went through the PEM and found nothing that could be handled. + if (importAction is null) + { + throw new ArgumentException(SR.Argument_PemImport_NoPemFound, nameof(input)); + } + + ReadOnlySpan base64Contents = foundSlice[foundFields.Base64Data]; + int base64size = foundFields.DecodedDataLength; + byte[] decodeBuffer = CryptoPool.Rent(base64size); + + try + { + if (!Convert.TryFromBase64Chars(base64Contents, decodeBuffer, out int bytesWritten)) + { + // Couldn't decode base64. We shouldn't get here since the + // contents are pre-validated. + Debug.Fail("Base64 decoding failed on already validated contents."); + throw new ArgumentException(); + } + + Debug.Assert(bytesWritten == base64size); + Span decodedBase64 = decodeBuffer.AsSpan(0, base64size); + importAction(decodedBase64, out _); + } + finally + { + CryptoPool.Return(decodeBuffer, clearSize: base64size); + } + } + } +} diff --git a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/DSA/DSAKeyPemTests.cs b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/DSA/DSAKeyPemTests.cs new file mode 100644 index 0000000000000..dafcb87250671 --- /dev/null +++ b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/DSA/DSAKeyPemTests.cs @@ -0,0 +1,302 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Text; +using Test.Cryptography; +using Xunit; + +namespace System.Security.Cryptography.Dsa.Tests +{ + public static class DSAKeyPemTests + { + [Fact] + public static void ImportFromPem_NoPem() + { + string pem = "pem? what pem? there is no pem here."; + using DSA dsa = DSAFactory.Create(); + AssertExtensions.Throws("input", () => dsa.ImportFromPem(pem)); + } + + [Fact] + public static void ImportFromPem_Pkcs8UnEncrypted_Simple() + { + string pem = @" +-----BEGIN PRIVATE KEY----- +MIHGAgEAMIGoBgcqhkjOOAQBMIGcAkEA1qi38cr3ppZNB2Y/xpHSL2q81Vw3rvWN +IHRnQNgv4U4UY2NifZGSUULc3uOEvgoeBO1b9fRxSG9NmG1CoufflQIVAPq19iXV +1eFkMKHvYw6+M4l8wiT5AkAIRMSQ5S71jgWQLGNtZNHV6yxggqDU87/RzgeOh7Q6 +fve77OGaTv4qbZwinTYAg86p9yHzmwW6+XBS3vxnpYorBBYCFC49eoTIW2Z4Xh9v +55aYKyKwy5i8 +-----END PRIVATE KEY-----"; + + using DSA dsa = DSAFactory.Create(); + dsa.ImportFromPem(pem); + DSAParameters dsaParameters = dsa.ExportParameters(true); + + DSAImportExport.AssertKeyEquals(DSATestData.Dsa512Parameters, dsaParameters); + } + + [Fact] + public static void ImportFromPem_Pkcs8_UnrelatedPrecedingPem() + { + string pem = @" +-----BEGIN CERTIFICATE----- +MII= +-----END CERTIFICATE----- +-----BEGIN PRIVATE KEY----- +MIHGAgEAMIGoBgcqhkjOOAQBMIGcAkEA1qi38cr3ppZNB2Y/xpHSL2q81Vw3rvWN +IHRnQNgv4U4UY2NifZGSUULc3uOEvgoeBO1b9fRxSG9NmG1CoufflQIVAPq19iXV +1eFkMKHvYw6+M4l8wiT5AkAIRMSQ5S71jgWQLGNtZNHV6yxggqDU87/RzgeOh7Q6 +fve77OGaTv4qbZwinTYAg86p9yHzmwW6+XBS3vxnpYorBBYCFC49eoTIW2Z4Xh9v +55aYKyKwy5i8 +-----END PRIVATE KEY-----"; + + using DSA dsa = DSAFactory.Create(); + dsa.ImportFromPem(pem); + DSAParameters dsaParameters = dsa.ExportParameters(true); + + DSAImportExport.AssertKeyEquals(DSATestData.Dsa512Parameters, dsaParameters); + } + + [Fact] + public static void ImportFromPem_Pkcs8_PrecedingMalformedPem() + { + string pem = @" +-----BEGIN CERTIFICATE----- +$$$ BAD PEM +-----END CERTIFICATE----- +-----BEGIN PRIVATE KEY----- +MIHGAgEAMIGoBgcqhkjOOAQBMIGcAkEA1qi38cr3ppZNB2Y/xpHSL2q81Vw3rvWN +IHRnQNgv4U4UY2NifZGSUULc3uOEvgoeBO1b9fRxSG9NmG1CoufflQIVAPq19iXV +1eFkMKHvYw6+M4l8wiT5AkAIRMSQ5S71jgWQLGNtZNHV6yxggqDU87/RzgeOh7Q6 +fve77OGaTv4qbZwinTYAg86p9yHzmwW6+XBS3vxnpYorBBYCFC49eoTIW2Z4Xh9v +55aYKyKwy5i8 +-----END PRIVATE KEY-----"; + + using DSA dsa = DSAFactory.Create(); + dsa.ImportFromPem(pem); + DSAParameters dsaParameters = dsa.ExportParameters(true); + + DSAImportExport.AssertKeyEquals(DSATestData.Dsa512Parameters, dsaParameters); + } + + [Fact] + public static void ImportFromPem_SubjectPublicKeyInfo_Simple() + { + string pem = @" +-----BEGIN PUBLIC KEY----- +MIHxMIGoBgcqhkjOOAQBMIGcAkEA1qi38cr3ppZNB2Y/xpHSL2q81Vw3rvWNIHRn +QNgv4U4UY2NifZGSUULc3uOEvgoeBO1b9fRxSG9NmG1CoufflQIVAPq19iXV1eFk +MKHvYw6+M4l8wiT5AkAIRMSQ5S71jgWQLGNtZNHV6yxggqDU87/RzgeOh7Q6fve7 +7OGaTv4qbZwinTYAg86p9yHzmwW6+XBS3vxnpYorA0QAAkEAwwDg5n2HfmztOf7q +qsHywr1WjmoyRnIn4Stq5FqNlHhUGkgKyAA4qshjgn1uOYQGGiWQXBi9JJmoOWY8 +PKRWBQ== +-----END PUBLIC KEY-----"; + + using DSA dsa = DSAFactory.Create(); + dsa.ImportFromPem(pem); + DSAParameters dsaParameters = dsa.ExportParameters(false); + + DSAImportExport.AssertKeyEquals(DSATestData.Dsa512Parameters.ToPublic(), dsaParameters); + } + + [Fact] + public static void ImportFromPem_Pkcs8_AmbiguousKey_Pkcs8() + { + string pem = @" +-----BEGIN PRIVATE KEY----- +MIHGAgEAMIGoBgcqhkjOOAQBMIGcAkEA1qi38cr3ppZNB2Y/xpHSL2q81Vw3rvWN +IHRnQNgv4U4UY2NifZGSUULc3uOEvgoeBO1b9fRxSG9NmG1CoufflQIVAPq19iXV +1eFkMKHvYw6+M4l8wiT5AkAIRMSQ5S71jgWQLGNtZNHV6yxggqDU87/RzgeOh7Q6 +fve77OGaTv4qbZwinTYAg86p9yHzmwW6+XBS3vxnpYorBBYCFC49eoTIW2Z4Xh9v +55aYKyKwy5i8 +-----END PRIVATE KEY----- +-----BEGIN PRIVATE KEY----- +MIHGAgEAMIGoBgcqhkjOOAQBMIGcAkEA1qi38cr3ppZNB2Y/xpHSL2q81Vw3rvWN +IHRnQNgv4U4UY2NifZGSUULc3uOEvgoeBO1b9fRxSG9NmG1CoufflQIVAPq19iXV +1eFkMKHvYw6+M4l8wiT5AkAIRMSQ5S71jgWQLGNtZNHV6yxggqDU87/RzgeOh7Q6 +fve77OGaTv4qbZwinTYAg86p9yHzmwW6+XBS3vxnpYorBBYCFC49eoTIW2Z4Xh9v +55aYKyKwy5i8 +-----END PRIVATE KEY-----"; + + using DSA dsa = DSAFactory.Create(); + AssertExtensions.Throws("input", () => dsa.ImportFromPem(pem)); + } + + [Fact] + public static void ImportFromPem_Pkcs8_AmbiguousKey_Spki() + { + string pem = @" +-----BEGIN PUBLIC KEY----- +MIHxMIGoBgcqhkjOOAQBMIGcAkEA1qi38cr3ppZNB2Y/xpHSL2q81Vw3rvWNIHRn +QNgv4U4UY2NifZGSUULc3uOEvgoeBO1b9fRxSG9NmG1CoufflQIVAPq19iXV1eFk +MKHvYw6+M4l8wiT5AkAIRMSQ5S71jgWQLGNtZNHV6yxggqDU87/RzgeOh7Q6fve7 +7OGaTv4qbZwinTYAg86p9yHzmwW6+XBS3vxnpYorA0QAAkEAwwDg5n2HfmztOf7q +qsHywr1WjmoyRnIn4Stq5FqNlHhUGkgKyAA4qshjgn1uOYQGGiWQXBi9JJmoOWY8 +PKRWBQ== +-----END PUBLIC KEY----- +-----BEGIN PRIVATE KEY----- +MIHGAgEAMIGoBgcqhkjOOAQBMIGcAkEA1qi38cr3ppZNB2Y/xpHSL2q81Vw3rvWN +IHRnQNgv4U4UY2NifZGSUULc3uOEvgoeBO1b9fRxSG9NmG1CoufflQIVAPq19iXV +1eFkMKHvYw6+M4l8wiT5AkAIRMSQ5S71jgWQLGNtZNHV6yxggqDU87/RzgeOh7Q6 +fve77OGaTv4qbZwinTYAg86p9yHzmwW6+XBS3vxnpYorBBYCFC49eoTIW2Z4Xh9v +55aYKyKwy5i8 +-----END PRIVATE KEY-----"; + + using DSA dsa = DSAFactory.Create(); + AssertExtensions.Throws("input", () => dsa.ImportFromPem(pem)); + } + + [Fact] + public static void ImportFromPem_Pkcs8_AmbiguousKey_EncryptedPkcs8() + { + string pem = @" +-----BEGIN ENCRYPTED PRIVATE KEY----- +MIIBIDBLBgkqhkiG9w0BBQ0wPjApBgkqhkiG9w0BBQwwHAQIkM/kCKe6rYsCAggA +MAwGCCqGSIb3DQIJBQAwEQYFKw4DAgcECBOccveL65bDBIHQiCcCqwxJs93g1+16 +7Gx1D5lL4/nZ94fRa+Hl4nGEX4gmjuxH6pOHKyywwflAyXNTfVhOCP9zBedwENx9 +MGHbpaaShD6iJfoGMRX0frr0mMCtuOOZkkjBF9pSpkhaH0TDSq1PrVLxcM0/S4Vs ++//2uPrP8U+CTW9W7CXCZw698BAuevZRuD0koT2Bn9ErhTiuVZZMcOjtLmN2oXHG +dVYwfovccu8ktEAwk5XAOo0r+5CCw2lDDw/hbDeO87BToC5Cc5nu3F5LxAUj8Flc +v8pi3w== +-----END ENCRYPTED PRIVATE KEY----- +-----BEGIN PRIVATE KEY----- +MIHGAgEAMIGoBgcqhkjOOAQBMIGcAkEA1qi38cr3ppZNB2Y/xpHSL2q81Vw3rvWN +IHRnQNgv4U4UY2NifZGSUULc3uOEvgoeBO1b9fRxSG9NmG1CoufflQIVAPq19iXV +1eFkMKHvYw6+M4l8wiT5AkAIRMSQ5S71jgWQLGNtZNHV6yxggqDU87/RzgeOh7Q6 +fve77OGaTv4qbZwinTYAg86p9yHzmwW6+XBS3vxnpYorBBYCFC49eoTIW2Z4Xh9v +55aYKyKwy5i8 +-----END PRIVATE KEY-----"; + + using DSA dsa = DSAFactory.Create(); + AssertExtensions.Throws("input", () => dsa.ImportFromPem(pem)); + } + + [Fact] + public static void ImportFromPem_EncryptedPrivateKeyFails() + { + string pem = @" +-----BEGIN ENCRYPTED PRIVATE KEY----- +MIIBIDBLBgkqhkiG9w0BBQ0wPjApBgkqhkiG9w0BBQwwHAQIkM/kCKe6rYsCAggA +MAwGCCqGSIb3DQIJBQAwEQYFKw4DAgcECBOccveL65bDBIHQiCcCqwxJs93g1+16 +7Gx1D5lL4/nZ94fRa+Hl4nGEX4gmjuxH6pOHKyywwflAyXNTfVhOCP9zBedwENx9 +MGHbpaaShD6iJfoGMRX0frr0mMCtuOOZkkjBF9pSpkhaH0TDSq1PrVLxcM0/S4Vs ++//2uPrP8U+CTW9W7CXCZw698BAuevZRuD0koT2Bn9ErhTiuVZZMcOjtLmN2oXHG +dVYwfovccu8ktEAwk5XAOo0r+5CCw2lDDw/hbDeO87BToC5Cc5nu3F5LxAUj8Flc +v8pi3w== +-----END ENCRYPTED PRIVATE KEY-----"; + + using DSA dsa = DSAFactory.Create(); + AssertExtensions.Throws("input", () => dsa.ImportFromPem(pem)); + } + + [Fact] + public static void ImportFromPem_SpkiAlgorithmMismatch_Throws() + { + string pem = @" +The below key is for an RSA SPKI +-----BEGIN PUBLIC KEY----- +MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBALc/WfXui9VeJLf/AprRaoVDyW0lPlQx +m5NTLEHDwUd7idstLzPXuah0WEjgao5oO1BEUR4byjYlJ+F89Cs4BhUCAwEAAQ== +-----END PUBLIC KEY-----"; + + using DSA dsa = DSAFactory.Create(); + Assert.Throws(() => dsa.ImportFromPem(pem)); + } + + [Fact] + public static void ImportFromEncryptedPem_Pkcs8_Encrypted_Char_Simple() + { + string pem = @" +-----BEGIN ENCRYPTED PRIVATE KEY----- +MIIBIDBLBgkqhkiG9w0BBQ0wPjApBgkqhkiG9w0BBQwwHAQIkM/kCKe6rYsCAggA +MAwGCCqGSIb3DQIJBQAwEQYFKw4DAgcECBOccveL65bDBIHQiCcCqwxJs93g1+16 +7Gx1D5lL4/nZ94fRa+Hl4nGEX4gmjuxH6pOHKyywwflAyXNTfVhOCP9zBedwENx9 +MGHbpaaShD6iJfoGMRX0frr0mMCtuOOZkkjBF9pSpkhaH0TDSq1PrVLxcM0/S4Vs ++//2uPrP8U+CTW9W7CXCZw698BAuevZRuD0koT2Bn9ErhTiuVZZMcOjtLmN2oXHG +dVYwfovccu8ktEAwk5XAOo0r+5CCw2lDDw/hbDeO87BToC5Cc5nu3F5LxAUj8Flc +v8pi3w== +-----END ENCRYPTED PRIVATE KEY-----"; + + using DSA dsa = DSAFactory.Create(); + dsa.ImportFromEncryptedPem(pem, "test"); + DSAParameters dsaParameters = dsa.ExportParameters(true); + + DSAImportExport.AssertKeyEquals(DSATestData.Dsa512Parameters, dsaParameters); + } + + [Fact] + public static void ImportFromEncryptedPem_Pkcs8_Encrypted_Byte_Simple() + { + string pem = @" +-----BEGIN ENCRYPTED PRIVATE KEY----- +MIIBLDBXBgkqhkiG9w0BBQ0wSjApBgkqhkiG9w0BBQwwHAQIfcoipdEY/C4CAggA +MAwGCCqGSIb3DQIJBQAwHQYJYIZIAWUDBAECBBC9heEphj00fB89aP6chSOjBIHQ +HF2RLrIw6654q2hjUdCG4PhhYNXlck0zD0mOuaVQHmnKIKArk/1DSpgSrYnKw6aE +2eujwNdySLLEwUj5l+X/IXwhOnPIZDJqUN7oMagUYJX28gnQmXyDvrt3r16utbpd +ho0YNYGUDSgOs6RxBpw1rJUCnAlHNU09peCjEP+aZSrhsxlejN/GpVS4e0JTmMeo +xTL6VO9mx52x6h5WDAQAisMVeMkBoxQUWLANXiw1zSfVbsmB7mDknsRcvD3tcgMs +7YLD7LQMiPAIjDlOP8XP/w== +-----END ENCRYPTED PRIVATE KEY-----"; + + using DSA dsa = DSAFactory.Create(); + byte[] passwordBytes = Encoding.UTF8.GetBytes("test"); + dsa.ImportFromEncryptedPem(pem, passwordBytes); + DSAParameters dsaParameters = dsa.ExportParameters(true); + + DSAImportExport.AssertKeyEquals(DSATestData.Dsa512Parameters, dsaParameters); + } + + [Fact] + public static void ImportFromEncryptedPem_Pkcs8_Encrypted_AmbiguousPem() + { + string pem = @" +-----BEGIN ENCRYPTED PRIVATE KEY----- +MIIBLDBXBgkqhkiG9w0BBQ0wSjApBgkqhkiG9w0BBQwwHAQIfcoipdEY/C4CAggA +MAwGCCqGSIb3DQIJBQAwHQYJYIZIAWUDBAECBBC9heEphj00fB89aP6chSOjBIHQ +HF2RLrIw6654q2hjUdCG4PhhYNXlck0zD0mOuaVQHmnKIKArk/1DSpgSrYnKw6aE +2eujwNdySLLEwUj5l+X/IXwhOnPIZDJqUN7oMagUYJX28gnQmXyDvrt3r16utbpd +ho0YNYGUDSgOs6RxBpw1rJUCnAlHNU09peCjEP+aZSrhsxlejN/GpVS4e0JTmMeo +xTL6VO9mx52x6h5WDAQAisMVeMkBoxQUWLANXiw1zSfVbsmB7mDknsRcvD3tcgMs +7YLD7LQMiPAIjDlOP8XP/w== +-----END ENCRYPTED PRIVATE KEY----- +-----BEGIN ENCRYPTED PRIVATE KEY----- +MIIBIDBLBgkqhkiG9w0BBQ0wPjApBgkqhkiG9w0BBQwwHAQIkM/kCKe6rYsCAggA +MAwGCCqGSIb3DQIJBQAwEQYFKw4DAgcECBOccveL65bDBIHQiCcCqwxJs93g1+16 +7Gx1D5lL4/nZ94fRa+Hl4nGEX4gmjuxH6pOHKyywwflAyXNTfVhOCP9zBedwENx9 +MGHbpaaShD6iJfoGMRX0frr0mMCtuOOZkkjBF9pSpkhaH0TDSq1PrVLxcM0/S4Vs ++//2uPrP8U+CTW9W7CXCZw698BAuevZRuD0koT2Bn9ErhTiuVZZMcOjtLmN2oXHG +dVYwfovccu8ktEAwk5XAOo0r+5CCw2lDDw/hbDeO87BToC5Cc5nu3F5LxAUj8Flc +v8pi3w== +-----END ENCRYPTED PRIVATE KEY-----"; + + using DSA dsa = DSAFactory.Create(); + byte[] passwordBytes = Encoding.UTF8.GetBytes("test"); + AssertExtensions.Throws("input", () => dsa.ImportFromEncryptedPem(pem, passwordBytes)); + } + + [Fact] + public static void ImportFromEncryptedPem_Pkcs8_Byte_NoPem() + { + string pem = ""; + using DSA dsa = DSAFactory.Create(); + byte[] passwordBytes = Encoding.UTF8.GetBytes("test"); + AssertExtensions.Throws("input", () => dsa.ImportFromEncryptedPem(pem, passwordBytes)); + } + + [Fact] + public static void ImportFromEncryptedPem_Pkcs8_Char_NoPem() + { + string pem = ""; + using DSA dsa = DSAFactory.Create(); + AssertExtensions.Throws("input", () => dsa.ImportFromEncryptedPem(pem, "k")); + } + + private static DSAParameters ToPublic(this DSAParameters dsaParams) + { + dsaParams.X = null; + return dsaParams; + } + } +} diff --git a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/EC/ECKeyPemTests.cs b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/EC/ECKeyPemTests.cs new file mode 100644 index 0000000000000..3a98f36d99900 --- /dev/null +++ b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/EC/ECKeyPemTests.cs @@ -0,0 +1,295 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Text; +using Test.Cryptography; +using Xunit; + +namespace System.Security.Cryptography.Tests +{ + public abstract class ECKeyPemTests where TAlg : AsymmetricAlgorithm + { + protected abstract TAlg CreateKey(); + protected abstract ECParameters ExportParameters(TAlg key, bool includePrivateParameters); + + [Fact] + public void ImportFromPem_NoPem() + { + using TAlg key = CreateKey(); + AssertExtensions.Throws("input", () => key.ImportFromPem("")); + } + + [Fact] + public void ImportFromPem_ECPrivateKey_Simple() + { + using TAlg key = CreateKey(); + key.ImportFromPem(@" +-----BEGIN EC PRIVATE KEY----- +MHcCAQEEIHChLC2xaEXtVv9oz8IaRys/BNfWhRv2NJ8tfVs0UrOKoAoGCCqGSM49 +AwEHoUQDQgAEgQHs5HRkpurXDPaabivT2IaRoyYtIsuk92Ner/JmgKjYoSumHVmS +NfZ9nLTVjxeD08pD548KWrqmJAeZNsDDqQ== +-----END EC PRIVATE KEY-----"); + ECParameters ecParameters = ExportParameters(key, true); + ECParameters expected = EccTestData.GetNistP256ReferenceKey(); + EccTestBase.AssertEqual(expected, ecParameters); + } + + [Fact] + public void ImportFromPem_Pkcs8_Simple() + { + using TAlg key = CreateKey(); + key.ImportFromPem(@" +-----BEGIN PRIVATE KEY----- +MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgcKEsLbFoRe1W/2jP +whpHKz8E19aFG/Y0ny19WzRSs4qhRANCAASBAezkdGSm6tcM9ppuK9PYhpGjJi0i +y6T3Y16v8maAqNihK6YdWZI19n2ctNWPF4PTykPnjwpauqYkB5k2wMOp +-----END PRIVATE KEY-----"); + ECParameters ecParameters = ExportParameters(key, true); + ECParameters expected = EccTestData.GetNistP256ReferenceKey(); + EccTestBase.AssertEqual(expected, ecParameters); + } + + [Fact] + public void ImportFromPem_Spki_Simple() + { + using TAlg key = CreateKey(); + key.ImportFromPem(@" +-----BEGIN PUBLIC KEY----- +MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEgQHs5HRkpurXDPaabivT2IaRoyYt +Isuk92Ner/JmgKjYoSumHVmSNfZ9nLTVjxeD08pD548KWrqmJAeZNsDDqQ== +-----END PUBLIC KEY-----"); + ECParameters ecParameters = ExportParameters(key, false); + ECParameters expected = EccTestData.GetNistP256ReferenceKey(); + EccTestBase.ComparePublicKey(expected.Q, ecParameters.Q, isEqual: true); + } + + [Fact] + public void ImportFromPem_ECPrivateKey_ExplicitParams() + { + using TAlg key = CreateKey(); + key.ImportFromPem(@" +-----BEGIN EC PRIVATE KEY----- +MIIBaAIBAQQgcKEsLbFoRe1W/2jPwhpHKz8E19aFG/Y0ny19WzRSs4qggfowgfcC +AQEwLAYHKoZIzj0BAQIhAP////8AAAABAAAAAAAAAAAAAAAA//////////////// +MFsEIP////8AAAABAAAAAAAAAAAAAAAA///////////////8BCBaxjXYqjqT57Pr +vVV2mIa8ZR0GsMxTsPY7zjw+J9JgSwMVAMSdNgiG5wSTamZ44ROdJreBn36QBEEE +axfR8uEsQkf4vOblY6RA8ncDfYEt6zOg9KE5RdiYwpZP40Li/hp/m47n60p8D54W +K84zV2sxXs7LtkBoN79R9QIhAP////8AAAAA//////////+85vqtpxeehPO5ysL8 +YyVRAgEBoUQDQgAEgQHs5HRkpurXDPaabivT2IaRoyYtIsuk92Ner/JmgKjYoSum +HVmSNfZ9nLTVjxeD08pD548KWrqmJAeZNsDDqQ== +-----END EC PRIVATE KEY-----"); + ECParameters ecParameters = ExportParameters(key, true); + ECParameters expected = EccTestData.GetNistP256ReferenceKeyExplicit(); + EccTestBase.AssertEqual(expected, ecParameters); + } + + [Fact] + public void ImportFromPem_Pkcs8_ExplicitParams() + { + using TAlg key = CreateKey(); + key.ImportFromPem(@" +-----BEGIN PRIVATE KEY----- +MIIBeQIBADCCAQMGByqGSM49AgEwgfcCAQEwLAYHKoZIzj0BAQIhAP////8AAAAB +AAAAAAAAAAAAAAAA////////////////MFsEIP////8AAAABAAAAAAAAAAAAAAAA +///////////////8BCBaxjXYqjqT57PrvVV2mIa8ZR0GsMxTsPY7zjw+J9JgSwMV +AMSdNgiG5wSTamZ44ROdJreBn36QBEEEaxfR8uEsQkf4vOblY6RA8ncDfYEt6zOg +9KE5RdiYwpZP40Li/hp/m47n60p8D54WK84zV2sxXs7LtkBoN79R9QIhAP////8A +AAAA//////////+85vqtpxeehPO5ysL8YyVRAgEBBG0wawIBAQQgcKEsLbFoRe1W +/2jPwhpHKz8E19aFG/Y0ny19WzRSs4qhRANCAASBAezkdGSm6tcM9ppuK9PYhpGj +Ji0iy6T3Y16v8maAqNihK6YdWZI19n2ctNWPF4PTykPnjwpauqYkB5k2wMOp +-----END PRIVATE KEY-----"); + ECParameters ecParameters = ExportParameters(key, true); + ECParameters expected = EccTestData.GetNistP256ReferenceKeyExplicit(); + EccTestBase.AssertEqual(expected, ecParameters); + } + + [Fact] + public void ImportFromPem_Spki_PrecedingUnrelatedPemIsIgnored() + { + using TAlg key = CreateKey(); + key.ImportFromPem(@" +-----BEGIN CERTIFICATE----- +MIICTzCCAgmgAwIBAgIJAMQtYhFJ0+5jMA0GCSqGSIb3DQEBBQUAMIGSMQswCQYD +VQQGEwJVUzETMBEGA1UECAwKV2FzaGluZ3RvbjEQMA4GA1UEBwwHUmVkbW9uZDEY +MBYGA1UECgwPTWljcm9zb2Z0IENvcnAuMSAwHgYDVQQLDBcuTkVUIEZyYW1ld29y +ayAoQ29yZUZ4KTEgMB4GA1UEAwwXUlNBIDM4NC1iaXQgQ2VydGlmaWNhdGUwHhcN +MTYwMzAyMTY1OTA0WhcNMTYwNDAxMTY1OTA0WjCBkjELMAkGA1UEBhMCVVMxEzAR +BgNVBAgMCldhc2hpbmd0b24xEDAOBgNVBAcMB1JlZG1vbmQxGDAWBgNVBAoMD01p +Y3Jvc29mdCBDb3JwLjEgMB4GA1UECwwXLk5FVCBGcmFtZXdvcmsgKENvcmVGeCkx +IDAeBgNVBAMMF1JTQSAzODQtYml0IENlcnRpZmljYXRlMEwwDQYJKoZIhvcNAQEB +BQADOwAwOAIxANrMIthuZxV1Ay4x8gbc/BksZeLVEInlES0JbyiCr9tbeM22Vy/S +9h2zkEciMuPZ9QIDAQABo1AwTjAdBgNVHQ4EFgQU5FG2Fmi86hJOCf4KnjaxOGWV +dRUwHwYDVR0jBBgwFoAU5FG2Fmi86hJOCf4KnjaxOGWVdRUwDAYDVR0TBAUwAwEB +/zANBgkqhkiG9w0BAQUFAAMxAEzDg/u8TlApCnE8qxhcbTXk2MbX+2n5PCn+MVrW +wggvPj3b2WMXsVWiPr4S1Y/nBA== +-----END CERTIFICATE----- +-----BEGIN PUBLIC KEY----- +MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEgQHs5HRkpurXDPaabivT2IaRoyYt +Isuk92Ner/JmgKjYoSumHVmSNfZ9nLTVjxeD08pD548KWrqmJAeZNsDDqQ== +-----END PUBLIC KEY-----"); + ECParameters ecParameters = ExportParameters(key, false); + ECParameters expected = EccTestData.GetNistP256ReferenceKey(); + EccTestBase.ComparePublicKey(expected.Q, ecParameters.Q, isEqual: true); + } + + [Fact] + public void ImportFromPem_Spki_PrecedingMalformedPem() + { + using TAlg key = CreateKey(); + key.ImportFromPem(@" +-----BEGIN CERTIFICATE----- +$$ I AM NOT A PEM +-----END CERTIFICATE----- +-----BEGIN PUBLIC KEY----- +MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEgQHs5HRkpurXDPaabivT2IaRoyYt +Isuk92Ner/JmgKjYoSumHVmSNfZ9nLTVjxeD08pD548KWrqmJAeZNsDDqQ== +-----END PUBLIC KEY-----"); + ECParameters ecParameters = ExportParameters(key, false); + ECParameters expected = EccTestData.GetNistP256ReferenceKey(); + EccTestBase.ComparePublicKey(expected.Q, ecParameters.Q, isEqual: true); + } + + [Fact] + public void ImportFromPem_Spki_AmbiguousKey_Spki() + { + string pem = @" +-----BEGIN PUBLIC KEY----- +MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEgQHs5HRkpurXDPaabivT2IaRoyYt +Isuk92Ner/JmgKjYoSumHVmSNfZ9nLTVjxeD08pD548KWrqmJAeZNsDDqQ== +-----END PUBLIC KEY----- +-----BEGIN PUBLIC KEY----- +MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEgQHs5HRkpurXDPaabivT2IaRoyYt +Isuk92Ner/JmgKjYoSumHVmSNfZ9nLTVjxeD08pD548KWrqmJAeZNsDDqQ== +-----END PUBLIC KEY-----"; + using TAlg key = CreateKey(); + AssertExtensions.Throws("input", () => key.ImportFromPem(pem)); + } + + [Fact] + public void ImportFromPem_Spki_AmbiguousKey_EncryptedPkcs8() + { + string pem = @" +-----BEGIN ENCRYPTED PRIVATE KEY----- +MIHgMEsGCSqGSIb3DQEFDTA+MCkGCSqGSIb3DQEFDDAcBAjVvm4KTLb0JgICCAAw +DAYIKoZIhvcNAgkFADARBgUrDgMCBwQIuHgfok8Ytl0EgZDkDSJ9vt8UvSesdyV+ +Evt9yfvEjiP/6yITq59drw1Kcgp6buOCVCY7LZ06aD6WpogiqGDYMuzfvqg5hNFp +opSAJ/pvHONL5kyAJLeNyG9c/mR2qyrP2L9gL0Z5fB9NyPejKTLi0PXMGQWdDTH8 +Qh0fqdrNovgFLubbJFMQN/MwwIAfIuf0Mn0WFYYeQiBJ3kg= +-----END ENCRYPTED PRIVATE KEY----- +-----BEGIN PUBLIC KEY----- +MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEgQHs5HRkpurXDPaabivT2IaRoyYt +Isuk92Ner/JmgKjYoSumHVmSNfZ9nLTVjxeD08pD548KWrqmJAeZNsDDqQ== +-----END PUBLIC KEY-----"; + using TAlg key = CreateKey(); + AssertExtensions.Throws("input", () => key.ImportFromPem(pem)); + } + + [Fact] + public void ImportFromPem_EncryptedPrivateKeyFails() + { + string pem = @" +-----BEGIN ENCRYPTED PRIVATE KEY----- +MIHgMEsGCSqGSIb3DQEFDTA+MCkGCSqGSIb3DQEFDDAcBAjVvm4KTLb0JgICCAAw +DAYIKoZIhvcNAgkFADARBgUrDgMCBwQIuHgfok8Ytl0EgZDkDSJ9vt8UvSesdyV+ +Evt9yfvEjiP/6yITq59drw1Kcgp6buOCVCY7LZ06aD6WpogiqGDYMuzfvqg5hNFp +opSAJ/pvHONL5kyAJLeNyG9c/mR2qyrP2L9gL0Z5fB9NyPejKTLi0PXMGQWdDTH8 +Qh0fqdrNovgFLubbJFMQN/MwwIAfIuf0Mn0WFYYeQiBJ3kg= +-----END ENCRYPTED PRIVATE KEY-----"; + using TAlg key = CreateKey(); + AssertExtensions.Throws("input", () => key.ImportFromPem(pem)); + } + + [Fact] + public void ImportFromEncryptedPem_Pkcs8_Char_Simple() + { + string pem = @" +-----BEGIN ENCRYPTED PRIVATE KEY----- +MIHgMEsGCSqGSIb3DQEFDTA+MCkGCSqGSIb3DQEFDDAcBAjVvm4KTLb0JgICCAAw +DAYIKoZIhvcNAgkFADARBgUrDgMCBwQIuHgfok8Ytl0EgZDkDSJ9vt8UvSesdyV+ +Evt9yfvEjiP/6yITq59drw1Kcgp6buOCVCY7LZ06aD6WpogiqGDYMuzfvqg5hNFp +opSAJ/pvHONL5kyAJLeNyG9c/mR2qyrP2L9gL0Z5fB9NyPejKTLi0PXMGQWdDTH8 +Qh0fqdrNovgFLubbJFMQN/MwwIAfIuf0Mn0WFYYeQiBJ3kg= +-----END ENCRYPTED PRIVATE KEY-----"; + using TAlg key = CreateKey(); + key.ImportFromEncryptedPem(pem, "test"); + ECParameters ecParameters = ExportParameters(key, true); + ECParameters expected = EccTestData.GetNistP256ReferenceKey(); + EccTestBase.AssertEqual(expected, ecParameters); + } + + [Fact] + public void ImportFromEncryptedPem_Pkcs8_Byte_Simple() + { + string pem = @" +-----BEGIN ENCRYPTED PRIVATE KEY----- +MIHsMFcGCSqGSIb3DQEFDTBKMCkGCSqGSIb3DQEFDDAcBAgf9krO2ZiPvAICCAAw +DAYIKoZIhvcNAgkFADAdBglghkgBZQMEAQIEEEv4Re1ATH9lHzx+13GoZU0EgZAV +iE/+pIb/4quf+Y524bXUKTGYXzdSUE8Dp1qdZFcwDiCYCTtpL+065fGhmf1KZS2c +/OMt/tWvtMSj17+dJvShsu/NYJXF5fsfpSJbd3e50Y3AisW0Ob7mmF54KBfg6Y+4 +aATwwQdUIKVzUZsQctsHPjbriQKKn7GKSyUOikBUNQ+TozojX8/g7JAsl+T9jGM= +-----END ENCRYPTED PRIVATE KEY-----"; + using TAlg key = CreateKey(); + byte[] passwordBytes = Encoding.UTF8.GetBytes("test"); + key.ImportFromEncryptedPem(pem, passwordBytes); + ECParameters ecParameters = ExportParameters(key, true); + ECParameters expected = EccTestData.GetNistP256ReferenceKey(); + EccTestBase.AssertEqual(expected, ecParameters); + } + + [Fact] + public void ImportFromEncryptedPem_AmbiguousPem_Byte() + { + string pem = @" +-----BEGIN ENCRYPTED PRIVATE KEY----- +MIHsMFcGCSqGSIb3DQEFDTBKMCkGCSqGSIb3DQEFDDAcBAgf9krO2ZiPvAICCAAw +DAYIKoZIhvcNAgkFADAdBglghkgBZQMEAQIEEEv4Re1ATH9lHzx+13GoZU0EgZAV +iE/+pIb/4quf+Y524bXUKTGYXzdSUE8Dp1qdZFcwDiCYCTtpL+065fGhmf1KZS2c +/OMt/tWvtMSj17+dJvShsu/NYJXF5fsfpSJbd3e50Y3AisW0Ob7mmF54KBfg6Y+4 +aATwwQdUIKVzUZsQctsHPjbriQKKn7GKSyUOikBUNQ+TozojX8/g7JAsl+T9jGM= +-----END ENCRYPTED PRIVATE KEY----- +-----BEGIN ENCRYPTED PRIVATE KEY----- +MIHgMEsGCSqGSIb3DQEFDTA+MCkGCSqGSIb3DQEFDDAcBAjVvm4KTLb0JgICCAAw +DAYIKoZIhvcNAgkFADARBgUrDgMCBwQIuHgfok8Ytl0EgZDkDSJ9vt8UvSesdyV+ +Evt9yfvEjiP/6yITq59drw1Kcgp6buOCVCY7LZ06aD6WpogiqGDYMuzfvqg5hNFp +opSAJ/pvHONL5kyAJLeNyG9c/mR2qyrP2L9gL0Z5fB9NyPejKTLi0PXMGQWdDTH8 +Qh0fqdrNovgFLubbJFMQN/MwwIAfIuf0Mn0WFYYeQiBJ3kg= +-----END ENCRYPTED PRIVATE KEY-----"; + using TAlg key = CreateKey(); + byte[] passwordBytes = Encoding.UTF8.GetBytes("test"); + + AssertExtensions.Throws("input", () => + key.ImportFromEncryptedPem(pem, passwordBytes)); + } + + [Fact] + public void ImportFromEncryptedPem_AmbiguousPem_Char() + { + string pem = @" +-----BEGIN ENCRYPTED PRIVATE KEY----- +MIHsMFcGCSqGSIb3DQEFDTBKMCkGCSqGSIb3DQEFDDAcBAgf9krO2ZiPvAICCAAw +DAYIKoZIhvcNAgkFADAdBglghkgBZQMEAQIEEEv4Re1ATH9lHzx+13GoZU0EgZAV +iE/+pIb/4quf+Y524bXUKTGYXzdSUE8Dp1qdZFcwDiCYCTtpL+065fGhmf1KZS2c +/OMt/tWvtMSj17+dJvShsu/NYJXF5fsfpSJbd3e50Y3AisW0Ob7mmF54KBfg6Y+4 +aATwwQdUIKVzUZsQctsHPjbriQKKn7GKSyUOikBUNQ+TozojX8/g7JAsl+T9jGM= +-----END ENCRYPTED PRIVATE KEY----- +-----BEGIN ENCRYPTED PRIVATE KEY----- +MIHgMEsGCSqGSIb3DQEFDTA+MCkGCSqGSIb3DQEFDDAcBAjVvm4KTLb0JgICCAAw +DAYIKoZIhvcNAgkFADARBgUrDgMCBwQIuHgfok8Ytl0EgZDkDSJ9vt8UvSesdyV+ +Evt9yfvEjiP/6yITq59drw1Kcgp6buOCVCY7LZ06aD6WpogiqGDYMuzfvqg5hNFp +opSAJ/pvHONL5kyAJLeNyG9c/mR2qyrP2L9gL0Z5fB9NyPejKTLi0PXMGQWdDTH8 +Qh0fqdrNovgFLubbJFMQN/MwwIAfIuf0Mn0WFYYeQiBJ3kg= +-----END ENCRYPTED PRIVATE KEY-----"; + using TAlg key = CreateKey(); + AssertExtensions.Throws("input", () => + key.ImportFromEncryptedPem(pem, "")); + } + + [Fact] + public void ImportFromEncryptedPem_NoPem() + { + using TAlg key = CreateKey(); + AssertExtensions.Throws("input", () => key.ImportFromEncryptedPem("", "")); + } + } +} diff --git a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/ECDiffieHellman/ECDiffieHellmanKeyPemTests.cs b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/ECDiffieHellman/ECDiffieHellmanKeyPemTests.cs new file mode 100644 index 0000000000000..2e6985a220f8c --- /dev/null +++ b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/ECDiffieHellman/ECDiffieHellmanKeyPemTests.cs @@ -0,0 +1,15 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Security.Cryptography.Tests; + +namespace System.Security.Cryptography.EcDsa.Tests +{ + public sealed class ECDiffieHellmanKeyPemTests : ECKeyPemTests + { + protected override ECDiffieHellman CreateKey() => ECDiffieHellman.Create(); + protected override ECParameters ExportParameters(ECDiffieHellman key, bool includePrivateParameters) => + key.ExportParameters(includePrivateParameters); + } +} diff --git a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/ECDsa/ECDsaKeyPemTests.cs b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/ECDsa/ECDsaKeyPemTests.cs new file mode 100644 index 0000000000000..8358edca90acd --- /dev/null +++ b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/ECDsa/ECDsaKeyPemTests.cs @@ -0,0 +1,15 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Security.Cryptography.Tests; + +namespace System.Security.Cryptography.EcDsa.Tests +{ + public sealed class ECDsaKeyPemTests : ECKeyPemTests + { + protected override ECDsa CreateKey() => ECDsa.Create(); + protected override ECParameters ExportParameters(ECDsa key, bool includePrivateParameters) => + key.ExportParameters(includePrivateParameters); + } +} diff --git a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/RSA/RSAKeyPemTests.cs b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/RSA/RSAKeyPemTests.cs new file mode 100644 index 0000000000000..7a18f1dc3f30a --- /dev/null +++ b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/RSA/RSAKeyPemTests.cs @@ -0,0 +1,384 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Text; +using Test.Cryptography; +using Xunit; + +namespace System.Security.Cryptography.Rsa.Tests +{ + public static class RSAKeyPemTests + { + [Fact] + public static void ImportFromPem_NoPem() + { + string pem = @"these aren't the PEMs you're looking for"; + using RSA rsa = RSAFactory.Create(); + AssertExtensions.Throws("input", () => rsa.ImportFromPem(pem)); + } + + [Fact] + public static void ImportFromPem_RSAPrivateKey_Simple() + { + string pem = @" +-----BEGIN RSA PRIVATE KEY----- +MIIBOwIBAAJBALc/WfXui9VeJLf/AprRaoVDyW0lPlQxm5NTLEHDwUd7idstLzPX +uah0WEjgao5oO1BEUR4byjYlJ+F89Cs4BhUCAwEAAQJBAK/m8jYvnK9exaSR+DAh +Ij12ip5pB+HOFOdhCbS/coNoIowa6WJGrd3Np1m9BBhouWloF8UB6Iu8/e/wAg+F +9ykCIQDzcnsehnYgVZTTxzoCJ01PGpgESilRyFzNEsb8V60ZewIhAMCyOujqUqn7 +Q079SlHzXuvocqIdt4IM1EmIlrlU9GGvAh8Ijv3FFPUSLfANgfOIH9mX7ldpzzGk +rmaUzxQvyuVLAiEArCTM8dSbopUADWnD4jArhU50UhWAIaM6ZrKqC8k0RKsCIQDC +yZWUxoxAdjfrBGsx+U6BHM0Myqqe7fY7hjWzj4aBCw== +-----END RSA PRIVATE KEY-----"; + + using RSA rsa = RSAFactory.Create(); + rsa.ImportFromPem(pem); + RSAParameters rsaParameters = rsa.ExportParameters(true); + + ImportExport.AssertKeyEquals(TestData.DiminishedDPParameters, rsaParameters); + } + + [Fact] + public static void ImportFromPem_Pkcs8UnEncrypted_Simple() + { + string pem = @" +-----BEGIN PRIVATE KEY----- +MIIBVQIBADANBgkqhkiG9w0BAQEFAASCAT8wggE7AgEAAkEAtz9Z9e6L1V4kt/8C +mtFqhUPJbSU+VDGbk1MsQcPBR3uJ2y0vM9e5qHRYSOBqjmg7UERRHhvKNiUn4Xz0 +KzgGFQIDAQABAkEAr+byNi+cr17FpJH4MCEiPXaKnmkH4c4U52EJtL9yg2gijBrp +Ykat3c2nWb0EGGi5aWgXxQHoi7z97/ACD4X3KQIhAPNyex6GdiBVlNPHOgInTU8a +mARKKVHIXM0SxvxXrRl7AiEAwLI66OpSqftDTv1KUfNe6+hyoh23ggzUSYiWuVT0 +Ya8CHwiO/cUU9RIt8A2B84gf2ZfuV2nPMaSuZpTPFC/K5UsCIQCsJMzx1JuilQAN +acPiMCuFTnRSFYAhozpmsqoLyTREqwIhAMLJlZTGjEB2N+sEazH5ToEczQzKqp7t +9juGNbOPhoEL +-----END PRIVATE KEY-----"; + + using RSA rsa = RSAFactory.Create(); + rsa.ImportFromPem(pem); + RSAParameters rsaParameters = rsa.ExportParameters(true); + + ImportExport.AssertKeyEquals(TestData.DiminishedDPParameters, rsaParameters); + } + + [Fact] + public static void ImportFromPem_SubjectPublicKeyInfo_Simple() + { + string pem = @" +-----BEGIN PUBLIC KEY----- +MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBALc/WfXui9VeJLf/AprRaoVDyW0lPlQx +m5NTLEHDwUd7idstLzPXuah0WEjgao5oO1BEUR4byjYlJ+F89Cs4BhUCAwEAAQ== +-----END PUBLIC KEY-----"; + + using RSA rsa = RSAFactory.Create(); + rsa.ImportFromPem(pem); + RSAParameters rsaParameters = rsa.ExportParameters(false); + + ImportExport.AssertKeyEquals(TestData.DiminishedDPParameters.ToPublic(), rsaParameters); + } + + [Fact] + public static void ImportFromPem_RSAPublicKey_Simple() + { + string pem = @" +-----BEGIN RSA PUBLIC KEY----- +MEgCQQC3P1n17ovVXiS3/wKa0WqFQ8ltJT5UMZuTUyxBw8FHe4nbLS8z17modFhI +4GqOaDtQRFEeG8o2JSfhfPQrOAYVAgMBAAE= +-----END RSA PUBLIC KEY-----"; + + using RSA rsa = RSAFactory.Create(); + rsa.ImportFromPem(pem); + RSAParameters rsaParameters = rsa.ExportParameters(false); + + ImportExport.AssertKeyEquals(TestData.DiminishedDPParameters.ToPublic(), rsaParameters); + } + + [Fact] + public static void ImportFromPem_RSAPrivateKey_PrecedingUnrelatedPem() + { + string pem = @" +-----BEGIN CERTIFICATE----- +MIICTzCCAgmgAwIBAgIJAMQtYhFJ0+5jMA0GCSqGSIb3DQEBBQUAMIGSMQswCQYD +VQQGEwJVUzETMBEGA1UECAwKV2FzaGluZ3RvbjEQMA4GA1UEBwwHUmVkbW9uZDEY +MBYGA1UECgwPTWljcm9zb2Z0IENvcnAuMSAwHgYDVQQLDBcuTkVUIEZyYW1ld29y +ayAoQ29yZUZ4KTEgMB4GA1UEAwwXUlNBIDM4NC1iaXQgQ2VydGlmaWNhdGUwHhcN +MTYwMzAyMTY1OTA0WhcNMTYwNDAxMTY1OTA0WjCBkjELMAkGA1UEBhMCVVMxEzAR +BgNVBAgMCldhc2hpbmd0b24xEDAOBgNVBAcMB1JlZG1vbmQxGDAWBgNVBAoMD01p +Y3Jvc29mdCBDb3JwLjEgMB4GA1UECwwXLk5FVCBGcmFtZXdvcmsgKENvcmVGeCkx +IDAeBgNVBAMMF1JTQSAzODQtYml0IENlcnRpZmljYXRlMEwwDQYJKoZIhvcNAQEB +BQADOwAwOAIxANrMIthuZxV1Ay4x8gbc/BksZeLVEInlES0JbyiCr9tbeM22Vy/S +9h2zkEciMuPZ9QIDAQABo1AwTjAdBgNVHQ4EFgQU5FG2Fmi86hJOCf4KnjaxOGWV +dRUwHwYDVR0jBBgwFoAU5FG2Fmi86hJOCf4KnjaxOGWVdRUwDAYDVR0TBAUwAwEB +/zANBgkqhkiG9w0BAQUFAAMxAEzDg/u8TlApCnE8qxhcbTXk2MbX+2n5PCn+MVrW +wggvPj3b2WMXsVWiPr4S1Y/nBA== +-----END CERTIFICATE----- +-----BEGIN RSA PRIVATE KEY----- +MIIBOwIBAAJBALc/WfXui9VeJLf/AprRaoVDyW0lPlQxm5NTLEHDwUd7idstLzPX +uah0WEjgao5oO1BEUR4byjYlJ+F89Cs4BhUCAwEAAQJBAK/m8jYvnK9exaSR+DAh +Ij12ip5pB+HOFOdhCbS/coNoIowa6WJGrd3Np1m9BBhouWloF8UB6Iu8/e/wAg+F +9ykCIQDzcnsehnYgVZTTxzoCJ01PGpgESilRyFzNEsb8V60ZewIhAMCyOujqUqn7 +Q079SlHzXuvocqIdt4IM1EmIlrlU9GGvAh8Ijv3FFPUSLfANgfOIH9mX7ldpzzGk +rmaUzxQvyuVLAiEArCTM8dSbopUADWnD4jArhU50UhWAIaM6ZrKqC8k0RKsCIQDC +yZWUxoxAdjfrBGsx+U6BHM0Myqqe7fY7hjWzj4aBCw== +-----END RSA PRIVATE KEY-----"; + using RSA rsa = RSAFactory.Create(); + rsa.ImportFromPem(pem); + RSAParameters rsaParameters = rsa.ExportParameters(true); + + ImportExport.AssertKeyEquals(TestData.DiminishedDPParameters, rsaParameters); + } + + [Fact] + public static void ImportFromPem_RSAPrivateKey_PrecedingMalformedPem() + { + string pem = @" +-----BEGIN CERTIFICATE----- +$$ I AM NOT A PEM +-----END CERTIFICATE----- +-----BEGIN RSA PRIVATE KEY----- +MIIBOwIBAAJBALc/WfXui9VeJLf/AprRaoVDyW0lPlQxm5NTLEHDwUd7idstLzPX +uah0WEjgao5oO1BEUR4byjYlJ+F89Cs4BhUCAwEAAQJBAK/m8jYvnK9exaSR+DAh +Ij12ip5pB+HOFOdhCbS/coNoIowa6WJGrd3Np1m9BBhouWloF8UB6Iu8/e/wAg+F +9ykCIQDzcnsehnYgVZTTxzoCJ01PGpgESilRyFzNEsb8V60ZewIhAMCyOujqUqn7 +Q079SlHzXuvocqIdt4IM1EmIlrlU9GGvAh8Ijv3FFPUSLfANgfOIH9mX7ldpzzGk +rmaUzxQvyuVLAiEArCTM8dSbopUADWnD4jArhU50UhWAIaM6ZrKqC8k0RKsCIQDC +yZWUxoxAdjfrBGsx+U6BHM0Myqqe7fY7hjWzj4aBCw== +-----END RSA PRIVATE KEY-----"; + using RSA rsa = RSAFactory.Create(); + rsa.ImportFromPem(pem); + RSAParameters rsaParameters = rsa.ExportParameters(true); + + ImportExport.AssertKeyEquals(TestData.DiminishedDPParameters, rsaParameters); + } + + [Fact] + public static void ImportFromPem_RSAPrivateKey_AmbiguousKey_RSAPrivateKey() + { + string pem = @" +-----BEGIN RSA PRIVATE KEY----- +MII= +-----END RSA PRIVATE KEY----- +-----BEGIN RSA PRIVATE KEY----- +MIIBOwIBAAJBALc/WfXui9VeJLf/AprRaoVDyW0lPlQxm5NTLEHDwUd7idstLzPX +uah0WEjgao5oO1BEUR4byjYlJ+F89Cs4BhUCAwEAAQJBAK/m8jYvnK9exaSR+DAh +Ij12ip5pB+HOFOdhCbS/coNoIowa6WJGrd3Np1m9BBhouWloF8UB6Iu8/e/wAg+F +9ykCIQDzcnsehnYgVZTTxzoCJ01PGpgESilRyFzNEsb8V60ZewIhAMCyOujqUqn7 +Q079SlHzXuvocqIdt4IM1EmIlrlU9GGvAh8Ijv3FFPUSLfANgfOIH9mX7ldpzzGk +rmaUzxQvyuVLAiEArCTM8dSbopUADWnD4jArhU50UhWAIaM6ZrKqC8k0RKsCIQDC +yZWUxoxAdjfrBGsx+U6BHM0Myqqe7fY7hjWzj4aBCw== +-----END RSA PRIVATE KEY-----"; + using RSA rsa = RSAFactory.Create(); + AssertExtensions.Throws("input", () => rsa.ImportFromPem(pem)); + } + + [Fact] + public static void ImportFromPem_RSAPrivateKey_AmbiguousKey_SubjectPublicKeyInfo() + { + string pem = @" +-----BEGIN PUBLIC KEY----- +MII= +-----END PUBLIC KEY----- +-----BEGIN RSA PRIVATE KEY----- +MIIBOwIBAAJBALc/WfXui9VeJLf/AprRaoVDyW0lPlQxm5NTLEHDwUd7idstLzPX +uah0WEjgao5oO1BEUR4byjYlJ+F89Cs4BhUCAwEAAQJBAK/m8jYvnK9exaSR+DAh +Ij12ip5pB+HOFOdhCbS/coNoIowa6WJGrd3Np1m9BBhouWloF8UB6Iu8/e/wAg+F +9ykCIQDzcnsehnYgVZTTxzoCJ01PGpgESilRyFzNEsb8V60ZewIhAMCyOujqUqn7 +Q079SlHzXuvocqIdt4IM1EmIlrlU9GGvAh8Ijv3FFPUSLfANgfOIH9mX7ldpzzGk +rmaUzxQvyuVLAiEArCTM8dSbopUADWnD4jArhU50UhWAIaM6ZrKqC8k0RKsCIQDC +yZWUxoxAdjfrBGsx+U6BHM0Myqqe7fY7hjWzj4aBCw== +-----END RSA PRIVATE KEY-----"; + using RSA rsa = RSAFactory.Create(); + AssertExtensions.Throws("input", () => rsa.ImportFromPem(pem)); + } + + [Fact] + public static void ImportFromPem_RSAPrivateKey_AmbiguousKey_RSAPublicKey() + { + string pem = @" +-----BEGIN RSA PUBLIC KEY----- +MII= +-----END RSA PUBLIC KEY----- +-----BEGIN RSA PRIVATE KEY----- +MIIBOwIBAAJBALc/WfXui9VeJLf/AprRaoVDyW0lPlQxm5NTLEHDwUd7idstLzPX +uah0WEjgao5oO1BEUR4byjYlJ+F89Cs4BhUCAwEAAQJBAK/m8jYvnK9exaSR+DAh +Ij12ip5pB+HOFOdhCbS/coNoIowa6WJGrd3Np1m9BBhouWloF8UB6Iu8/e/wAg+F +9ykCIQDzcnsehnYgVZTTxzoCJ01PGpgESilRyFzNEsb8V60ZewIhAMCyOujqUqn7 +Q079SlHzXuvocqIdt4IM1EmIlrlU9GGvAh8Ijv3FFPUSLfANgfOIH9mX7ldpzzGk +rmaUzxQvyuVLAiEArCTM8dSbopUADWnD4jArhU50UhWAIaM6ZrKqC8k0RKsCIQDC +yZWUxoxAdjfrBGsx+U6BHM0Myqqe7fY7hjWzj4aBCw== +-----END RSA PRIVATE KEY-----"; + using RSA rsa = RSAFactory.Create(); + AssertExtensions.Throws("input", () => rsa.ImportFromPem(pem)); + } + + [Fact] + public static void ImportFromPem_RSAPrivateKey_AmbiguousKey_EncryptedPkcs8() + { + string pem = @" +-----BEGIN ENCRYPTED PRIVATE KEY----- +MII= +-----END ENCRYPTED PRIVATE KEY----- +-----BEGIN RSA PRIVATE KEY----- +MIIBOwIBAAJBALc/WfXui9VeJLf/AprRaoVDyW0lPlQxm5NTLEHDwUd7idstLzPX +uah0WEjgao5oO1BEUR4byjYlJ+F89Cs4BhUCAwEAAQJBAK/m8jYvnK9exaSR+DAh +Ij12ip5pB+HOFOdhCbS/coNoIowa6WJGrd3Np1m9BBhouWloF8UB6Iu8/e/wAg+F +9ykCIQDzcnsehnYgVZTTxzoCJ01PGpgESilRyFzNEsb8V60ZewIhAMCyOujqUqn7 +Q079SlHzXuvocqIdt4IM1EmIlrlU9GGvAh8Ijv3FFPUSLfANgfOIH9mX7ldpzzGk +rmaUzxQvyuVLAiEArCTM8dSbopUADWnD4jArhU50UhWAIaM6ZrKqC8k0RKsCIQDC +yZWUxoxAdjfrBGsx+U6BHM0Myqqe7fY7hjWzj4aBCw== +-----END RSA PRIVATE KEY-----"; + using RSA rsa = RSAFactory.Create(); + AssertExtensions.Throws("input", () => rsa.ImportFromPem(pem)); + } + + [Fact] + public static void ImportFromPem_EncryptedPrivateKeyFails() + { + string pem = @" +-----BEGIN ENCRYPTED PRIVATE KEY----- +MIIBsTBLBgkqhkiG9w0BBQ0wPjApBgkqhkiG9w0BBQwwHAQIioaQaFwlfasCAggA +MAwGCCqGSIb3DQIJBQAwEQYFKw4DAgcECJLGzSuIgnSkBIIBYHofFpp5AsrkNc9w +s0uebkLBgMXbmhu+t6XQYXhnZXguT4KF4g49vIE3XwtZkXzEeSrNRIWZcPH1UWp2 +qbv2d+ub3wBpMdFDzv5Zty6e6gACWwyMRy/oX8gZqWDfDnQwm7BV21yLANEFnRuT +K3c9EmQ9IAT2MLLRUeijyg6KUL0dZ5VmXbtQdDoovuhzU20HjSyQLXNbX8NzUhWy +VMuNHs8NhiIgOuFKMoqlN42LBA1+iOA4MGR5XDXXmGyKPLCs0USbD9Dm4/Q1h7Fs +x2yC94Mej7kgAusuNZk9GafsIQbM7jZT1PLxIKyMXAxIpS9sIYbegxK774npiy8/ +LiBC1SQXJ3sJdAeUE0QPJEci937f8SteWUmF5mUqznb/0nYjvSZh/GcZ4GWEAO8j +RkMxT/C7OZVMOlb3HV3fJj7kDmOMqfc6aKEQjLdWtuYRB8CgaudldIpK4jP2+0b5 +pBORBb0= +-----END ENCRYPTED PRIVATE KEY-----"; + using RSA rsa = RSAFactory.Create(); + AssertExtensions.Throws("input", () => rsa.ImportFromPem(pem)); + } + + [Fact] + public static void ImportFromPem_Pkcs8AlgorithmMismatch_Throws() + { + string pem = @" +The below PEM is a 1024-bit DSA key. +-----BEGIN PRIVATE KEY----- +MIIBSgIBADCCASsGByqGSM44BAEwggEeAoGBAL5KGXEaazCA+k1pMcCBc/+bodFh +0P4U2QDLyDtnmytusGPaHcFp69pVdJZWMBycwJdaFQkraQNmqQsjAmBHtpqMeJpE +VLgjzve83oMAw5aysmaQC4Wy35vnBZnshvdzgbPRHZD2dWmFvWxToqBnxh74rb/H +Nkpt8JrirFOdNuyvAhUA9+LZ6XHLZZKeFhDxYl+a9lYabdsCgYACRi+pc9joLRah +A9ushrXVItFyOsq45hOB9hT37nyTEmane/YAjmoR28XyDYdF/Ql97iSVm3cY3OYT +eDr38gQ/Hk0CgW3/RFrNWdbIpfMifs80vqCUNqDggcQixEmDVZ0gwq4+wz8EVyYG +42+vM7ajN4O2VGvCA99Vl6zv69hOpAQWAhQtFFLZyKAUOQwUQh4hNw+oBgPhFw== +-----END PRIVATE KEY-----"; + using RSA rsa = RSAFactory.Create(); + Assert.Throws(() => rsa.ImportFromPem(pem)); + } + + [Fact] + public static void ImportFromEncryptedPem_Pkcs8Encrypted_Char_Simple() + { + string pem = @" +-----BEGIN ENCRYPTED PRIVATE KEY----- +MIIBsTBLBgkqhkiG9w0BBQ0wPjApBgkqhkiG9w0BBQwwHAQIcvgI1lw9LqYCAggA +MAwGCCqGSIb3DQIJBQAwEQYFKw4DAgcECFDpLREQXt5pBIIBYOKuM5ljAvCViDL+ +nTFq7A/fI9rqdL20TMdf0wy7s43oXmsw5gCStoNEaoVToFCQWYYBRU99mK8YNFA8 +1ZJT53SDS7buJ0zX9oDltf2ByXRPI4mn2Il2HZvN2hi9ir1w8M3XoSFSurN9tC8r +IOiGkVfK9Ll54knONewNiCNefFZFctRfVMbac5SwHokCkBMHukl0oPrpVuBE8kRo +p7XtjM8ILtzLVz0iLqKXiNIf6kRdouCBmCn8VIQgIvPPIHD8vheMXWjN7g69P5n4 +1YI4c/acljcofmq1BBPTwvxaETrg2NHW0XMIgAxoaVP8lIIGlNk1glWTYpuMd69L +AWvBUt33Sozc+dF0l7NGLAWL2tqkkpyDQuKn6UgYz/vxkFeQAVfSuaJVR+fUlHg0 +N4lD7/hJq7b+yYPhlN3Fvvt8M9MtRg1TLAve67CA2v4TITHB06M/ELe3y42bZuLW +CA7ffFk= +-----END ENCRYPTED PRIVATE KEY-----"; + + using RSA rsa = RSAFactory.Create(); + rsa.ImportFromEncryptedPem(pem, "test"); + RSAParameters rsaParameters = rsa.ExportParameters(true); + + ImportExport.AssertKeyEquals(TestData.DiminishedDPParameters, rsaParameters); + } + + [Fact] + public static void ImportFromEncryptedPem_Pkcs8Encrypted_Byte_Simple() + { + string pem = @" +-----BEGIN ENCRYPTED PRIVATE KEY----- +MIIBvTBXBgkqhkiG9w0BBQ0wSjApBgkqhkiG9w0BBQwwHAQIciLWmWb33X0CAggA +MAwGCCqGSIb3DQIJBQAwHQYJYIZIAWUDBAECBBBVEmHhJdbi+HKzPttNjXm4BIIB +YFejknurbot2VDXwc671A0mfA0cw/u7K44gsYXcZwAARC8j6f3lSzB0tN2kMEx/L +TB+kpMBbfAoIPKoEc9Y4w9m3NXkQYrLRONh9AFiAnOjULHwkstQfN2ofFlolDfbH +hAE6ga6aQJTQ8rDKTL4QkCg+s+qWlicPqs5ikSQfUz2Qiy8FKe7zZlJ0OWpT+zk7 +EYRrUSKQcEAjfNS7anlMps2ZXRc1LkLJNHZSl6h2BuFPfIKEV9REpy3Y7sH7vNZZ +PWPa9/xM4CX/c/ommy6LqvZikUuUGc56/Hbz65SwG3voivIhOTmM28LiA6z0YXmY +E+nr7hyinl51raM1RSHojJB22oOW+GwV7GgWYIjUgIEMDOhN10FcGNfTeC65PCXx +5QSEe7EKVF0aHXBYB5SzMGVuxR/BqydDa26jlhVzO3LNvy9FYuqLKUslCrBCmPrt +raZNyk8KAsLs+FJq9T2tda0= +-----END ENCRYPTED PRIVATE KEY-----"; + + using RSA rsa = RSAFactory.Create(); + rsa.ImportFromEncryptedPem(pem, Encoding.UTF8.GetBytes("test")); + RSAParameters rsaParameters = rsa.ExportParameters(true); + + ImportExport.AssertKeyEquals(TestData.DiminishedDPParameters, rsaParameters); + } + + [Fact] + public static void ImportFromEncryptedPem_Pkcs8Encrypted_AmbiguousPem() + { + string pem = @" +-----BEGIN ENCRYPTED PRIVATE KEY----- +MIIBvTBXBgkqhkiG9w0BBQ0wSjApBgkqhkiG9w0BBQwwHAQIciLWmWb33X0CAggA +MAwGCCqGSIb3DQIJBQAwHQYJYIZIAWUDBAECBBBVEmHhJdbi+HKzPttNjXm4BIIB +YFejknurbot2VDXwc671A0mfA0cw/u7K44gsYXcZwAARC8j6f3lSzB0tN2kMEx/L +TB+kpMBbfAoIPKoEc9Y4w9m3NXkQYrLRONh9AFiAnOjULHwkstQfN2ofFlolDfbH +hAE6ga6aQJTQ8rDKTL4QkCg+s+qWlicPqs5ikSQfUz2Qiy8FKe7zZlJ0OWpT+zk7 +EYRrUSKQcEAjfNS7anlMps2ZXRc1LkLJNHZSl6h2BuFPfIKEV9REpy3Y7sH7vNZZ +PWPa9/xM4CX/c/ommy6LqvZikUuUGc56/Hbz65SwG3voivIhOTmM28LiA6z0YXmY +E+nr7hyinl51raM1RSHojJB22oOW+GwV7GgWYIjUgIEMDOhN10FcGNfTeC65PCXx +5QSEe7EKVF0aHXBYB5SzMGVuxR/BqydDa26jlhVzO3LNvy9FYuqLKUslCrBCmPrt +raZNyk8KAsLs+FJq9T2tda0= +-----END ENCRYPTED PRIVATE KEY----- +-----BEGIN ENCRYPTED PRIVATE KEY----- +MIIBsTBLBgkqhkiG9w0BBQ0wPjApBgkqhkiG9w0BBQwwHAQIcvgI1lw9LqYCAggA +MAwGCCqGSIb3DQIJBQAwEQYFKw4DAgcECFDpLREQXt5pBIIBYOKuM5ljAvCViDL+ +nTFq7A/fI9rqdL20TMdf0wy7s43oXmsw5gCStoNEaoVToFCQWYYBRU99mK8YNFA8 +1ZJT53SDS7buJ0zX9oDltf2ByXRPI4mn2Il2HZvN2hi9ir1w8M3XoSFSurN9tC8r +IOiGkVfK9Ll54knONewNiCNefFZFctRfVMbac5SwHokCkBMHukl0oPrpVuBE8kRo +p7XtjM8ILtzLVz0iLqKXiNIf6kRdouCBmCn8VIQgIvPPIHD8vheMXWjN7g69P5n4 +1YI4c/acljcofmq1BBPTwvxaETrg2NHW0XMIgAxoaVP8lIIGlNk1glWTYpuMd69L +AWvBUt33Sozc+dF0l7NGLAWL2tqkkpyDQuKn6UgYz/vxkFeQAVfSuaJVR+fUlHg0 +N4lD7/hJq7b+yYPhlN3Fvvt8M9MtRg1TLAve67CA2v4TITHB06M/ELe3y42bZuLW +CA7ffFk= +-----END ENCRYPTED PRIVATE KEY-----"; + + using RSA rsa = RSAFactory.Create(); + byte[] passwordBytes = Encoding.UTF8.GetBytes("test"); + AssertExtensions.Throws("input", () => + rsa.ImportFromEncryptedPem(pem, passwordBytes)); + } + + [Fact] + public static void ImportFromEncryptedPem_Pkcs8Encrypted_Byte_NoPem() + { + string pem = "these aren't the PEMs we're looking for."; + using RSA rsa = RSAFactory.Create(); + byte[] passwordBytes = Encoding.UTF8.GetBytes("test"); + AssertExtensions.Throws("input", () => + rsa.ImportFromEncryptedPem(pem, passwordBytes)); + } + + [Fact] + public static void ImportFromEncryptedPem_Pkcs8Encrypted_Char_NoPem() + { + string pem = "go about your business"; + using RSA rsa = RSAFactory.Create(); + string password = "test"; + AssertExtensions.Throws("input", () => + rsa.ImportFromEncryptedPem(pem, password)); + } + + private static RSAParameters ToPublic(this RSAParameters rsaParams) + { + return new RSAParameters + { + Exponent = rsaParams.Exponent, + Modulus = rsaParams.Modulus + }; + } + } +} diff --git a/src/libraries/System.Security.Cryptography.Algorithms/ref/System.Security.Cryptography.Algorithms.cs b/src/libraries/System.Security.Cryptography.Algorithms/ref/System.Security.Cryptography.Algorithms.cs index fe1cafe80e816..68f153b882db9 100644 --- a/src/libraries/System.Security.Cryptography.Algorithms/ref/System.Security.Cryptography.Algorithms.cs +++ b/src/libraries/System.Security.Cryptography.Algorithms/ref/System.Security.Cryptography.Algorithms.cs @@ -135,6 +135,7 @@ public override void FromXmlString(string xmlString) { } protected virtual byte[] HashData(System.IO.Stream data, System.Security.Cryptography.HashAlgorithmName hashAlgorithm) { throw null; } public override void ImportEncryptedPkcs8PrivateKey(System.ReadOnlySpan passwordBytes, System.ReadOnlySpan source, out int bytesRead) { throw null; } public override void ImportEncryptedPkcs8PrivateKey(System.ReadOnlySpan password, System.ReadOnlySpan source, out int bytesRead) { throw null; } + public override void ImportFromPem(System.ReadOnlySpan input) { } public abstract void ImportParameters(System.Security.Cryptography.DSAParameters parameters); public override void ImportPkcs8PrivateKey(System.ReadOnlySpan source, out int bytesRead) { throw null; } public override void ImportSubjectPublicKeyInfo(System.ReadOnlySpan source, out int bytesRead) { throw null; } @@ -283,6 +284,7 @@ public virtual void GenerateKey(System.Security.Cryptography.ECCurve curve) { } public virtual void ImportECPrivateKey(System.ReadOnlySpan source, out int bytesRead) { throw null; } public override void ImportEncryptedPkcs8PrivateKey(System.ReadOnlySpan passwordBytes, System.ReadOnlySpan source, out int bytesRead) { throw null; } public override void ImportEncryptedPkcs8PrivateKey(System.ReadOnlySpan password, System.ReadOnlySpan source, out int bytesRead) { throw null; } + public override void ImportFromPem(System.ReadOnlySpan input) { } public virtual void ImportParameters(System.Security.Cryptography.ECParameters parameters) { } public override void ImportPkcs8PrivateKey(System.ReadOnlySpan source, out int bytesRead) { throw null; } public override void ImportSubjectPublicKeyInfo(System.ReadOnlySpan source, out int bytesRead) { throw null; } @@ -324,6 +326,7 @@ public virtual void GenerateKey(System.Security.Cryptography.ECCurve curve) { } public virtual void ImportECPrivateKey(System.ReadOnlySpan source, out int bytesRead) { throw null; } public override void ImportEncryptedPkcs8PrivateKey(System.ReadOnlySpan passwordBytes, System.ReadOnlySpan source, out int bytesRead) { throw null; } public override void ImportEncryptedPkcs8PrivateKey(System.ReadOnlySpan password, System.ReadOnlySpan source, out int bytesRead) { throw null; } + public override void ImportFromPem(System.ReadOnlySpan input) { } public virtual void ImportParameters(System.Security.Cryptography.ECParameters parameters) { } public override void ImportPkcs8PrivateKey(System.ReadOnlySpan source, out int bytesRead) { throw null; } public override void ImportSubjectPublicKeyInfo(System.ReadOnlySpan source, out int bytesRead) { throw null; } @@ -573,6 +576,9 @@ public override void FromXmlString(string xmlString) { } protected virtual byte[] HashData(System.IO.Stream data, System.Security.Cryptography.HashAlgorithmName hashAlgorithm) { throw null; } public override void ImportEncryptedPkcs8PrivateKey(System.ReadOnlySpan passwordBytes, System.ReadOnlySpan source, out int bytesRead) { throw null; } public override void ImportEncryptedPkcs8PrivateKey(System.ReadOnlySpan password, System.ReadOnlySpan source, out int bytesRead) { throw null; } + public override void ImportFromEncryptedPem(System.ReadOnlySpan input, System.ReadOnlySpan passwordBytes) { } + public override void ImportFromEncryptedPem(System.ReadOnlySpan input, System.ReadOnlySpan password) { } + public override void ImportFromPem(System.ReadOnlySpan input) { } public abstract void ImportParameters(System.Security.Cryptography.RSAParameters parameters); public override void ImportPkcs8PrivateKey(System.ReadOnlySpan source, out int bytesRead) { throw null; } public virtual void ImportRSAPrivateKey(System.ReadOnlySpan source, out int bytesRead) { throw null; } diff --git a/src/libraries/System.Security.Cryptography.Algorithms/src/Resources/Strings.resx b/src/libraries/System.Security.Cryptography.Algorithms/src/Resources/Strings.resx index 878856832fbab..cadd55c13b545 100644 --- a/src/libraries/System.Security.Cryptography.Algorithms/src/Resources/Strings.resx +++ b/src/libraries/System.Security.Cryptography.Algorithms/src/Resources/Strings.resx @@ -81,6 +81,15 @@ Buffer cannot be null. + + A supported key was not found. + + + Multiple supported keys were found. + + + An encrypted key was found, but attempted to import it without a password. + Error occurred during a cryptographic operation. @@ -320,7 +329,7 @@ Method not supported. - + Method not supported. Derived class must override. diff --git a/src/libraries/System.Security.Cryptography.Algorithms/src/System.Security.Cryptography.Algorithms.csproj b/src/libraries/System.Security.Cryptography.Algorithms/src/System.Security.Cryptography.Algorithms.csproj index 680eedda4281d..4ed8e9a17b15d 100644 --- a/src/libraries/System.Security.Cryptography.Algorithms/src/System.Security.Cryptography.Algorithms.csproj +++ b/src/libraries/System.Security.Cryptography.Algorithms/src/System.Security.Cryptography.Algorithms.csproj @@ -98,6 +98,9 @@ Internal\Cryptography\HashProvider.cs + + Common\Internal\Cryptography\PemKeyImportHelpers.cs + Internal\Cryptography\UniversalCryptoTransform.cs @@ -731,4 +734,4 @@ - \ No newline at end of file + diff --git a/src/libraries/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/DSA.cs b/src/libraries/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/DSA.cs index 69b260cc71550..5c145a03f7349 100644 --- a/src/libraries/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/DSA.cs +++ b/src/libraries/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/DSA.cs @@ -1125,5 +1125,33 @@ public int GetMaxSignatureSize(DSASignatureFormat signatureFormat) throw new ArgumentOutOfRangeException(nameof(signatureFormat)); } } + + public override void ImportFromPem(ReadOnlySpan input) + { + PemKeyImportHelpers.ImportPem(input, label => { + if (label.SequenceEqual("PRIVATE KEY")) + { + return ImportPkcs8PrivateKey; + } + else if (label.SequenceEqual("PUBLIC KEY")) + { + return ImportSubjectPublicKeyInfo; + } + else + { + return null; + } + }); + } + + public override void ImportFromEncryptedPem(ReadOnlySpan input, ReadOnlySpan password) + { + PemKeyImportHelpers.ImportEncryptedPem(input, password, ImportEncryptedPkcs8PrivateKey); + } + + public override void ImportFromEncryptedPem(ReadOnlySpan input, ReadOnlySpan passwordBytes) + { + PemKeyImportHelpers.ImportEncryptedPem(input, passwordBytes, ImportEncryptedPkcs8PrivateKey); + } } } diff --git a/src/libraries/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/ECDiffieHellman.cs b/src/libraries/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/ECDiffieHellman.cs index 6109ae344db20..28a9eef35850a 100644 --- a/src/libraries/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/ECDiffieHellman.cs +++ b/src/libraries/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/ECDiffieHellman.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +using Internal.Cryptography; using System.Security.Cryptography.Asn1; namespace System.Security.Cryptography @@ -433,5 +434,37 @@ public virtual unsafe bool TryExportECPrivateKey(Span destination, out int } } } + + public override void ImportFromPem(ReadOnlySpan input) + { + PemKeyImportHelpers.ImportPem(input, label => { + if (label.SequenceEqual("PRIVATE KEY")) + { + return ImportPkcs8PrivateKey; + } + else if (label.SequenceEqual("PUBLIC KEY")) + { + return ImportSubjectPublicKeyInfo; + } + else if (label.SequenceEqual("EC PRIVATE KEY")) + { + return ImportECPrivateKey; + } + else + { + return null; + } + }); + } + + public override void ImportFromEncryptedPem(ReadOnlySpan input, ReadOnlySpan password) + { + PemKeyImportHelpers.ImportEncryptedPem(input, password, ImportEncryptedPkcs8PrivateKey); + } + + public override void ImportFromEncryptedPem(ReadOnlySpan input, ReadOnlySpan passwordBytes) + { + PemKeyImportHelpers.ImportEncryptedPem(input, passwordBytes, ImportEncryptedPkcs8PrivateKey); + } } } diff --git a/src/libraries/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/ECDsa.cs b/src/libraries/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/ECDsa.cs index 01d1109e6edd3..d10cd0c674c2a 100644 --- a/src/libraries/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/ECDsa.cs +++ b/src/libraries/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/ECDsa.cs @@ -1298,5 +1298,37 @@ public int GetMaxSignatureSize(DSASignatureFormat signatureFormat) throw new ArgumentOutOfRangeException(nameof(signatureFormat)); } } + + public override void ImportFromPem(ReadOnlySpan input) + { + PemKeyImportHelpers.ImportPem(input, label => { + if (label.SequenceEqual("PRIVATE KEY")) + { + return ImportPkcs8PrivateKey; + } + else if (label.SequenceEqual("PUBLIC KEY")) + { + return ImportSubjectPublicKeyInfo; + } + else if (label.SequenceEqual("EC PRIVATE KEY")) + { + return ImportECPrivateKey; + } + else + { + return null; + } + }); + } + + public override void ImportFromEncryptedPem(ReadOnlySpan input, ReadOnlySpan password) + { + PemKeyImportHelpers.ImportEncryptedPem(input, password, ImportEncryptedPkcs8PrivateKey); + } + + public override void ImportFromEncryptedPem(ReadOnlySpan input, ReadOnlySpan passwordBytes) + { + PemKeyImportHelpers.ImportEncryptedPem(input, passwordBytes, ImportEncryptedPkcs8PrivateKey); + } } } diff --git a/src/libraries/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/RSA.cs b/src/libraries/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/RSA.cs index 0d7a6c6bd41b7..9cf69cea0f75f 100644 --- a/src/libraries/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/RSA.cs +++ b/src/libraries/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/RSA.cs @@ -625,6 +625,42 @@ public override unsafe void ImportEncryptedPkcs8PrivateKey( bytesRead = localRead; } + public override void ImportFromPem(ReadOnlySpan input) + { + PemKeyImportHelpers.ImportPem(input, label => { + if (label.SequenceEqual("RSA PRIVATE KEY")) + { + return ImportRSAPrivateKey; + } + else if (label.SequenceEqual("PRIVATE KEY")) + { + return ImportPkcs8PrivateKey; + } + else if (label.SequenceEqual("RSA PUBLIC KEY")) + { + return ImportRSAPublicKey; + } + else if (label.SequenceEqual("PUBLIC KEY")) + { + return ImportSubjectPublicKeyInfo; + } + else + { + return null; + } + }); + } + + public override void ImportFromEncryptedPem(ReadOnlySpan input, ReadOnlySpan password) + { + PemKeyImportHelpers.ImportEncryptedPem(input, password, ImportEncryptedPkcs8PrivateKey); + } + + public override void ImportFromEncryptedPem(ReadOnlySpan input, ReadOnlySpan passwordBytes) + { + PemKeyImportHelpers.ImportEncryptedPem(input, passwordBytes, ImportEncryptedPkcs8PrivateKey); + } + private static void ClearPrivateParameters(in RSAParameters rsaParameters) { CryptographicOperations.ZeroMemory(rsaParameters.D); diff --git a/src/libraries/System.Security.Cryptography.Algorithms/tests/System.Security.Cryptography.Algorithms.Tests.csproj b/src/libraries/System.Security.Cryptography.Algorithms/tests/System.Security.Cryptography.Algorithms.Tests.csproj index aa25b8f7bab7d..d08dc787b604b 100644 --- a/src/libraries/System.Security.Cryptography.Algorithms/tests/System.Security.Cryptography.Algorithms.Tests.csproj +++ b/src/libraries/System.Security.Cryptography.Algorithms/tests/System.Security.Cryptography.Algorithms.Tests.csproj @@ -141,12 +141,21 @@ CommonTest\System\Security\Cryptography\AlgorithmImplementations\DSA\DSAKeyFileTests.cs + + CommonTest\System\Security\Cryptography\AlgorithmImplementations\DSA\DSAKeyPemTests.cs + CommonTest\System\Security\Cryptography\AlgorithmImplementations\EC\ECKeyFileTests.cs + + CommonTest\System\Security\Cryptography\AlgorithmImplementations\EC\ECKeyPemTests.cs + CommonTest\System\Security\Cryptography\AlgorithmImplementations\ECDiffieHellman\ECDhKeyFileTests.cs + + CommonTest\System\Security\Cryptography\AlgorithmImplementations\ECDiffieHellman\ECDiffieHellmanKeyPemTests.cs + CommonTest\System\Security\Cryptography\AlgorithmImplementations\ECDiffieHellman\ECDiffieHellmanFactory.cs @@ -174,9 +183,15 @@ CommonTest\System\Security\Cryptography\AlgorithmImplementations\ECDsa\ECDsaKeyFileTests.cs + + CommonTest\System\Security\Cryptography\AlgorithmImplementations\ECDsa\ECDsaKeyPemTests.cs + CommonTest\System\Security\Cryptography\AlgorithmImplementations\RSA\RSAKeyFileTests.cs + + CommonTest\System\Security\Cryptography\AlgorithmImplementations\RSA\RSAKeyPemTests.cs + @@ -280,4 +295,4 @@ - \ No newline at end of file + diff --git a/src/libraries/System.Security.Cryptography.Cng/tests/System.Security.Cryptography.Cng.Tests.csproj b/src/libraries/System.Security.Cryptography.Cng/tests/System.Security.Cryptography.Cng.Tests.csproj index b78e98c57e348..4cefd7d70786c 100644 --- a/src/libraries/System.Security.Cryptography.Cng/tests/System.Security.Cryptography.Cng.Tests.csproj +++ b/src/libraries/System.Security.Cryptography.Cng/tests/System.Security.Cryptography.Cng.Tests.csproj @@ -117,6 +117,9 @@ CommonTest\System\Security\Cryptography\AlgorithmImplementations\DSA\DSAKeyFileTests.cs + + CommonTest\System\Security\Cryptography\AlgorithmImplementations\DSA\DSAKeyPemTests.cs + CommonTest\System\Security\Cryptography\AlgorithmImplementations\DSA\DSASignatureFormatter.cs @@ -135,15 +138,24 @@ CommonTest\System\Security\Cryptography\AlgorithmImplementations\EC\ECKeyFileTests.cs + + CommonTest\System\Security\Cryptography\AlgorithmImplementations\EC\ECKeyPemTests.cs + CommonTest\System\Security\Cryptography\AlgorithmImplementations\ECDiffieHellman\ECDhKeyFileTests.cs + + CommonTest\System\Security\Cryptography\AlgorithmImplementations\ECDiffieHellman\ECDiffieHellmanKeyPemTests.cs + CommonTest\System\Security\Cryptography\AlgorithmImplementations\ECDsa\ECDsaTests.netcoreapp.cs CommonTest\System\Security\Cryptography\AlgorithmImplementations\ECDsa\ECDsaKeyFileTests.cs + + CommonTest\System\Security\Cryptography\AlgorithmImplementations\ECDsa\ECDsaKeyPemTests.cs + CommonTest\System\Security\Cryptography\AlgorithmImplementations\ECDsa\ECDsaSignatureFormatTests.cs @@ -159,6 +171,9 @@ CommonTest\System\Security\Cryptography\AlgorithmImplementations\RSA\RSAKeyFileTests.cs + + CommonTest\System\Security\Cryptography\AlgorithmImplementations\RSA\RSAKeyPemTests.cs + CommonTest\System\Security\Cryptography\AlgorithmImplementations\RSA\RSASignatureFormatter.cs diff --git a/src/libraries/System.Security.Cryptography.Csp/tests/System.Security.Cryptography.Csp.Tests.csproj b/src/libraries/System.Security.Cryptography.Csp/tests/System.Security.Cryptography.Csp.Tests.csproj index df8ab9e89365c..887d4a3e1f205 100644 --- a/src/libraries/System.Security.Cryptography.Csp/tests/System.Security.Cryptography.Csp.Tests.csproj +++ b/src/libraries/System.Security.Cryptography.Csp/tests/System.Security.Cryptography.Csp.Tests.csproj @@ -75,6 +75,9 @@ CommonTest\System\Security\Cryptography\AlgorithmImplementations\DSA\DSAKeyFileTests.cs + + CommonTest\System\Security\Cryptography\AlgorithmImplementations\DSA\DSAKeyPemTests.cs + CommonTest\System\Security\Cryptography\AlgorithmImplementations\DSA\DSAKeyGeneration.cs @@ -117,6 +120,9 @@ CommonTest\System\Security\Cryptography\AlgorithmImplementations\RSA\RSAKeyFileTests.cs + + CommonTest\System\Security\Cryptography\AlgorithmImplementations\RSA\RSAKeyPemTests.cs + CommonTest\System\Security\Cryptography\AlgorithmImplementations\RSA\SignVerify.netcoreapp.cs diff --git a/src/libraries/System.Security.Cryptography.OpenSsl/tests/System.Security.Cryptography.OpenSsl.Tests.csproj b/src/libraries/System.Security.Cryptography.OpenSsl/tests/System.Security.Cryptography.OpenSsl.Tests.csproj index 147d63cbfdd74..d7b4ef6f1fe96 100644 --- a/src/libraries/System.Security.Cryptography.OpenSsl/tests/System.Security.Cryptography.OpenSsl.Tests.csproj +++ b/src/libraries/System.Security.Cryptography.OpenSsl/tests/System.Security.Cryptography.OpenSsl.Tests.csproj @@ -140,15 +140,27 @@ CommonTest\System\Security\Cryptography\AlgorithmImplementations\DSA\DSAKeyFileTests.cs + + CommonTest\System\Security\Cryptography\AlgorithmImplementations\DSA\DSAKeyPemTests.cs + CommonTest\System\Security\Cryptography\AlgorithmImplementations\EC\ECKeyFileTests.cs + + CommonTest\System\Security\Cryptography\AlgorithmImplementations\EC\ECKeyPemTests.cs + CommonTest\System\Security\Cryptography\AlgorithmImplementations\ECDiffieHellman\ECDhKeyFileTests.cs + + CommonTest\System\Security\Cryptography\AlgorithmImplementations\ECDiffieHellman\ECDiffieHellmanKeyPemTests.cs + CommonTest\System\Security\Cryptography\AlgorithmImplementations\ECDsa\ECDsaKeyFileTests.cs + + CommonTest\System\Security\Cryptography\AlgorithmImplementations\ECDsa\ECDsaKeyPemTests.cs + CommonTest\System\Security\Cryptography\AlgorithmImplementations\ECDsa\ECDsaTests.netcoreapp.cs @@ -158,9 +170,12 @@ CommonTest\System\Security\Cryptography\AlgorithmImplementations\RSA\RSAKeyFileTests.cs + + CommonTest\System\Security\Cryptography\AlgorithmImplementations\RSA\RSAKeyPemTests.cs + CommonTest\System\Security\Cryptography\AlgorithmImplementations\RSA\SignVerify.netcoreapp.cs - \ No newline at end of file + diff --git a/src/libraries/System.Security.Cryptography.Primitives/ref/System.Security.Cryptography.Primitives.cs b/src/libraries/System.Security.Cryptography.Primitives/ref/System.Security.Cryptography.Primitives.cs index 3530fac13129f..92787b5a35ff6 100644 --- a/src/libraries/System.Security.Cryptography.Primitives/ref/System.Security.Cryptography.Primitives.cs +++ b/src/libraries/System.Security.Cryptography.Primitives/ref/System.Security.Cryptography.Primitives.cs @@ -28,6 +28,9 @@ protected virtual void Dispose(bool disposing) { } public virtual void FromXmlString(string xmlString) { } public virtual void ImportEncryptedPkcs8PrivateKey(System.ReadOnlySpan passwordBytes, System.ReadOnlySpan source, out int bytesRead) { throw null; } public virtual void ImportEncryptedPkcs8PrivateKey(System.ReadOnlySpan password, System.ReadOnlySpan source, out int bytesRead) { throw null; } + public virtual void ImportFromEncryptedPem(System.ReadOnlySpan input, System.ReadOnlySpan passwordBytes) { } + public virtual void ImportFromEncryptedPem(System.ReadOnlySpan input, System.ReadOnlySpan password) { } + public virtual void ImportFromPem(System.ReadOnlySpan input) { } public virtual void ImportPkcs8PrivateKey(System.ReadOnlySpan source, out int bytesRead) { throw null; } public virtual void ImportSubjectPublicKeyInfo(System.ReadOnlySpan source, out int bytesRead) { throw null; } public virtual string ToXmlString(bool includePrivateParameters) { throw null; } diff --git a/src/libraries/System.Security.Cryptography.Primitives/src/System/Security/Cryptography/AsymmetricAlgorithm.cs b/src/libraries/System.Security.Cryptography.Primitives/src/System/Security/Cryptography/AsymmetricAlgorithm.cs index 0b2941def5b32..bf39f81135673 100644 --- a/src/libraries/System.Security.Cryptography.Primitives/src/System/Security/Cryptography/AsymmetricAlgorithm.cs +++ b/src/libraries/System.Security.Cryptography.Primitives/src/System/Security/Cryptography/AsymmetricAlgorithm.cs @@ -164,6 +164,15 @@ public virtual bool TryExportPkcs8PrivateKey(Span destination, out int byt public virtual bool TryExportSubjectPublicKeyInfo(Span destination, out int bytesWritten) => throw new NotImplementedException(SR.NotSupported_SubclassOverride); + public virtual void ImportFromEncryptedPem(ReadOnlySpan input, ReadOnlySpan password) => + throw new NotImplementedException(SR.NotSupported_SubclassOverride); + + public virtual void ImportFromEncryptedPem(ReadOnlySpan input, ReadOnlySpan passwordBytes) => + throw new NotImplementedException(SR.NotSupported_SubclassOverride); + + public virtual void ImportFromPem(ReadOnlySpan input) => + throw new NotImplementedException(SR.NotSupported_SubclassOverride); + private delegate bool TryExportPbe( ReadOnlySpan password, PbeParameters pbeParameters, From cc719234952cdf09d5d71a051895979f06f98f91 Mon Sep 17 00:00:00 2001 From: Kevin Jones Date: Wed, 25 Mar 2020 12:05:31 -0400 Subject: [PATCH 02/18] Documentation. --- .../src/System/Security/Cryptography/DSA.cs | 135 +++++++++++++++++ .../Security/Cryptography/ECDiffieHellman.cs | 136 +++++++++++++++++ .../src/System/Security/Cryptography/ECDsa.cs | 136 +++++++++++++++++ .../src/System/Security/Cryptography/RSA.cs | 137 ++++++++++++++++++ .../Cryptography/AsymmetricAlgorithm.cs | 27 ++++ 5 files changed, 571 insertions(+) diff --git a/src/libraries/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/DSA.cs b/src/libraries/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/DSA.cs index 5c145a03f7349..a471e1ce4c913 100644 --- a/src/libraries/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/DSA.cs +++ b/src/libraries/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/DSA.cs @@ -1126,6 +1126,35 @@ public int GetMaxSignatureSize(DSASignatureFormat signatureFormat) } } + /// + /// Imports an RFC 7468 PEM-encoded key, replacing the keys for this object. + /// + /// The PEM text of the key to import. + /// + /// does not contain a PEM-encoded key with a recognized label. + /// + /// -or- + /// + /// contains multiple PEM-encoded keys with a recognized label. + /// + /// -or- + /// + /// contains an encrypted PEM-encoded key. + /// + /// + /// + /// Unsupported or malformed PEM-encoded objects will be ignored. If multiple supported PEM labels + /// are found, an exception is raised to prevent importing a key when + /// the key is ambiguous. + /// + /// + /// This method supports the following PEM labels: + /// + /// PUBLIC KEY + /// PRIVATE KEY + /// + /// + /// public override void ImportFromPem(ReadOnlySpan input) { PemKeyImportHelpers.ImportPem(input, label => { @@ -1144,11 +1173,117 @@ public override void ImportFromPem(ReadOnlySpan input) }); } + /// + /// Imports an encrypted RFC 7468 PEM-encoded private key, replacing the keys for this object. + /// + /// The PEM text of the encrypted key to import. + /// + /// The password to use for decrypting the key material. + /// + /// + /// does not contain a PEM-encoded key with a recognized label. + /// + /// -or- + /// + /// contains multiple PEM-encoded keys with a recognized label. + /// + /// + /// The password is incorrect. + /// + /// -or- + /// + /// The base-64 decoded contents of the PEM text from + /// do not represent an ASN.1-BER-encoded PKCS#8 EncryptedPrivateKeyInfo structure. + /// + /// -or- + /// + /// The base-64 decoded contents of the PEM text from + /// indicate the key is for an algorithm other than the algorithm + /// represented by this instance. + /// + /// -or- + /// + /// The base-64 decoded contents of the PEM text from + /// represent the key in a format that is not supported. + /// + /// -or- + /// + /// The algorithm-specific key import failed. + /// + /// + /// + /// When the base-64 decoded contents of indicate an algorithm that uses PBKDF1 + /// (Password-Based Key Derivation Function 1) or PBKDF2 (Password-Based Key Derivation Function 2), + /// the password is converted to bytes via the UTF-8 encoding. This method + /// only supports the binary (BER/CER/DER) encoding of EncryptedPrivateKeyInfo. + /// + /// + /// Unsupported or malformed PEM-encoded objects will be ignored. If multiple supported PEM labels + /// are found, an exception is raised to prevent importing a key when + /// the key is ambiguous. + /// + /// This method supports the ENCRYPTED PRIVATE KEY PEM label. + /// public override void ImportFromEncryptedPem(ReadOnlySpan input, ReadOnlySpan password) { PemKeyImportHelpers.ImportEncryptedPem(input, password, ImportEncryptedPkcs8PrivateKey); } + /// + /// Imports an encrypted RFC 7468 PEM-encoded private key, replacing the keys for this object. + /// + /// The PEM text of the encrypted key to import. + /// + /// The bytes to use as a password when decrypting the key material. + /// + /// + /// does not contain a PEM-encoded key with a recognized label. + /// + /// -or- + /// + /// contains multiple PEM-encoded keys with a recognized label. + /// + /// + /// The password is incorrect. + /// + /// -or- + /// + /// The base-64 decoded contents of the PEM text from + /// do not represent an ASN.1-BER-encoded PKCS#8 EncryptedPrivateKeyInfo structure. + /// + /// -or- + /// + /// The base-64 decoded contents of the PEM text from + /// indicate the key is for an algorithm other than the algorithm + /// represented by this instance. + /// + /// -or- + /// + /// The base-64 decoded contents of the PEM text from + /// represent the key in a format that is not supported. + /// + /// -or- + /// + /// The algorithm-specific key import failed. + /// + /// + /// + /// The password bytes are passed directly into the Key Derivation Function (KDF) + /// used by the algorithm indicated by pbeParameters. This enables compatibility + /// with other systems which use a text encoding other than UTF-8 when processing + /// passwords with PBKDF2 (Password-Based Key Derivation Function 2). + /// + /// + /// The base-64 decoded contents of the PEM text only supports + /// the binary (BER/CER/DER) encoding of EncryptedPrivateKeyInfo. + /// + /// + /// Unsupported or malformed PEM-encoded objects will be ignored. If multiple supported PEM labels + /// are found, an exception is raised to prevent importing a key when + /// the key is ambiguous. + /// + /// This method supports the ENCRYPTED PRIVATE KEY PEM label. + /// public override void ImportFromEncryptedPem(ReadOnlySpan input, ReadOnlySpan passwordBytes) { PemKeyImportHelpers.ImportEncryptedPem(input, passwordBytes, ImportEncryptedPkcs8PrivateKey); diff --git a/src/libraries/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/ECDiffieHellman.cs b/src/libraries/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/ECDiffieHellman.cs index 28a9eef35850a..d0d64fc660030 100644 --- a/src/libraries/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/ECDiffieHellman.cs +++ b/src/libraries/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/ECDiffieHellman.cs @@ -435,6 +435,36 @@ public virtual unsafe bool TryExportECPrivateKey(Span destination, out int } } + /// + /// Imports an RFC 7468 PEM-encoded key, replacing the keys for this object. + /// + /// The PEM text of the key to import. + /// + /// does not contain a PEM-encoded key with a recognized label. + /// + /// -or- + /// + /// contains multiple PEM-encoded keys with a recognized label. + /// + /// -or- + /// + /// contains an encrypted PEM-encoded key. + /// + /// + /// + /// Unsupported or malformed PEM-encoded objects will be ignored. If multiple supported PEM labels + /// are found, an exception is raised to prevent importing a key when + /// the key is ambiguous. + /// + /// + /// This method supports the following PEM labels: + /// + /// PUBLIC KEY + /// PRIVATE KEY + /// EC PRIVATE KEY + /// + /// + /// public override void ImportFromPem(ReadOnlySpan input) { PemKeyImportHelpers.ImportPem(input, label => { @@ -457,11 +487,117 @@ public override void ImportFromPem(ReadOnlySpan input) }); } + /// + /// Imports an encrypted RFC 7468 PEM-encoded private key, replacing the keys for this object. + /// + /// The PEM text of the encrypted key to import. + /// + /// The password to use for decrypting the key material. + /// + /// + /// does not contain a PEM-encoded key with a recognized label. + /// + /// -or- + /// + /// contains multiple PEM-encoded keys with a recognized label. + /// + /// + /// The password is incorrect. + /// + /// -or- + /// + /// The base-64 decoded contents of the PEM text from + /// do not represent an ASN.1-BER-encoded PKCS#8 EncryptedPrivateKeyInfo structure. + /// + /// -or- + /// + /// The base-64 decoded contents of the PEM text from + /// indicate the key is for an algorithm other than the algorithm + /// represented by this instance. + /// + /// -or- + /// + /// The base-64 decoded contents of the PEM text from + /// represent the key in a format that is not supported. + /// + /// -or- + /// + /// The algorithm-specific key import failed. + /// + /// + /// + /// When the base-64 decoded contents of indicate an algorithm that uses PBKDF1 + /// (Password-Based Key Derivation Function 1) or PBKDF2 (Password-Based Key Derivation Function 2), + /// the password is converted to bytes via the UTF-8 encoding. This method + /// only supports the binary (BER/CER/DER) encoding of EncryptedPrivateKeyInfo. + /// + /// + /// Unsupported or malformed PEM-encoded objects will be ignored. If multiple supported PEM labels + /// are found, an exception is raised to prevent importing a key when + /// the key is ambiguous. + /// + /// This method supports the ENCRYPTED PRIVATE KEY PEM label. + /// public override void ImportFromEncryptedPem(ReadOnlySpan input, ReadOnlySpan password) { PemKeyImportHelpers.ImportEncryptedPem(input, password, ImportEncryptedPkcs8PrivateKey); } + /// + /// Imports an encrypted RFC 7468 PEM-encoded private key, replacing the keys for this object. + /// + /// The PEM text of the encrypted key to import. + /// + /// The bytes to use as a password when decrypting the key material. + /// + /// + /// does not contain a PEM-encoded key with a recognized label. + /// + /// -or- + /// + /// contains multiple PEM-encoded keys with a recognized label. + /// + /// + /// The password is incorrect. + /// + /// -or- + /// + /// The base-64 decoded contents of the PEM text from + /// do not represent an ASN.1-BER-encoded PKCS#8 EncryptedPrivateKeyInfo structure. + /// + /// -or- + /// + /// The base-64 decoded contents of the PEM text from + /// indicate the key is for an algorithm other than the algorithm + /// represented by this instance. + /// + /// -or- + /// + /// The base-64 decoded contents of the PEM text from + /// represent the key in a format that is not supported. + /// + /// -or- + /// + /// The algorithm-specific key import failed. + /// + /// + /// + /// The password bytes are passed directly into the Key Derivation Function (KDF) + /// used by the algorithm indicated by pbeParameters. This enables compatibility + /// with other systems which use a text encoding other than UTF-8 when processing + /// passwords with PBKDF2 (Password-Based Key Derivation Function 2). + /// + /// + /// The base-64 decoded contents of the PEM text only supports + /// the binary (BER/CER/DER) encoding of EncryptedPrivateKeyInfo. + /// + /// + /// Unsupported or malformed PEM-encoded objects will be ignored. If multiple supported PEM labels + /// are found, an exception is raised to prevent importing a key when + /// the key is ambiguous. + /// + /// This method supports the ENCRYPTED PRIVATE KEY PEM label. + /// public override void ImportFromEncryptedPem(ReadOnlySpan input, ReadOnlySpan passwordBytes) { PemKeyImportHelpers.ImportEncryptedPem(input, passwordBytes, ImportEncryptedPkcs8PrivateKey); diff --git a/src/libraries/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/ECDsa.cs b/src/libraries/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/ECDsa.cs index d10cd0c674c2a..977d2302b4394 100644 --- a/src/libraries/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/ECDsa.cs +++ b/src/libraries/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/ECDsa.cs @@ -1299,6 +1299,36 @@ public int GetMaxSignatureSize(DSASignatureFormat signatureFormat) } } + /// + /// Imports an RFC 7468 PEM-encoded key, replacing the keys for this object. + /// + /// The PEM text of the key to import. + /// + /// does not contain a PEM-encoded key with a recognized label. + /// + /// -or- + /// + /// contains multiple PEM-encoded keys with a recognized label. + /// + /// -or- + /// + /// contains an encrypted PEM-encoded key. + /// + /// + /// + /// Unsupported or malformed PEM-encoded objects will be ignored. If multiple supported PEM labels + /// are found, an exception is raised to prevent importing a key when + /// the key is ambiguous. + /// + /// + /// This method supports the following PEM labels: + /// + /// PUBLIC KEY + /// PRIVATE KEY + /// EC PRIVATE KEY + /// + /// + /// public override void ImportFromPem(ReadOnlySpan input) { PemKeyImportHelpers.ImportPem(input, label => { @@ -1321,11 +1351,117 @@ public override void ImportFromPem(ReadOnlySpan input) }); } + /// + /// Imports an encrypted RFC 7468 PEM-encoded private key, replacing the keys for this object. + /// + /// The PEM text of the encrypted key to import. + /// + /// The password to use for decrypting the key material. + /// + /// + /// does not contain a PEM-encoded key with a recognized label. + /// + /// -or- + /// + /// contains multiple PEM-encoded keys with a recognized label. + /// + /// + /// The password is incorrect. + /// + /// -or- + /// + /// The base-64 decoded contents of the PEM text from + /// do not represent an ASN.1-BER-encoded PKCS#8 EncryptedPrivateKeyInfo structure. + /// + /// -or- + /// + /// The base-64 decoded contents of the PEM text from + /// indicate the key is for an algorithm other than the algorithm + /// represented by this instance. + /// + /// -or- + /// + /// The base-64 decoded contents of the PEM text from + /// represent the key in a format that is not supported. + /// + /// -or- + /// + /// The algorithm-specific key import failed. + /// + /// + /// + /// When the base-64 decoded contents of indicate an algorithm that uses PBKDF1 + /// (Password-Based Key Derivation Function 1) or PBKDF2 (Password-Based Key Derivation Function 2), + /// the password is converted to bytes via the UTF-8 encoding. This method + /// only supports the binary (BER/CER/DER) encoding of EncryptedPrivateKeyInfo. + /// + /// + /// Unsupported or malformed PEM-encoded objects will be ignored. If multiple supported PEM labels + /// are found, an exception is raised to prevent importing a key when + /// the key is ambiguous. + /// + /// This method supports the ENCRYPTED PRIVATE KEY PEM label. + /// public override void ImportFromEncryptedPem(ReadOnlySpan input, ReadOnlySpan password) { PemKeyImportHelpers.ImportEncryptedPem(input, password, ImportEncryptedPkcs8PrivateKey); } + /// + /// Imports an encrypted RFC 7468 PEM-encoded private key, replacing the keys for this object. + /// + /// The PEM text of the encrypted key to import. + /// + /// The bytes to use as a password when decrypting the key material. + /// + /// + /// does not contain a PEM-encoded key with a recognized label. + /// + /// -or- + /// + /// contains multiple PEM-encoded keys with a recognized label. + /// + /// + /// The password is incorrect. + /// + /// -or- + /// + /// The base-64 decoded contents of the PEM text from + /// do not represent an ASN.1-BER-encoded PKCS#8 EncryptedPrivateKeyInfo structure. + /// + /// -or- + /// + /// The base-64 decoded contents of the PEM text from + /// indicate the key is for an algorithm other than the algorithm + /// represented by this instance. + /// + /// -or- + /// + /// The base-64 decoded contents of the PEM text from + /// represent the key in a format that is not supported. + /// + /// -or- + /// + /// The algorithm-specific key import failed. + /// + /// + /// + /// The password bytes are passed directly into the Key Derivation Function (KDF) + /// used by the algorithm indicated by pbeParameters. This enables compatibility + /// with other systems which use a text encoding other than UTF-8 when processing + /// passwords with PBKDF2 (Password-Based Key Derivation Function 2). + /// + /// + /// The base-64 decoded contents of the PEM text only supports + /// the binary (BER/CER/DER) encoding of EncryptedPrivateKeyInfo. + /// + /// + /// Unsupported or malformed PEM-encoded objects will be ignored. If multiple supported PEM labels + /// are found, an exception is raised to prevent importing a key when + /// the key is ambiguous. + /// + /// This method supports the ENCRYPTED PRIVATE KEY PEM label. + /// public override void ImportFromEncryptedPem(ReadOnlySpan input, ReadOnlySpan passwordBytes) { PemKeyImportHelpers.ImportEncryptedPem(input, passwordBytes, ImportEncryptedPkcs8PrivateKey); diff --git a/src/libraries/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/RSA.cs b/src/libraries/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/RSA.cs index 9cf69cea0f75f..16e5940acfefb 100644 --- a/src/libraries/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/RSA.cs +++ b/src/libraries/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/RSA.cs @@ -625,6 +625,37 @@ public override unsafe void ImportEncryptedPkcs8PrivateKey( bytesRead = localRead; } + /// + /// Imports an RFC 7468 PEM-encoded key, replacing the keys for this object. + /// + /// The PEM text of the key to import. + /// + /// does not contain a PEM-encoded key with a recognized label. + /// + /// -or- + /// + /// contains multiple PEM-encoded keys with a recognized label. + /// + /// -or- + /// + /// contains an encrypted PEM-encoded key. + /// + /// + /// + /// Unsupported or malformed PEM-encoded objects will be ignored. If multiple supported PEM labels + /// are found, an exception is raised to prevent importing a key when + /// the key is ambiguous. + /// + /// + /// This method supports the following PEM labels: + /// + /// PUBLIC KEY + /// PRIVATE KEY + /// RSA PRIVATE KEY + /// RSA PUBLIC KEY + /// + /// + /// public override void ImportFromPem(ReadOnlySpan input) { PemKeyImportHelpers.ImportPem(input, label => { @@ -651,11 +682,117 @@ public override void ImportFromPem(ReadOnlySpan input) }); } + /// + /// Imports an encrypted RFC 7468 PEM-encoded private key, replacing the keys for this object. + /// + /// The PEM text of the encrypted key to import. + /// + /// The password to use for decrypting the key material. + /// + /// + /// does not contain a PEM-encoded key with a recognized label. + /// + /// -or- + /// + /// contains multiple PEM-encoded keys with a recognized label. + /// + /// + /// The password is incorrect. + /// + /// -or- + /// + /// The base-64 decoded contents of the PEM text from + /// do not represent an ASN.1-BER-encoded PKCS#8 EncryptedPrivateKeyInfo structure. + /// + /// -or- + /// + /// The base-64 decoded contents of the PEM text from + /// indicate the key is for an algorithm other than the algorithm + /// represented by this instance. + /// + /// -or- + /// + /// The base-64 decoded contents of the PEM text from + /// represent the key in a format that is not supported. + /// + /// -or- + /// + /// The algorithm-specific key import failed. + /// + /// + /// + /// When the base-64 decoded contents of indicate an algorithm that uses PBKDF1 + /// (Password-Based Key Derivation Function 1) or PBKDF2 (Password-Based Key Derivation Function 2), + /// the password is converted to bytes via the UTF-8 encoding. This method + /// only supports the binary (BER/CER/DER) encoding of EncryptedPrivateKeyInfo. + /// + /// + /// Unsupported or malformed PEM-encoded objects will be ignored. If multiple supported PEM labels + /// are found, an exception is raised to prevent importing a key when + /// the key is ambiguous. + /// + /// This method supports the ENCRYPTED PRIVATE KEY PEM label. + /// public override void ImportFromEncryptedPem(ReadOnlySpan input, ReadOnlySpan password) { PemKeyImportHelpers.ImportEncryptedPem(input, password, ImportEncryptedPkcs8PrivateKey); } + /// + /// Imports an encrypted RFC 7468 PEM-encoded private key, replacing the keys for this object. + /// + /// The PEM text of the encrypted key to import. + /// + /// The bytes to use as a password when decrypting the key material. + /// + /// + /// does not contain a PEM-encoded key with a recognized label. + /// + /// -or- + /// + /// contains multiple PEM-encoded keys with a recognized label. + /// + /// + /// The password is incorrect. + /// + /// -or- + /// + /// The base-64 decoded contents of the PEM text from + /// do not represent an ASN.1-BER-encoded PKCS#8 EncryptedPrivateKeyInfo structure. + /// + /// -or- + /// + /// The base-64 decoded contents of the PEM text from + /// indicate the key is for an algorithm other than the algorithm + /// represented by this instance. + /// + /// -or- + /// + /// The base-64 decoded contents of the PEM text from + /// represent the key in a format that is not supported. + /// + /// -or- + /// + /// The algorithm-specific key import failed. + /// + /// + /// + /// The password bytes are passed directly into the Key Derivation Function (KDF) + /// used by the algorithm indicated by pbeParameters. This enables compatibility + /// with other systems which use a text encoding other than UTF-8 when processing + /// passwords with PBKDF2 (Password-Based Key Derivation Function 2). + /// + /// + /// The base-64 decoded contents of the PEM text only supports + /// the binary (BER/CER/DER) encoding of EncryptedPrivateKeyInfo. + /// + /// + /// Unsupported or malformed PEM-encoded objects will be ignored. If multiple supported PEM labels + /// are found, an exception is raised to prevent importing a key when + /// the key is ambiguous. + /// + /// This method supports the ENCRYPTED PRIVATE KEY PEM label. + /// public override void ImportFromEncryptedPem(ReadOnlySpan input, ReadOnlySpan passwordBytes) { PemKeyImportHelpers.ImportEncryptedPem(input, passwordBytes, ImportEncryptedPkcs8PrivateKey); diff --git a/src/libraries/System.Security.Cryptography.Primitives/src/System/Security/Cryptography/AsymmetricAlgorithm.cs b/src/libraries/System.Security.Cryptography.Primitives/src/System/Security/Cryptography/AsymmetricAlgorithm.cs index bf39f81135673..c1f4cc20eac0b 100644 --- a/src/libraries/System.Security.Cryptography.Primitives/src/System/Security/Cryptography/AsymmetricAlgorithm.cs +++ b/src/libraries/System.Security.Cryptography.Primitives/src/System/Security/Cryptography/AsymmetricAlgorithm.cs @@ -167,9 +167,36 @@ public virtual bool TryExportSubjectPublicKeyInfo(Span destination, out in public virtual void ImportFromEncryptedPem(ReadOnlySpan input, ReadOnlySpan password) => throw new NotImplementedException(SR.NotSupported_SubclassOverride); + /// + /// When overridden in a derived class, imports an encrypted RFC 7468 + /// PEM-encoded key, replacing the keys for this object. + /// + /// The PEM text of the encrypted key to import. + /// + /// The bytes to use as a password when decrypting the key material. + /// + /// + /// A derived type has not overriden this member. + /// + /// + /// Because each algorithm may have algorithm-specific PEM labels, the + /// default behavior will throw . + /// public virtual void ImportFromEncryptedPem(ReadOnlySpan input, ReadOnlySpan passwordBytes) => throw new NotImplementedException(SR.NotSupported_SubclassOverride); + /// + /// When overridden in a derived class, imports an RFC 7468 textually + /// encoded key, replacing the keys for this object. + /// + /// The text of the PEM key to import. + /// + /// A derived type has not overriden this member. + /// + /// + /// Because each algorithm may have algorithm-specific PEM labels, the + /// default behavior will throw . + /// public virtual void ImportFromPem(ReadOnlySpan input) => throw new NotImplementedException(SR.NotSupported_SubclassOverride); From 6c199dee3035bc1ba387d3acf8cbfc6d3d0e204f Mon Sep 17 00:00:00 2001 From: Kevin Jones Date: Wed, 25 Mar 2020 16:19:56 -0400 Subject: [PATCH 03/18] Fix reference source --- .../ref/System.Security.Cryptography.Algorithms.cs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/libraries/System.Security.Cryptography.Algorithms/ref/System.Security.Cryptography.Algorithms.cs b/src/libraries/System.Security.Cryptography.Algorithms/ref/System.Security.Cryptography.Algorithms.cs index 68f153b882db9..5ea714ab6d8c1 100644 --- a/src/libraries/System.Security.Cryptography.Algorithms/ref/System.Security.Cryptography.Algorithms.cs +++ b/src/libraries/System.Security.Cryptography.Algorithms/ref/System.Security.Cryptography.Algorithms.cs @@ -135,6 +135,8 @@ public override void FromXmlString(string xmlString) { } protected virtual byte[] HashData(System.IO.Stream data, System.Security.Cryptography.HashAlgorithmName hashAlgorithm) { throw null; } public override void ImportEncryptedPkcs8PrivateKey(System.ReadOnlySpan passwordBytes, System.ReadOnlySpan source, out int bytesRead) { throw null; } public override void ImportEncryptedPkcs8PrivateKey(System.ReadOnlySpan password, System.ReadOnlySpan source, out int bytesRead) { throw null; } + public override void ImportFromEncryptedPem(System.ReadOnlySpan input, System.ReadOnlySpan passwordBytes) { } + public override void ImportFromEncryptedPem(System.ReadOnlySpan input, System.ReadOnlySpan password) { } public override void ImportFromPem(System.ReadOnlySpan input) { } public abstract void ImportParameters(System.Security.Cryptography.DSAParameters parameters); public override void ImportPkcs8PrivateKey(System.ReadOnlySpan source, out int bytesRead) { throw null; } @@ -284,6 +286,8 @@ public virtual void GenerateKey(System.Security.Cryptography.ECCurve curve) { } public virtual void ImportECPrivateKey(System.ReadOnlySpan source, out int bytesRead) { throw null; } public override void ImportEncryptedPkcs8PrivateKey(System.ReadOnlySpan passwordBytes, System.ReadOnlySpan source, out int bytesRead) { throw null; } public override void ImportEncryptedPkcs8PrivateKey(System.ReadOnlySpan password, System.ReadOnlySpan source, out int bytesRead) { throw null; } + public override void ImportFromEncryptedPem(System.ReadOnlySpan input, System.ReadOnlySpan passwordBytes) { } + public override void ImportFromEncryptedPem(System.ReadOnlySpan input, System.ReadOnlySpan password) { } public override void ImportFromPem(System.ReadOnlySpan input) { } public virtual void ImportParameters(System.Security.Cryptography.ECParameters parameters) { } public override void ImportPkcs8PrivateKey(System.ReadOnlySpan source, out int bytesRead) { throw null; } @@ -326,6 +330,8 @@ public virtual void GenerateKey(System.Security.Cryptography.ECCurve curve) { } public virtual void ImportECPrivateKey(System.ReadOnlySpan source, out int bytesRead) { throw null; } public override void ImportEncryptedPkcs8PrivateKey(System.ReadOnlySpan passwordBytes, System.ReadOnlySpan source, out int bytesRead) { throw null; } public override void ImportEncryptedPkcs8PrivateKey(System.ReadOnlySpan password, System.ReadOnlySpan source, out int bytesRead) { throw null; } + public override void ImportFromEncryptedPem(System.ReadOnlySpan input, System.ReadOnlySpan passwordBytes) { } + public override void ImportFromEncryptedPem(System.ReadOnlySpan input, System.ReadOnlySpan password) { } public override void ImportFromPem(System.ReadOnlySpan input) { } public virtual void ImportParameters(System.Security.Cryptography.ECParameters parameters) { } public override void ImportPkcs8PrivateKey(System.ReadOnlySpan source, out int bytesRead) { throw null; } From 8ae49aedacaae836ad956a1e4435cfac53bf9b11 Mon Sep 17 00:00:00 2001 From: Kevin Jones Date: Wed, 25 Mar 2020 17:50:54 -0400 Subject: [PATCH 04/18] Add missing doc comment. --- .../Security/Cryptography/AsymmetricAlgorithm.cs | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/libraries/System.Security.Cryptography.Primitives/src/System/Security/Cryptography/AsymmetricAlgorithm.cs b/src/libraries/System.Security.Cryptography.Primitives/src/System/Security/Cryptography/AsymmetricAlgorithm.cs index c1f4cc20eac0b..5dd73c8ced548 100644 --- a/src/libraries/System.Security.Cryptography.Primitives/src/System/Security/Cryptography/AsymmetricAlgorithm.cs +++ b/src/libraries/System.Security.Cryptography.Primitives/src/System/Security/Cryptography/AsymmetricAlgorithm.cs @@ -164,6 +164,21 @@ public virtual bool TryExportPkcs8PrivateKey(Span destination, out int byt public virtual bool TryExportSubjectPublicKeyInfo(Span destination, out int bytesWritten) => throw new NotImplementedException(SR.NotSupported_SubclassOverride); + /// + /// When overridden in a derived class, imports an encrypted RFC 7468 + /// PEM-encoded key, replacing the keys for this object. + /// + /// The PEM text of the encrypted key to import. + /// + /// The password to use for decrypting the key material. + /// + /// + /// A derived type has not overriden this member. + /// + /// + /// Because each algorithm may have algorithm-specific PEM labels, the + /// default behavior will throw . + /// public virtual void ImportFromEncryptedPem(ReadOnlySpan input, ReadOnlySpan password) => throw new NotImplementedException(SR.NotSupported_SubclassOverride); From 7c09314e34dfa5a988829edaf1daa945b961ab69 Mon Sep 17 00:00:00 2001 From: Kevin Jones Date: Wed, 25 Mar 2020 21:56:53 -0400 Subject: [PATCH 05/18] Skip overload tests for shim helpers. --- .../System.Security.Cryptography.Csp/tests/ShimHelpers.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/libraries/System.Security.Cryptography.Csp/tests/ShimHelpers.cs b/src/libraries/System.Security.Cryptography.Csp/tests/ShimHelpers.cs index 63dc763b5ef09..9d02ae8643bdb 100644 --- a/src/libraries/System.Security.Cryptography.Csp/tests/ShimHelpers.cs +++ b/src/libraries/System.Security.Cryptography.Csp/tests/ShimHelpers.cs @@ -51,6 +51,9 @@ public static void VerifyAllBaseMembersOverloaded(Type shimType) // DecryptValue and EncryptValue throw PNSE in base class, so they don't need to be checked. "DecryptValue", "EncryptValue", + // PEM Import/Export defers to Import methods. + "ImportFromPem", + "ImportFromEncryptedPem", // Key Import/Export defers to ImportParameters/ExportParameters (covered by *KeyFileTests) "ImportRSAPrivateKey", "ImportRSAPublicKey", From f7c25013e8767656b6a97283f8f0d9f4f5838fab Mon Sep 17 00:00:00 2001 From: Kevin Jones Date: Wed, 25 Mar 2020 22:02:34 -0400 Subject: [PATCH 06/18] Skip explicit curve test for unsupported platforms --- .../AlgorithmImplementations/EC/ECKeyPemTests.cs | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/EC/ECKeyPemTests.cs b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/EC/ECKeyPemTests.cs index 3a98f36d99900..08a837649abb5 100644 --- a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/EC/ECKeyPemTests.cs +++ b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/EC/ECKeyPemTests.cs @@ -12,6 +12,7 @@ public abstract class ECKeyPemTests where TAlg : AsymmetricAlgorithm { protected abstract TAlg CreateKey(); protected abstract ECParameters ExportParameters(TAlg key, bool includePrivateParameters); + public static bool SupportsExplicitCurves { get; } = EcDiffieHellman.Tests.ECDiffieHellmanFactory.ExplicitCurvesSupported; [Fact] public void ImportFromPem_NoPem() @@ -67,6 +68,11 @@ public void ImportFromPem_Spki_Simple() [Fact] public void ImportFromPem_ECPrivateKey_ExplicitParams() { + if (!SupportsExplicitCurves) + { + return; + } + using TAlg key = CreateKey(); key.ImportFromPem(@" -----BEGIN EC PRIVATE KEY----- @@ -87,6 +93,11 @@ public void ImportFromPem_ECPrivateKey_ExplicitParams() [Fact] public void ImportFromPem_Pkcs8_ExplicitParams() { + if (!SupportsExplicitCurves) + { + return; + } + using TAlg key = CreateKey(); key.ImportFromPem(@" -----BEGIN PRIVATE KEY----- From 61d0ea53005fa7cfe5854d9d4ed26a68233cf9c6 Mon Sep 17 00:00:00 2001 From: Kevin Jones Date: Thu, 26 Mar 2020 12:54:34 -0400 Subject: [PATCH 07/18] Remove explicit params test. This is not strictly related to processing PEMs since the underlying import methods already test this. --- .../EC/ECKeyPemTests.cs | 51 ------------------- 1 file changed, 51 deletions(-) diff --git a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/EC/ECKeyPemTests.cs b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/EC/ECKeyPemTests.cs index 08a837649abb5..2d2e69cfa6946 100644 --- a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/EC/ECKeyPemTests.cs +++ b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/EC/ECKeyPemTests.cs @@ -12,7 +12,6 @@ public abstract class ECKeyPemTests where TAlg : AsymmetricAlgorithm { protected abstract TAlg CreateKey(); protected abstract ECParameters ExportParameters(TAlg key, bool includePrivateParameters); - public static bool SupportsExplicitCurves { get; } = EcDiffieHellman.Tests.ECDiffieHellmanFactory.ExplicitCurvesSupported; [Fact] public void ImportFromPem_NoPem() @@ -65,56 +64,6 @@ public void ImportFromPem_Spki_Simple() EccTestBase.ComparePublicKey(expected.Q, ecParameters.Q, isEqual: true); } - [Fact] - public void ImportFromPem_ECPrivateKey_ExplicitParams() - { - if (!SupportsExplicitCurves) - { - return; - } - - using TAlg key = CreateKey(); - key.ImportFromPem(@" ------BEGIN EC PRIVATE KEY----- -MIIBaAIBAQQgcKEsLbFoRe1W/2jPwhpHKz8E19aFG/Y0ny19WzRSs4qggfowgfcC -AQEwLAYHKoZIzj0BAQIhAP////8AAAABAAAAAAAAAAAAAAAA//////////////// -MFsEIP////8AAAABAAAAAAAAAAAAAAAA///////////////8BCBaxjXYqjqT57Pr -vVV2mIa8ZR0GsMxTsPY7zjw+J9JgSwMVAMSdNgiG5wSTamZ44ROdJreBn36QBEEE -axfR8uEsQkf4vOblY6RA8ncDfYEt6zOg9KE5RdiYwpZP40Li/hp/m47n60p8D54W -K84zV2sxXs7LtkBoN79R9QIhAP////8AAAAA//////////+85vqtpxeehPO5ysL8 -YyVRAgEBoUQDQgAEgQHs5HRkpurXDPaabivT2IaRoyYtIsuk92Ner/JmgKjYoSum -HVmSNfZ9nLTVjxeD08pD548KWrqmJAeZNsDDqQ== ------END EC PRIVATE KEY-----"); - ECParameters ecParameters = ExportParameters(key, true); - ECParameters expected = EccTestData.GetNistP256ReferenceKeyExplicit(); - EccTestBase.AssertEqual(expected, ecParameters); - } - - [Fact] - public void ImportFromPem_Pkcs8_ExplicitParams() - { - if (!SupportsExplicitCurves) - { - return; - } - - using TAlg key = CreateKey(); - key.ImportFromPem(@" ------BEGIN PRIVATE KEY----- -MIIBeQIBADCCAQMGByqGSM49AgEwgfcCAQEwLAYHKoZIzj0BAQIhAP////8AAAAB -AAAAAAAAAAAAAAAA////////////////MFsEIP////8AAAABAAAAAAAAAAAAAAAA -///////////////8BCBaxjXYqjqT57PrvVV2mIa8ZR0GsMxTsPY7zjw+J9JgSwMV -AMSdNgiG5wSTamZ44ROdJreBn36QBEEEaxfR8uEsQkf4vOblY6RA8ncDfYEt6zOg -9KE5RdiYwpZP40Li/hp/m47n60p8D54WK84zV2sxXs7LtkBoN79R9QIhAP////8A -AAAA//////////+85vqtpxeehPO5ysL8YyVRAgEBBG0wawIBAQQgcKEsLbFoRe1W -/2jPwhpHKz8E19aFG/Y0ny19WzRSs4qhRANCAASBAezkdGSm6tcM9ppuK9PYhpGj -Ji0iy6T3Y16v8maAqNihK6YdWZI19n2ctNWPF4PTykPnjwpauqYkB5k2wMOp ------END PRIVATE KEY-----"); - ECParameters ecParameters = ExportParameters(key, true); - ECParameters expected = EccTestData.GetNistP256ReferenceKeyExplicit(); - EccTestBase.AssertEqual(expected, ecParameters); - } - [Fact] public void ImportFromPem_Spki_PrecedingUnrelatedPemIsIgnored() { From 47880fb518d717b88b251d2e25a975c831141077 Mon Sep 17 00:00:00 2001 From: Kevin Jones Date: Tue, 7 Apr 2020 09:37:58 -0400 Subject: [PATCH 08/18] Use size based on actual decoding. --- .../Internal/Cryptography/PemKeyImportHelpers.cs | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/libraries/Common/src/Internal/Cryptography/PemKeyImportHelpers.cs b/src/libraries/Common/src/Internal/Cryptography/PemKeyImportHelpers.cs index d385785d13843..ac43ef57e0063 100644 --- a/src/libraries/Common/src/Internal/Cryptography/PemKeyImportHelpers.cs +++ b/src/libraries/Common/src/Internal/Cryptography/PemKeyImportHelpers.cs @@ -56,10 +56,11 @@ public static void ImportEncryptedPem( ReadOnlySpan base64Contents = foundSlice[foundFields.Base64Data]; int base64size = foundFields.DecodedDataLength; byte[] decodeBuffer = CryptoPool.Rent(base64size); + int bytesWritten = 0; try { - if (!Convert.TryFromBase64Chars(base64Contents, decodeBuffer, out int bytesWritten)) + if (!Convert.TryFromBase64Chars(base64Contents, decodeBuffer, out bytesWritten)) { // Couldn't decode base64. We shouldn't get here since the // contents are pre-validated. @@ -68,12 +69,12 @@ public static void ImportEncryptedPem( } Debug.Assert(bytesWritten == base64size); - Span decodedBase64 = decodeBuffer.AsSpan(0, base64size); + Span decodedBase64 = decodeBuffer.AsSpan(0, bytesWritten); importAction(password, decodedBase64, out _); } finally { - CryptoPool.Return(decodeBuffer, clearSize: base64size); + CryptoPool.Return(decodeBuffer, clearSize: bytesWritten); } } @@ -133,10 +134,11 @@ public static void ImportPem(ReadOnlySpan input, FindImportActionFunc call ReadOnlySpan base64Contents = foundSlice[foundFields.Base64Data]; int base64size = foundFields.DecodedDataLength; byte[] decodeBuffer = CryptoPool.Rent(base64size); + int bytesWritten = 0; try { - if (!Convert.TryFromBase64Chars(base64Contents, decodeBuffer, out int bytesWritten)) + if (!Convert.TryFromBase64Chars(base64Contents, decodeBuffer, out bytesWritten)) { // Couldn't decode base64. We shouldn't get here since the // contents are pre-validated. @@ -145,12 +147,12 @@ public static void ImportPem(ReadOnlySpan input, FindImportActionFunc call } Debug.Assert(bytesWritten == base64size); - Span decodedBase64 = decodeBuffer.AsSpan(0, base64size); + Span decodedBase64 = decodeBuffer.AsSpan(0, bytesWritten); importAction(decodedBase64, out _); } finally { - CryptoPool.Return(decodeBuffer, clearSize: base64size); + CryptoPool.Return(decodeBuffer, clearSize: bytesWritten); } } } From 62faaab5c1571611ae3f938dd6952a8aa475c927 Mon Sep 17 00:00:00 2001 From: Kevin Jones Date: Tue, 7 Apr 2020 10:16:21 -0400 Subject: [PATCH 09/18] Extract PEM labels out to constants. --- .../Internal/Cryptography/PemKeyImportHelpers.cs | 4 ++-- .../System/Security/Cryptography/PemLabels.cs | 16 ++++++++++++++++ ...ystem.Security.Cryptography.Algorithms.csproj | 3 +++ .../src/System/Security/Cryptography/DSA.cs | 4 ++-- .../Security/Cryptography/ECDiffieHellman.cs | 6 +++--- .../src/System/Security/Cryptography/ECDsa.cs | 6 +++--- .../src/System/Security/Cryptography/RSA.cs | 8 ++++---- 7 files changed, 33 insertions(+), 14 deletions(-) create mode 100644 src/libraries/Common/src/System/Security/Cryptography/PemLabels.cs diff --git a/src/libraries/Common/src/Internal/Cryptography/PemKeyImportHelpers.cs b/src/libraries/Common/src/Internal/Cryptography/PemKeyImportHelpers.cs index ac43ef57e0063..46a94183dae50 100644 --- a/src/libraries/Common/src/Internal/Cryptography/PemKeyImportHelpers.cs +++ b/src/libraries/Common/src/Internal/Cryptography/PemKeyImportHelpers.cs @@ -32,7 +32,7 @@ public static void ImportEncryptedPem( { ReadOnlySpan label = pem[fields.Label]; - if (label.SequenceEqual("ENCRYPTED PRIVATE KEY")) + if (label.SequenceEqual(PemLabels.EncryptedPkcs8PrivateKey)) { if (foundEncryptedPem) { @@ -108,7 +108,7 @@ public static void ImportPem(ReadOnlySpan input, FindImportActionFunc call foundFields = fields; foundSlice = pem; } - else if (label.SequenceEqual("ENCRYPTED PRIVATE KEY")) + else if (label.SequenceEqual(PemLabels.EncryptedPkcs8PrivateKey)) { containsEncryptedPem = true; } diff --git a/src/libraries/Common/src/System/Security/Cryptography/PemLabels.cs b/src/libraries/Common/src/System/Security/Cryptography/PemLabels.cs new file mode 100644 index 0000000000000..5adf4ab5d83d9 --- /dev/null +++ b/src/libraries/Common/src/System/Security/Cryptography/PemLabels.cs @@ -0,0 +1,16 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +namespace System.Security.Cryptography +{ + internal static class PemLabels + { + internal const string Pkcs8PrivateKey = "PRIVATE KEY"; + internal const string EncryptedPkcs8PrivateKey = "ENCRYPTED PRIVATE KEY"; + internal const string SpkiPublicKey = "PUBLIC KEY"; + internal const string RsaPublicKey = "RSA PUBLIC KEY"; + internal const string RsaPrivateKey = "RSA PRIVATE KEY"; + internal const string EcPrivateKey = "EC PRIVATE KEY"; + } +} diff --git a/src/libraries/System.Security.Cryptography.Algorithms/src/System.Security.Cryptography.Algorithms.csproj b/src/libraries/System.Security.Cryptography.Algorithms/src/System.Security.Cryptography.Algorithms.csproj index 4ed8e9a17b15d..b0a49ecf2030e 100644 --- a/src/libraries/System.Security.Cryptography.Algorithms/src/System.Security.Cryptography.Algorithms.csproj +++ b/src/libraries/System.Security.Cryptography.Algorithms/src/System.Security.Cryptography.Algorithms.csproj @@ -137,6 +137,9 @@ Common\System\Security\Cryptography\PasswordBasedEncryption.cs + + Common\System\Security\Cryptography\PemLabels.cs + Common\System\Security\Cryptography\Pkcs12Kdf.cs diff --git a/src/libraries/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/DSA.cs b/src/libraries/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/DSA.cs index a471e1ce4c913..f85834c3af7e5 100644 --- a/src/libraries/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/DSA.cs +++ b/src/libraries/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/DSA.cs @@ -1158,11 +1158,11 @@ public int GetMaxSignatureSize(DSASignatureFormat signatureFormat) public override void ImportFromPem(ReadOnlySpan input) { PemKeyImportHelpers.ImportPem(input, label => { - if (label.SequenceEqual("PRIVATE KEY")) + if (label.SequenceEqual(PemLabels.Pkcs8PrivateKey)) { return ImportPkcs8PrivateKey; } - else if (label.SequenceEqual("PUBLIC KEY")) + else if (label.SequenceEqual(PemLabels.SpkiPublicKey)) { return ImportSubjectPublicKeyInfo; } diff --git a/src/libraries/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/ECDiffieHellman.cs b/src/libraries/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/ECDiffieHellman.cs index d0d64fc660030..5eee83194deb5 100644 --- a/src/libraries/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/ECDiffieHellman.cs +++ b/src/libraries/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/ECDiffieHellman.cs @@ -468,15 +468,15 @@ public virtual unsafe bool TryExportECPrivateKey(Span destination, out int public override void ImportFromPem(ReadOnlySpan input) { PemKeyImportHelpers.ImportPem(input, label => { - if (label.SequenceEqual("PRIVATE KEY")) + if (label.SequenceEqual(PemLabels.Pkcs8PrivateKey)) { return ImportPkcs8PrivateKey; } - else if (label.SequenceEqual("PUBLIC KEY")) + else if (label.SequenceEqual(PemLabels.SpkiPublicKey)) { return ImportSubjectPublicKeyInfo; } - else if (label.SequenceEqual("EC PRIVATE KEY")) + else if (label.SequenceEqual(PemLabels.EcPrivateKey)) { return ImportECPrivateKey; } diff --git a/src/libraries/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/ECDsa.cs b/src/libraries/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/ECDsa.cs index 977d2302b4394..1115a27867ca6 100644 --- a/src/libraries/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/ECDsa.cs +++ b/src/libraries/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/ECDsa.cs @@ -1332,15 +1332,15 @@ public int GetMaxSignatureSize(DSASignatureFormat signatureFormat) public override void ImportFromPem(ReadOnlySpan input) { PemKeyImportHelpers.ImportPem(input, label => { - if (label.SequenceEqual("PRIVATE KEY")) + if (label.SequenceEqual(PemLabels.Pkcs8PrivateKey)) { return ImportPkcs8PrivateKey; } - else if (label.SequenceEqual("PUBLIC KEY")) + else if (label.SequenceEqual(PemLabels.SpkiPublicKey)) { return ImportSubjectPublicKeyInfo; } - else if (label.SequenceEqual("EC PRIVATE KEY")) + else if (label.SequenceEqual(PemLabels.EcPrivateKey)) { return ImportECPrivateKey; } diff --git a/src/libraries/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/RSA.cs b/src/libraries/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/RSA.cs index 16e5940acfefb..c8755b5996ad8 100644 --- a/src/libraries/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/RSA.cs +++ b/src/libraries/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/RSA.cs @@ -659,19 +659,19 @@ public override unsafe void ImportEncryptedPkcs8PrivateKey( public override void ImportFromPem(ReadOnlySpan input) { PemKeyImportHelpers.ImportPem(input, label => { - if (label.SequenceEqual("RSA PRIVATE KEY")) + if (label.SequenceEqual(PemLabels.RsaPrivateKey)) { return ImportRSAPrivateKey; } - else if (label.SequenceEqual("PRIVATE KEY")) + else if (label.SequenceEqual(PemLabels.Pkcs8PrivateKey)) { return ImportPkcs8PrivateKey; } - else if (label.SequenceEqual("RSA PUBLIC KEY")) + else if (label.SequenceEqual(PemLabels.RsaPublicKey)) { return ImportRSAPublicKey; } - else if (label.SequenceEqual("PUBLIC KEY")) + else if (label.SequenceEqual(PemLabels.SpkiPublicKey)) { return ImportSubjectPublicKeyInfo; } From 50ad96b71487afa445d4d681b7b3ab174bae94fb Mon Sep 17 00:00:00 2001 From: Kevin Jones Date: Mon, 6 Apr 2020 12:58:22 -0400 Subject: [PATCH 10/18] Braced usings. --- .../EC/ECKeyPemTests.cs | 148 +++++++++++------- 1 file changed, 88 insertions(+), 60 deletions(-) diff --git a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/EC/ECKeyPemTests.cs b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/EC/ECKeyPemTests.cs index 2d2e69cfa6946..42d6318331915 100644 --- a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/EC/ECKeyPemTests.cs +++ b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/EC/ECKeyPemTests.cs @@ -16,59 +16,68 @@ public abstract class ECKeyPemTests where TAlg : AsymmetricAlgorithm [Fact] public void ImportFromPem_NoPem() { - using TAlg key = CreateKey(); - AssertExtensions.Throws("input", () => key.ImportFromPem("")); + using (TAlg key = CreateKey()) + { + AssertExtensions.Throws("input", () => key.ImportFromPem("")); + } } [Fact] public void ImportFromPem_ECPrivateKey_Simple() { - using TAlg key = CreateKey(); - key.ImportFromPem(@" + using (TAlg key = CreateKey()) + { + key.ImportFromPem(@" -----BEGIN EC PRIVATE KEY----- MHcCAQEEIHChLC2xaEXtVv9oz8IaRys/BNfWhRv2NJ8tfVs0UrOKoAoGCCqGSM49 AwEHoUQDQgAEgQHs5HRkpurXDPaabivT2IaRoyYtIsuk92Ner/JmgKjYoSumHVmS NfZ9nLTVjxeD08pD548KWrqmJAeZNsDDqQ== -----END EC PRIVATE KEY-----"); - ECParameters ecParameters = ExportParameters(key, true); - ECParameters expected = EccTestData.GetNistP256ReferenceKey(); - EccTestBase.AssertEqual(expected, ecParameters); + ECParameters ecParameters = ExportParameters(key, true); + ECParameters expected = EccTestData.GetNistP256ReferenceKey(); + EccTestBase.AssertEqual(expected, ecParameters); + } } [Fact] public void ImportFromPem_Pkcs8_Simple() { - using TAlg key = CreateKey(); - key.ImportFromPem(@" + using (TAlg key = CreateKey()) + { + key.ImportFromPem(@" -----BEGIN PRIVATE KEY----- MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgcKEsLbFoRe1W/2jP whpHKz8E19aFG/Y0ny19WzRSs4qhRANCAASBAezkdGSm6tcM9ppuK9PYhpGjJi0i y6T3Y16v8maAqNihK6YdWZI19n2ctNWPF4PTykPnjwpauqYkB5k2wMOp -----END PRIVATE KEY-----"); - ECParameters ecParameters = ExportParameters(key, true); - ECParameters expected = EccTestData.GetNistP256ReferenceKey(); - EccTestBase.AssertEqual(expected, ecParameters); + ECParameters ecParameters = ExportParameters(key, true); + ECParameters expected = EccTestData.GetNistP256ReferenceKey(); + EccTestBase.AssertEqual(expected, ecParameters); + } } [Fact] public void ImportFromPem_Spki_Simple() { - using TAlg key = CreateKey(); - key.ImportFromPem(@" + using (TAlg key = CreateKey()) + { + key.ImportFromPem(@" -----BEGIN PUBLIC KEY----- MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEgQHs5HRkpurXDPaabivT2IaRoyYt Isuk92Ner/JmgKjYoSumHVmSNfZ9nLTVjxeD08pD548KWrqmJAeZNsDDqQ== -----END PUBLIC KEY-----"); - ECParameters ecParameters = ExportParameters(key, false); - ECParameters expected = EccTestData.GetNistP256ReferenceKey(); - EccTestBase.ComparePublicKey(expected.Q, ecParameters.Q, isEqual: true); + ECParameters ecParameters = ExportParameters(key, false); + ECParameters expected = EccTestData.GetNistP256ReferenceKey(); + EccTestBase.ComparePublicKey(expected.Q, ecParameters.Q, isEqual: true); + } } [Fact] public void ImportFromPem_Spki_PrecedingUnrelatedPemIsIgnored() { - using TAlg key = CreateKey(); - key.ImportFromPem(@" + using (TAlg key = CreateKey()) + { + key.ImportFromPem(@" -----BEGIN CERTIFICATE----- MIICTzCCAgmgAwIBAgIJAMQtYhFJ0+5jMA0GCSqGSIb3DQEBBQUAMIGSMQswCQYD VQQGEwJVUzETMBEGA1UECAwKV2FzaGluZ3RvbjEQMA4GA1UEBwwHUmVkbW9uZDEY @@ -88,16 +97,18 @@ public void ImportFromPem_Spki_PrecedingUnrelatedPemIsIgnored() MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEgQHs5HRkpurXDPaabivT2IaRoyYt Isuk92Ner/JmgKjYoSumHVmSNfZ9nLTVjxeD08pD548KWrqmJAeZNsDDqQ== -----END PUBLIC KEY-----"); - ECParameters ecParameters = ExportParameters(key, false); - ECParameters expected = EccTestData.GetNistP256ReferenceKey(); - EccTestBase.ComparePublicKey(expected.Q, ecParameters.Q, isEqual: true); + ECParameters ecParameters = ExportParameters(key, false); + ECParameters expected = EccTestData.GetNistP256ReferenceKey(); + EccTestBase.ComparePublicKey(expected.Q, ecParameters.Q, isEqual: true); + } } [Fact] public void ImportFromPem_Spki_PrecedingMalformedPem() { - using TAlg key = CreateKey(); - key.ImportFromPem(@" + using (TAlg key = CreateKey()) + { + key.ImportFromPem(@" -----BEGIN CERTIFICATE----- $$ I AM NOT A PEM -----END CERTIFICATE----- @@ -105,15 +116,18 @@ public void ImportFromPem_Spki_PrecedingMalformedPem() MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEgQHs5HRkpurXDPaabivT2IaRoyYt Isuk92Ner/JmgKjYoSumHVmSNfZ9nLTVjxeD08pD548KWrqmJAeZNsDDqQ== -----END PUBLIC KEY-----"); - ECParameters ecParameters = ExportParameters(key, false); - ECParameters expected = EccTestData.GetNistP256ReferenceKey(); - EccTestBase.ComparePublicKey(expected.Q, ecParameters.Q, isEqual: true); + ECParameters ecParameters = ExportParameters(key, false); + ECParameters expected = EccTestData.GetNistP256ReferenceKey(); + EccTestBase.ComparePublicKey(expected.Q, ecParameters.Q, isEqual: true); + } } [Fact] public void ImportFromPem_Spki_AmbiguousKey_Spki() { - string pem = @" + using (TAlg key = CreateKey()) + { + string pem = @" -----BEGIN PUBLIC KEY----- MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEgQHs5HRkpurXDPaabivT2IaRoyYt Isuk92Ner/JmgKjYoSumHVmSNfZ9nLTVjxeD08pD548KWrqmJAeZNsDDqQ== @@ -122,14 +136,16 @@ public void ImportFromPem_Spki_AmbiguousKey_Spki() MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEgQHs5HRkpurXDPaabivT2IaRoyYt Isuk92Ner/JmgKjYoSumHVmSNfZ9nLTVjxeD08pD548KWrqmJAeZNsDDqQ== -----END PUBLIC KEY-----"; - using TAlg key = CreateKey(); - AssertExtensions.Throws("input", () => key.ImportFromPem(pem)); + AssertExtensions.Throws("input", () => key.ImportFromPem(pem)); + } } [Fact] public void ImportFromPem_Spki_AmbiguousKey_EncryptedPkcs8() { - string pem = @" + using (TAlg key = CreateKey()) + { + string pem = @" -----BEGIN ENCRYPTED PRIVATE KEY----- MIHgMEsGCSqGSIb3DQEFDTA+MCkGCSqGSIb3DQEFDDAcBAjVvm4KTLb0JgICCAAw DAYIKoZIhvcNAgkFADARBgUrDgMCBwQIuHgfok8Ytl0EgZDkDSJ9vt8UvSesdyV+ @@ -141,14 +157,16 @@ public void ImportFromPem_Spki_AmbiguousKey_EncryptedPkcs8() MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEgQHs5HRkpurXDPaabivT2IaRoyYt Isuk92Ner/JmgKjYoSumHVmSNfZ9nLTVjxeD08pD548KWrqmJAeZNsDDqQ== -----END PUBLIC KEY-----"; - using TAlg key = CreateKey(); - AssertExtensions.Throws("input", () => key.ImportFromPem(pem)); + AssertExtensions.Throws("input", () => key.ImportFromPem(pem)); + } } [Fact] public void ImportFromPem_EncryptedPrivateKeyFails() { - string pem = @" + using (TAlg key = CreateKey()) + { + string pem = @" -----BEGIN ENCRYPTED PRIVATE KEY----- MIHgMEsGCSqGSIb3DQEFDTA+MCkGCSqGSIb3DQEFDDAcBAjVvm4KTLb0JgICCAAw DAYIKoZIhvcNAgkFADARBgUrDgMCBwQIuHgfok8Ytl0EgZDkDSJ9vt8UvSesdyV+ @@ -156,14 +174,16 @@ public void ImportFromPem_EncryptedPrivateKeyFails() opSAJ/pvHONL5kyAJLeNyG9c/mR2qyrP2L9gL0Z5fB9NyPejKTLi0PXMGQWdDTH8 Qh0fqdrNovgFLubbJFMQN/MwwIAfIuf0Mn0WFYYeQiBJ3kg= -----END ENCRYPTED PRIVATE KEY-----"; - using TAlg key = CreateKey(); - AssertExtensions.Throws("input", () => key.ImportFromPem(pem)); + AssertExtensions.Throws("input", () => key.ImportFromPem(pem)); + } } [Fact] public void ImportFromEncryptedPem_Pkcs8_Char_Simple() { - string pem = @" + using (TAlg key = CreateKey()) + { + string pem = @" -----BEGIN ENCRYPTED PRIVATE KEY----- MIHgMEsGCSqGSIb3DQEFDTA+MCkGCSqGSIb3DQEFDDAcBAjVvm4KTLb0JgICCAAw DAYIKoZIhvcNAgkFADARBgUrDgMCBwQIuHgfok8Ytl0EgZDkDSJ9vt8UvSesdyV+ @@ -171,17 +191,19 @@ public void ImportFromEncryptedPem_Pkcs8_Char_Simple() opSAJ/pvHONL5kyAJLeNyG9c/mR2qyrP2L9gL0Z5fB9NyPejKTLi0PXMGQWdDTH8 Qh0fqdrNovgFLubbJFMQN/MwwIAfIuf0Mn0WFYYeQiBJ3kg= -----END ENCRYPTED PRIVATE KEY-----"; - using TAlg key = CreateKey(); - key.ImportFromEncryptedPem(pem, "test"); - ECParameters ecParameters = ExportParameters(key, true); - ECParameters expected = EccTestData.GetNistP256ReferenceKey(); - EccTestBase.AssertEqual(expected, ecParameters); + key.ImportFromEncryptedPem(pem, "test"); + ECParameters ecParameters = ExportParameters(key, true); + ECParameters expected = EccTestData.GetNistP256ReferenceKey(); + EccTestBase.AssertEqual(expected, ecParameters); + } } [Fact] public void ImportFromEncryptedPem_Pkcs8_Byte_Simple() { - string pem = @" + using (TAlg key = CreateKey()) + { + string pem = @" -----BEGIN ENCRYPTED PRIVATE KEY----- MIHsMFcGCSqGSIb3DQEFDTBKMCkGCSqGSIb3DQEFDDAcBAgf9krO2ZiPvAICCAAw DAYIKoZIhvcNAgkFADAdBglghkgBZQMEAQIEEEv4Re1ATH9lHzx+13GoZU0EgZAV @@ -189,18 +211,20 @@ public void ImportFromEncryptedPem_Pkcs8_Byte_Simple() /OMt/tWvtMSj17+dJvShsu/NYJXF5fsfpSJbd3e50Y3AisW0Ob7mmF54KBfg6Y+4 aATwwQdUIKVzUZsQctsHPjbriQKKn7GKSyUOikBUNQ+TozojX8/g7JAsl+T9jGM= -----END ENCRYPTED PRIVATE KEY-----"; - using TAlg key = CreateKey(); - byte[] passwordBytes = Encoding.UTF8.GetBytes("test"); - key.ImportFromEncryptedPem(pem, passwordBytes); - ECParameters ecParameters = ExportParameters(key, true); - ECParameters expected = EccTestData.GetNistP256ReferenceKey(); - EccTestBase.AssertEqual(expected, ecParameters); + byte[] passwordBytes = Encoding.UTF8.GetBytes("test"); + key.ImportFromEncryptedPem(pem, passwordBytes); + ECParameters ecParameters = ExportParameters(key, true); + ECParameters expected = EccTestData.GetNistP256ReferenceKey(); + EccTestBase.AssertEqual(expected, ecParameters); + } } [Fact] public void ImportFromEncryptedPem_AmbiguousPem_Byte() { - string pem = @" + using (TAlg key = CreateKey()) + { + string pem = @" -----BEGIN ENCRYPTED PRIVATE KEY----- MIHsMFcGCSqGSIb3DQEFDTBKMCkGCSqGSIb3DQEFDDAcBAgf9krO2ZiPvAICCAAw DAYIKoZIhvcNAgkFADAdBglghkgBZQMEAQIEEEv4Re1ATH9lHzx+13GoZU0EgZAV @@ -215,17 +239,19 @@ public void ImportFromEncryptedPem_AmbiguousPem_Byte() opSAJ/pvHONL5kyAJLeNyG9c/mR2qyrP2L9gL0Z5fB9NyPejKTLi0PXMGQWdDTH8 Qh0fqdrNovgFLubbJFMQN/MwwIAfIuf0Mn0WFYYeQiBJ3kg= -----END ENCRYPTED PRIVATE KEY-----"; - using TAlg key = CreateKey(); - byte[] passwordBytes = Encoding.UTF8.GetBytes("test"); + byte[] passwordBytes = Encoding.UTF8.GetBytes("test"); - AssertExtensions.Throws("input", () => - key.ImportFromEncryptedPem(pem, passwordBytes)); + AssertExtensions.Throws("input", () => + key.ImportFromEncryptedPem(pem, passwordBytes)); + } } [Fact] public void ImportFromEncryptedPem_AmbiguousPem_Char() { - string pem = @" + using (TAlg key = CreateKey()) + { + string pem = @" -----BEGIN ENCRYPTED PRIVATE KEY----- MIHsMFcGCSqGSIb3DQEFDTBKMCkGCSqGSIb3DQEFDDAcBAgf9krO2ZiPvAICCAAw DAYIKoZIhvcNAgkFADAdBglghkgBZQMEAQIEEEv4Re1ATH9lHzx+13GoZU0EgZAV @@ -240,16 +266,18 @@ public void ImportFromEncryptedPem_AmbiguousPem_Char() opSAJ/pvHONL5kyAJLeNyG9c/mR2qyrP2L9gL0Z5fB9NyPejKTLi0PXMGQWdDTH8 Qh0fqdrNovgFLubbJFMQN/MwwIAfIuf0Mn0WFYYeQiBJ3kg= -----END ENCRYPTED PRIVATE KEY-----"; - using TAlg key = CreateKey(); - AssertExtensions.Throws("input", () => - key.ImportFromEncryptedPem(pem, "")); + AssertExtensions.Throws("input", () => + key.ImportFromEncryptedPem(pem, "")); + } } [Fact] public void ImportFromEncryptedPem_NoPem() { - using TAlg key = CreateKey(); - AssertExtensions.Throws("input", () => key.ImportFromEncryptedPem("", "")); + using(TAlg key = CreateKey()) + { + AssertExtensions.Throws("input", () => key.ImportFromEncryptedPem("", "")); + } } } } From 102ffe32d1b1af48587c1c5c7e24fc937c666be8 Mon Sep 17 00:00:00 2001 From: Kevin Jones Date: Mon, 6 Apr 2020 13:07:58 -0400 Subject: [PATCH 11/18] Braced usings. --- .../RSA/RSAKeyPemTests.cs | 191 ++++++++++-------- 1 file changed, 112 insertions(+), 79 deletions(-) diff --git a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/RSA/RSAKeyPemTests.cs b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/RSA/RSAKeyPemTests.cs index 7a18f1dc3f30a..1268af7642589 100644 --- a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/RSA/RSAKeyPemTests.cs +++ b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/RSA/RSAKeyPemTests.cs @@ -13,15 +13,19 @@ public static class RSAKeyPemTests [Fact] public static void ImportFromPem_NoPem() { - string pem = @"these aren't the PEMs you're looking for"; - using RSA rsa = RSAFactory.Create(); - AssertExtensions.Throws("input", () => rsa.ImportFromPem(pem)); + using (RSA rsa = RSAFactory.Create()) + { + string pem = @"these aren't the PEMs you're looking for"; + AssertExtensions.Throws("input", () => rsa.ImportFromPem(pem)); + } } [Fact] public static void ImportFromPem_RSAPrivateKey_Simple() { - string pem = @" + using (RSA rsa = RSAFactory.Create()) + { + string pem = @" -----BEGIN RSA PRIVATE KEY----- MIIBOwIBAAJBALc/WfXui9VeJLf/AprRaoVDyW0lPlQxm5NTLEHDwUd7idstLzPX uah0WEjgao5oO1BEUR4byjYlJ+F89Cs4BhUCAwEAAQJBAK/m8jYvnK9exaSR+DAh @@ -32,17 +36,19 @@ public static void ImportFromPem_RSAPrivateKey_Simple() yZWUxoxAdjfrBGsx+U6BHM0Myqqe7fY7hjWzj4aBCw== -----END RSA PRIVATE KEY-----"; - using RSA rsa = RSAFactory.Create(); - rsa.ImportFromPem(pem); - RSAParameters rsaParameters = rsa.ExportParameters(true); + rsa.ImportFromPem(pem); + RSAParameters rsaParameters = rsa.ExportParameters(true); - ImportExport.AssertKeyEquals(TestData.DiminishedDPParameters, rsaParameters); + ImportExport.AssertKeyEquals(TestData.DiminishedDPParameters, rsaParameters); + } } [Fact] public static void ImportFromPem_Pkcs8UnEncrypted_Simple() { - string pem = @" + using (RSA rsa = RSAFactory.Create()) + { + string pem = @" -----BEGIN PRIVATE KEY----- MIIBVQIBADANBgkqhkiG9w0BAQEFAASCAT8wggE7AgEAAkEAtz9Z9e6L1V4kt/8C mtFqhUPJbSU+VDGbk1MsQcPBR3uJ2y0vM9e5qHRYSOBqjmg7UERRHhvKNiUn4Xz0 @@ -54,49 +60,55 @@ public static void ImportFromPem_Pkcs8UnEncrypted_Simple() 9juGNbOPhoEL -----END PRIVATE KEY-----"; - using RSA rsa = RSAFactory.Create(); - rsa.ImportFromPem(pem); - RSAParameters rsaParameters = rsa.ExportParameters(true); + rsa.ImportFromPem(pem); + RSAParameters rsaParameters = rsa.ExportParameters(true); - ImportExport.AssertKeyEquals(TestData.DiminishedDPParameters, rsaParameters); + ImportExport.AssertKeyEquals(TestData.DiminishedDPParameters, rsaParameters); + } } [Fact] public static void ImportFromPem_SubjectPublicKeyInfo_Simple() { - string pem = @" + using (RSA rsa = RSAFactory.Create()) + { + string pem = @" -----BEGIN PUBLIC KEY----- MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBALc/WfXui9VeJLf/AprRaoVDyW0lPlQx m5NTLEHDwUd7idstLzPXuah0WEjgao5oO1BEUR4byjYlJ+F89Cs4BhUCAwEAAQ== -----END PUBLIC KEY-----"; - using RSA rsa = RSAFactory.Create(); - rsa.ImportFromPem(pem); - RSAParameters rsaParameters = rsa.ExportParameters(false); + rsa.ImportFromPem(pem); + RSAParameters rsaParameters = rsa.ExportParameters(false); - ImportExport.AssertKeyEquals(TestData.DiminishedDPParameters.ToPublic(), rsaParameters); + ImportExport.AssertKeyEquals(TestData.DiminishedDPParameters.ToPublic(), rsaParameters); + } } [Fact] public static void ImportFromPem_RSAPublicKey_Simple() { - string pem = @" + using (RSA rsa = RSAFactory.Create()) + { + string pem = @" -----BEGIN RSA PUBLIC KEY----- MEgCQQC3P1n17ovVXiS3/wKa0WqFQ8ltJT5UMZuTUyxBw8FHe4nbLS8z17modFhI 4GqOaDtQRFEeG8o2JSfhfPQrOAYVAgMBAAE= -----END RSA PUBLIC KEY-----"; - using RSA rsa = RSAFactory.Create(); - rsa.ImportFromPem(pem); - RSAParameters rsaParameters = rsa.ExportParameters(false); + rsa.ImportFromPem(pem); + RSAParameters rsaParameters = rsa.ExportParameters(false); - ImportExport.AssertKeyEquals(TestData.DiminishedDPParameters.ToPublic(), rsaParameters); + ImportExport.AssertKeyEquals(TestData.DiminishedDPParameters.ToPublic(), rsaParameters); + } } [Fact] public static void ImportFromPem_RSAPrivateKey_PrecedingUnrelatedPem() { - string pem = @" + using (RSA rsa = RSAFactory.Create()) + { + string pem = @" -----BEGIN CERTIFICATE----- MIICTzCCAgmgAwIBAgIJAMQtYhFJ0+5jMA0GCSqGSIb3DQEBBQUAMIGSMQswCQYD VQQGEwJVUzETMBEGA1UECAwKV2FzaGluZ3RvbjEQMA4GA1UEBwwHUmVkbW9uZDEY @@ -121,17 +133,19 @@ public static void ImportFromPem_RSAPrivateKey_PrecedingUnrelatedPem() rmaUzxQvyuVLAiEArCTM8dSbopUADWnD4jArhU50UhWAIaM6ZrKqC8k0RKsCIQDC yZWUxoxAdjfrBGsx+U6BHM0Myqqe7fY7hjWzj4aBCw== -----END RSA PRIVATE KEY-----"; - using RSA rsa = RSAFactory.Create(); - rsa.ImportFromPem(pem); - RSAParameters rsaParameters = rsa.ExportParameters(true); + rsa.ImportFromPem(pem); + RSAParameters rsaParameters = rsa.ExportParameters(true); - ImportExport.AssertKeyEquals(TestData.DiminishedDPParameters, rsaParameters); + ImportExport.AssertKeyEquals(TestData.DiminishedDPParameters, rsaParameters); + } } [Fact] public static void ImportFromPem_RSAPrivateKey_PrecedingMalformedPem() { - string pem = @" + using (RSA rsa = RSAFactory.Create()) + { + string pem = @" -----BEGIN CERTIFICATE----- $$ I AM NOT A PEM -----END CERTIFICATE----- @@ -144,17 +158,19 @@ public static void ImportFromPem_RSAPrivateKey_PrecedingMalformedPem() rmaUzxQvyuVLAiEArCTM8dSbopUADWnD4jArhU50UhWAIaM6ZrKqC8k0RKsCIQDC yZWUxoxAdjfrBGsx+U6BHM0Myqqe7fY7hjWzj4aBCw== -----END RSA PRIVATE KEY-----"; - using RSA rsa = RSAFactory.Create(); - rsa.ImportFromPem(pem); - RSAParameters rsaParameters = rsa.ExportParameters(true); + rsa.ImportFromPem(pem); + RSAParameters rsaParameters = rsa.ExportParameters(true); - ImportExport.AssertKeyEquals(TestData.DiminishedDPParameters, rsaParameters); + ImportExport.AssertKeyEquals(TestData.DiminishedDPParameters, rsaParameters); + } } [Fact] public static void ImportFromPem_RSAPrivateKey_AmbiguousKey_RSAPrivateKey() { - string pem = @" + using (RSA rsa = RSAFactory.Create()) + { + string pem = @" -----BEGIN RSA PRIVATE KEY----- MII= -----END RSA PRIVATE KEY----- @@ -167,14 +183,16 @@ public static void ImportFromPem_RSAPrivateKey_AmbiguousKey_RSAPrivateKey() rmaUzxQvyuVLAiEArCTM8dSbopUADWnD4jArhU50UhWAIaM6ZrKqC8k0RKsCIQDC yZWUxoxAdjfrBGsx+U6BHM0Myqqe7fY7hjWzj4aBCw== -----END RSA PRIVATE KEY-----"; - using RSA rsa = RSAFactory.Create(); - AssertExtensions.Throws("input", () => rsa.ImportFromPem(pem)); + AssertExtensions.Throws("input", () => rsa.ImportFromPem(pem)); + } } [Fact] public static void ImportFromPem_RSAPrivateKey_AmbiguousKey_SubjectPublicKeyInfo() { - string pem = @" + using (RSA rsa = RSAFactory.Create()) + { + string pem = @" -----BEGIN PUBLIC KEY----- MII= -----END PUBLIC KEY----- @@ -187,14 +205,16 @@ public static void ImportFromPem_RSAPrivateKey_AmbiguousKey_SubjectPublicKeyInfo rmaUzxQvyuVLAiEArCTM8dSbopUADWnD4jArhU50UhWAIaM6ZrKqC8k0RKsCIQDC yZWUxoxAdjfrBGsx+U6BHM0Myqqe7fY7hjWzj4aBCw== -----END RSA PRIVATE KEY-----"; - using RSA rsa = RSAFactory.Create(); - AssertExtensions.Throws("input", () => rsa.ImportFromPem(pem)); + AssertExtensions.Throws("input", () => rsa.ImportFromPem(pem)); + } } [Fact] public static void ImportFromPem_RSAPrivateKey_AmbiguousKey_RSAPublicKey() { - string pem = @" + using (RSA rsa = RSAFactory.Create()) + { + string pem = @" -----BEGIN RSA PUBLIC KEY----- MII= -----END RSA PUBLIC KEY----- @@ -207,14 +227,16 @@ public static void ImportFromPem_RSAPrivateKey_AmbiguousKey_RSAPublicKey() rmaUzxQvyuVLAiEArCTM8dSbopUADWnD4jArhU50UhWAIaM6ZrKqC8k0RKsCIQDC yZWUxoxAdjfrBGsx+U6BHM0Myqqe7fY7hjWzj4aBCw== -----END RSA PRIVATE KEY-----"; - using RSA rsa = RSAFactory.Create(); - AssertExtensions.Throws("input", () => rsa.ImportFromPem(pem)); + AssertExtensions.Throws("input", () => rsa.ImportFromPem(pem)); + } } [Fact] public static void ImportFromPem_RSAPrivateKey_AmbiguousKey_EncryptedPkcs8() { - string pem = @" + using (RSA rsa = RSAFactory.Create()) + { + string pem = @" -----BEGIN ENCRYPTED PRIVATE KEY----- MII= -----END ENCRYPTED PRIVATE KEY----- @@ -227,14 +249,16 @@ public static void ImportFromPem_RSAPrivateKey_AmbiguousKey_EncryptedPkcs8() rmaUzxQvyuVLAiEArCTM8dSbopUADWnD4jArhU50UhWAIaM6ZrKqC8k0RKsCIQDC yZWUxoxAdjfrBGsx+U6BHM0Myqqe7fY7hjWzj4aBCw== -----END RSA PRIVATE KEY-----"; - using RSA rsa = RSAFactory.Create(); - AssertExtensions.Throws("input", () => rsa.ImportFromPem(pem)); + AssertExtensions.Throws("input", () => rsa.ImportFromPem(pem)); + } } [Fact] public static void ImportFromPem_EncryptedPrivateKeyFails() { - string pem = @" + using (RSA rsa = RSAFactory.Create()) + { + string pem = @" -----BEGIN ENCRYPTED PRIVATE KEY----- MIIBsTBLBgkqhkiG9w0BBQ0wPjApBgkqhkiG9w0BBQwwHAQIioaQaFwlfasCAggA MAwGCCqGSIb3DQIJBQAwEQYFKw4DAgcECJLGzSuIgnSkBIIBYHofFpp5AsrkNc9w @@ -247,14 +271,16 @@ public static void ImportFromPem_EncryptedPrivateKeyFails() RkMxT/C7OZVMOlb3HV3fJj7kDmOMqfc6aKEQjLdWtuYRB8CgaudldIpK4jP2+0b5 pBORBb0= -----END ENCRYPTED PRIVATE KEY-----"; - using RSA rsa = RSAFactory.Create(); - AssertExtensions.Throws("input", () => rsa.ImportFromPem(pem)); + AssertExtensions.Throws("input", () => rsa.ImportFromPem(pem)); + } } [Fact] public static void ImportFromPem_Pkcs8AlgorithmMismatch_Throws() { - string pem = @" + using (RSA rsa = RSAFactory.Create()) + { + string pem = @" The below PEM is a 1024-bit DSA key. -----BEGIN PRIVATE KEY----- MIIBSgIBADCCASsGByqGSM44BAEwggEeAoGBAL5KGXEaazCA+k1pMcCBc/+bodFh @@ -265,14 +291,16 @@ The below PEM is a 1024-bit DSA key. eDr38gQ/Hk0CgW3/RFrNWdbIpfMifs80vqCUNqDggcQixEmDVZ0gwq4+wz8EVyYG 42+vM7ajN4O2VGvCA99Vl6zv69hOpAQWAhQtFFLZyKAUOQwUQh4hNw+oBgPhFw== -----END PRIVATE KEY-----"; - using RSA rsa = RSAFactory.Create(); - Assert.Throws(() => rsa.ImportFromPem(pem)); + Assert.Throws(() => rsa.ImportFromPem(pem)); + } } [Fact] public static void ImportFromEncryptedPem_Pkcs8Encrypted_Char_Simple() { - string pem = @" + using (RSA rsa = RSAFactory.Create()) + { + string pem = @" -----BEGIN ENCRYPTED PRIVATE KEY----- MIIBsTBLBgkqhkiG9w0BBQ0wPjApBgkqhkiG9w0BBQwwHAQIcvgI1lw9LqYCAggA MAwGCCqGSIb3DQIJBQAwEQYFKw4DAgcECFDpLREQXt5pBIIBYOKuM5ljAvCViDL+ @@ -285,18 +313,19 @@ public static void ImportFromEncryptedPem_Pkcs8Encrypted_Char_Simple() N4lD7/hJq7b+yYPhlN3Fvvt8M9MtRg1TLAve67CA2v4TITHB06M/ELe3y42bZuLW CA7ffFk= -----END ENCRYPTED PRIVATE KEY-----"; + rsa.ImportFromEncryptedPem(pem, "test"); + RSAParameters rsaParameters = rsa.ExportParameters(true); - using RSA rsa = RSAFactory.Create(); - rsa.ImportFromEncryptedPem(pem, "test"); - RSAParameters rsaParameters = rsa.ExportParameters(true); - - ImportExport.AssertKeyEquals(TestData.DiminishedDPParameters, rsaParameters); + ImportExport.AssertKeyEquals(TestData.DiminishedDPParameters, rsaParameters); + } } [Fact] public static void ImportFromEncryptedPem_Pkcs8Encrypted_Byte_Simple() { - string pem = @" + using (RSA rsa = RSAFactory.Create()) + { + string pem = @" -----BEGIN ENCRYPTED PRIVATE KEY----- MIIBvTBXBgkqhkiG9w0BBQ0wSjApBgkqhkiG9w0BBQwwHAQIciLWmWb33X0CAggA MAwGCCqGSIb3DQIJBQAwHQYJYIZIAWUDBAECBBBVEmHhJdbi+HKzPttNjXm4BIIB @@ -309,18 +338,19 @@ public static void ImportFromEncryptedPem_Pkcs8Encrypted_Byte_Simple() 5QSEe7EKVF0aHXBYB5SzMGVuxR/BqydDa26jlhVzO3LNvy9FYuqLKUslCrBCmPrt raZNyk8KAsLs+FJq9T2tda0= -----END ENCRYPTED PRIVATE KEY-----"; + rsa.ImportFromEncryptedPem(pem, Encoding.UTF8.GetBytes("test")); + RSAParameters rsaParameters = rsa.ExportParameters(true); - using RSA rsa = RSAFactory.Create(); - rsa.ImportFromEncryptedPem(pem, Encoding.UTF8.GetBytes("test")); - RSAParameters rsaParameters = rsa.ExportParameters(true); - - ImportExport.AssertKeyEquals(TestData.DiminishedDPParameters, rsaParameters); + ImportExport.AssertKeyEquals(TestData.DiminishedDPParameters, rsaParameters); + } } [Fact] public static void ImportFromEncryptedPem_Pkcs8Encrypted_AmbiguousPem() { - string pem = @" + using (RSA rsa = RSAFactory.Create()) + { + string pem = @" -----BEGIN ENCRYPTED PRIVATE KEY----- MIIBvTBXBgkqhkiG9w0BBQ0wSjApBgkqhkiG9w0BBQwwHAQIciLWmWb33X0CAggA MAwGCCqGSIb3DQIJBQAwHQYJYIZIAWUDBAECBBBVEmHhJdbi+HKzPttNjXm4BIIB @@ -345,31 +375,34 @@ public static void ImportFromEncryptedPem_Pkcs8Encrypted_AmbiguousPem() N4lD7/hJq7b+yYPhlN3Fvvt8M9MtRg1TLAve67CA2v4TITHB06M/ELe3y42bZuLW CA7ffFk= -----END ENCRYPTED PRIVATE KEY-----"; - - using RSA rsa = RSAFactory.Create(); - byte[] passwordBytes = Encoding.UTF8.GetBytes("test"); - AssertExtensions.Throws("input", () => - rsa.ImportFromEncryptedPem(pem, passwordBytes)); + byte[] passwordBytes = Encoding.UTF8.GetBytes("test"); + AssertExtensions.Throws("input", () => + rsa.ImportFromEncryptedPem(pem, passwordBytes)); + } } [Fact] public static void ImportFromEncryptedPem_Pkcs8Encrypted_Byte_NoPem() { - string pem = "these aren't the PEMs we're looking for."; - using RSA rsa = RSAFactory.Create(); - byte[] passwordBytes = Encoding.UTF8.GetBytes("test"); - AssertExtensions.Throws("input", () => - rsa.ImportFromEncryptedPem(pem, passwordBytes)); + using (RSA rsa = RSAFactory.Create()) + { + string pem = "these aren't the PEMs we're looking for."; + byte[] passwordBytes = Encoding.UTF8.GetBytes("test"); + AssertExtensions.Throws("input", () => + rsa.ImportFromEncryptedPem(pem, passwordBytes)); + } } [Fact] public static void ImportFromEncryptedPem_Pkcs8Encrypted_Char_NoPem() { - string pem = "go about your business"; - using RSA rsa = RSAFactory.Create(); - string password = "test"; - AssertExtensions.Throws("input", () => - rsa.ImportFromEncryptedPem(pem, password)); + using (RSA rsa = RSAFactory.Create()) + { + string pem = "go about your business"; + string password = "test"; + AssertExtensions.Throws("input", () => + rsa.ImportFromEncryptedPem(pem, password)); + } } private static RSAParameters ToPublic(this RSAParameters rsaParams) From 06b2c936defeaf204071eca97fa8e4c8adda6432 Mon Sep 17 00:00:00 2001 From: Kevin Jones Date: Mon, 6 Apr 2020 13:12:34 -0400 Subject: [PATCH 12/18] Braced usings. --- .../DSA/DSAKeyPemTests.cs | 162 ++++++++++-------- 1 file changed, 90 insertions(+), 72 deletions(-) diff --git a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/DSA/DSAKeyPemTests.cs b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/DSA/DSAKeyPemTests.cs index dafcb87250671..c7cbed28652e4 100644 --- a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/DSA/DSAKeyPemTests.cs +++ b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/DSA/DSAKeyPemTests.cs @@ -13,15 +13,19 @@ public static class DSAKeyPemTests [Fact] public static void ImportFromPem_NoPem() { - string pem = "pem? what pem? there is no pem here."; - using DSA dsa = DSAFactory.Create(); - AssertExtensions.Throws("input", () => dsa.ImportFromPem(pem)); + using (DSA dsa = DSAFactory.Create()) + { + string pem = "pem? what pem? there is no pem here."; + AssertExtensions.Throws("input", () => dsa.ImportFromPem(pem)); + } } [Fact] public static void ImportFromPem_Pkcs8UnEncrypted_Simple() { - string pem = @" + using (DSA dsa = DSAFactory.Create()) + { + string pem = @" -----BEGIN PRIVATE KEY----- MIHGAgEAMIGoBgcqhkjOOAQBMIGcAkEA1qi38cr3ppZNB2Y/xpHSL2q81Vw3rvWN IHRnQNgv4U4UY2NifZGSUULc3uOEvgoeBO1b9fRxSG9NmG1CoufflQIVAPq19iXV @@ -29,18 +33,19 @@ public static void ImportFromPem_Pkcs8UnEncrypted_Simple() fve77OGaTv4qbZwinTYAg86p9yHzmwW6+XBS3vxnpYorBBYCFC49eoTIW2Z4Xh9v 55aYKyKwy5i8 -----END PRIVATE KEY-----"; + dsa.ImportFromPem(pem); + DSAParameters dsaParameters = dsa.ExportParameters(true); - using DSA dsa = DSAFactory.Create(); - dsa.ImportFromPem(pem); - DSAParameters dsaParameters = dsa.ExportParameters(true); - - DSAImportExport.AssertKeyEquals(DSATestData.Dsa512Parameters, dsaParameters); + DSAImportExport.AssertKeyEquals(DSATestData.Dsa512Parameters, dsaParameters); + } } [Fact] public static void ImportFromPem_Pkcs8_UnrelatedPrecedingPem() { - string pem = @" + using (DSA dsa = DSAFactory.Create()) + { + string pem = @" -----BEGIN CERTIFICATE----- MII= -----END CERTIFICATE----- @@ -51,18 +56,19 @@ public static void ImportFromPem_Pkcs8_UnrelatedPrecedingPem() fve77OGaTv4qbZwinTYAg86p9yHzmwW6+XBS3vxnpYorBBYCFC49eoTIW2Z4Xh9v 55aYKyKwy5i8 -----END PRIVATE KEY-----"; + dsa.ImportFromPem(pem); + DSAParameters dsaParameters = dsa.ExportParameters(true); - using DSA dsa = DSAFactory.Create(); - dsa.ImportFromPem(pem); - DSAParameters dsaParameters = dsa.ExportParameters(true); - - DSAImportExport.AssertKeyEquals(DSATestData.Dsa512Parameters, dsaParameters); + DSAImportExport.AssertKeyEquals(DSATestData.Dsa512Parameters, dsaParameters); + } } [Fact] public static void ImportFromPem_Pkcs8_PrecedingMalformedPem() { - string pem = @" + using (DSA dsa = DSAFactory.Create()) + { + string pem = @" -----BEGIN CERTIFICATE----- $$$ BAD PEM -----END CERTIFICATE----- @@ -73,18 +79,19 @@ public static void ImportFromPem_Pkcs8_PrecedingMalformedPem() fve77OGaTv4qbZwinTYAg86p9yHzmwW6+XBS3vxnpYorBBYCFC49eoTIW2Z4Xh9v 55aYKyKwy5i8 -----END PRIVATE KEY-----"; + dsa.ImportFromPem(pem); + DSAParameters dsaParameters = dsa.ExportParameters(true); - using DSA dsa = DSAFactory.Create(); - dsa.ImportFromPem(pem); - DSAParameters dsaParameters = dsa.ExportParameters(true); - - DSAImportExport.AssertKeyEquals(DSATestData.Dsa512Parameters, dsaParameters); + DSAImportExport.AssertKeyEquals(DSATestData.Dsa512Parameters, dsaParameters); + } } [Fact] public static void ImportFromPem_SubjectPublicKeyInfo_Simple() { - string pem = @" + using (DSA dsa = DSAFactory.Create()) + { + string pem = @" -----BEGIN PUBLIC KEY----- MIHxMIGoBgcqhkjOOAQBMIGcAkEA1qi38cr3ppZNB2Y/xpHSL2q81Vw3rvWNIHRn QNgv4U4UY2NifZGSUULc3uOEvgoeBO1b9fRxSG9NmG1CoufflQIVAPq19iXV1eFk @@ -93,18 +100,19 @@ public static void ImportFromPem_SubjectPublicKeyInfo_Simple() qsHywr1WjmoyRnIn4Stq5FqNlHhUGkgKyAA4qshjgn1uOYQGGiWQXBi9JJmoOWY8 PKRWBQ== -----END PUBLIC KEY-----"; + dsa.ImportFromPem(pem); + DSAParameters dsaParameters = dsa.ExportParameters(false); - using DSA dsa = DSAFactory.Create(); - dsa.ImportFromPem(pem); - DSAParameters dsaParameters = dsa.ExportParameters(false); - - DSAImportExport.AssertKeyEquals(DSATestData.Dsa512Parameters.ToPublic(), dsaParameters); + DSAImportExport.AssertKeyEquals(DSATestData.Dsa512Parameters.ToPublic(), dsaParameters); + } } [Fact] public static void ImportFromPem_Pkcs8_AmbiguousKey_Pkcs8() { - string pem = @" + using (DSA dsa = DSAFactory.Create()) + { + string pem = @" -----BEGIN PRIVATE KEY----- MIHGAgEAMIGoBgcqhkjOOAQBMIGcAkEA1qi38cr3ppZNB2Y/xpHSL2q81Vw3rvWN IHRnQNgv4U4UY2NifZGSUULc3uOEvgoeBO1b9fRxSG9NmG1CoufflQIVAPq19iXV @@ -119,15 +127,16 @@ public static void ImportFromPem_Pkcs8_AmbiguousKey_Pkcs8() fve77OGaTv4qbZwinTYAg86p9yHzmwW6+XBS3vxnpYorBBYCFC49eoTIW2Z4Xh9v 55aYKyKwy5i8 -----END PRIVATE KEY-----"; - - using DSA dsa = DSAFactory.Create(); - AssertExtensions.Throws("input", () => dsa.ImportFromPem(pem)); + AssertExtensions.Throws("input", () => dsa.ImportFromPem(pem)); + } } [Fact] public static void ImportFromPem_Pkcs8_AmbiguousKey_Spki() { - string pem = @" + using (DSA dsa = DSAFactory.Create()) + { + string pem = @" -----BEGIN PUBLIC KEY----- MIHxMIGoBgcqhkjOOAQBMIGcAkEA1qi38cr3ppZNB2Y/xpHSL2q81Vw3rvWNIHRn QNgv4U4UY2NifZGSUULc3uOEvgoeBO1b9fRxSG9NmG1CoufflQIVAPq19iXV1eFk @@ -143,15 +152,16 @@ public static void ImportFromPem_Pkcs8_AmbiguousKey_Spki() fve77OGaTv4qbZwinTYAg86p9yHzmwW6+XBS3vxnpYorBBYCFC49eoTIW2Z4Xh9v 55aYKyKwy5i8 -----END PRIVATE KEY-----"; - - using DSA dsa = DSAFactory.Create(); - AssertExtensions.Throws("input", () => dsa.ImportFromPem(pem)); + AssertExtensions.Throws("input", () => dsa.ImportFromPem(pem)); + } } [Fact] public static void ImportFromPem_Pkcs8_AmbiguousKey_EncryptedPkcs8() { - string pem = @" + using (DSA dsa = DSAFactory.Create()) + { + string pem = @" -----BEGIN ENCRYPTED PRIVATE KEY----- MIIBIDBLBgkqhkiG9w0BBQ0wPjApBgkqhkiG9w0BBQwwHAQIkM/kCKe6rYsCAggA MAwGCCqGSIb3DQIJBQAwEQYFKw4DAgcECBOccveL65bDBIHQiCcCqwxJs93g1+16 @@ -168,15 +178,16 @@ public static void ImportFromPem_Pkcs8_AmbiguousKey_EncryptedPkcs8() fve77OGaTv4qbZwinTYAg86p9yHzmwW6+XBS3vxnpYorBBYCFC49eoTIW2Z4Xh9v 55aYKyKwy5i8 -----END PRIVATE KEY-----"; - - using DSA dsa = DSAFactory.Create(); - AssertExtensions.Throws("input", () => dsa.ImportFromPem(pem)); + AssertExtensions.Throws("input", () => dsa.ImportFromPem(pem)); + } } [Fact] public static void ImportFromPem_EncryptedPrivateKeyFails() { - string pem = @" + using (DSA dsa = DSAFactory.Create()) + { + string pem = @" -----BEGIN ENCRYPTED PRIVATE KEY----- MIIBIDBLBgkqhkiG9w0BBQ0wPjApBgkqhkiG9w0BBQwwHAQIkM/kCKe6rYsCAggA MAwGCCqGSIb3DQIJBQAwEQYFKw4DAgcECBOccveL65bDBIHQiCcCqwxJs93g1+16 @@ -186,29 +197,31 @@ public static void ImportFromPem_EncryptedPrivateKeyFails() dVYwfovccu8ktEAwk5XAOo0r+5CCw2lDDw/hbDeO87BToC5Cc5nu3F5LxAUj8Flc v8pi3w== -----END ENCRYPTED PRIVATE KEY-----"; - - using DSA dsa = DSAFactory.Create(); - AssertExtensions.Throws("input", () => dsa.ImportFromPem(pem)); + AssertExtensions.Throws("input", () => dsa.ImportFromPem(pem)); + } } [Fact] public static void ImportFromPem_SpkiAlgorithmMismatch_Throws() { - string pem = @" + using (DSA dsa = DSAFactory.Create()) + { + string pem = @" The below key is for an RSA SPKI -----BEGIN PUBLIC KEY----- MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBALc/WfXui9VeJLf/AprRaoVDyW0lPlQx m5NTLEHDwUd7idstLzPXuah0WEjgao5oO1BEUR4byjYlJ+F89Cs4BhUCAwEAAQ== -----END PUBLIC KEY-----"; - - using DSA dsa = DSAFactory.Create(); - Assert.Throws(() => dsa.ImportFromPem(pem)); + Assert.Throws(() => dsa.ImportFromPem(pem)); + } } [Fact] public static void ImportFromEncryptedPem_Pkcs8_Encrypted_Char_Simple() { - string pem = @" + using (DSA dsa = DSAFactory.Create()) + { + string pem = @" -----BEGIN ENCRYPTED PRIVATE KEY----- MIIBIDBLBgkqhkiG9w0BBQ0wPjApBgkqhkiG9w0BBQwwHAQIkM/kCKe6rYsCAggA MAwGCCqGSIb3DQIJBQAwEQYFKw4DAgcECBOccveL65bDBIHQiCcCqwxJs93g1+16 @@ -218,18 +231,19 @@ public static void ImportFromEncryptedPem_Pkcs8_Encrypted_Char_Simple() dVYwfovccu8ktEAwk5XAOo0r+5CCw2lDDw/hbDeO87BToC5Cc5nu3F5LxAUj8Flc v8pi3w== -----END ENCRYPTED PRIVATE KEY-----"; + dsa.ImportFromEncryptedPem(pem, "test"); + DSAParameters dsaParameters = dsa.ExportParameters(true); - using DSA dsa = DSAFactory.Create(); - dsa.ImportFromEncryptedPem(pem, "test"); - DSAParameters dsaParameters = dsa.ExportParameters(true); - - DSAImportExport.AssertKeyEquals(DSATestData.Dsa512Parameters, dsaParameters); + DSAImportExport.AssertKeyEquals(DSATestData.Dsa512Parameters, dsaParameters); + } } [Fact] public static void ImportFromEncryptedPem_Pkcs8_Encrypted_Byte_Simple() { - string pem = @" + using (DSA dsa = DSAFactory.Create()) + { + string pem = @" -----BEGIN ENCRYPTED PRIVATE KEY----- MIIBLDBXBgkqhkiG9w0BBQ0wSjApBgkqhkiG9w0BBQwwHAQIfcoipdEY/C4CAggA MAwGCCqGSIb3DQIJBQAwHQYJYIZIAWUDBAECBBC9heEphj00fB89aP6chSOjBIHQ @@ -239,19 +253,20 @@ public static void ImportFromEncryptedPem_Pkcs8_Encrypted_Byte_Simple() xTL6VO9mx52x6h5WDAQAisMVeMkBoxQUWLANXiw1zSfVbsmB7mDknsRcvD3tcgMs 7YLD7LQMiPAIjDlOP8XP/w== -----END ENCRYPTED PRIVATE KEY-----"; + byte[] passwordBytes = Encoding.UTF8.GetBytes("test"); + dsa.ImportFromEncryptedPem(pem, passwordBytes); + DSAParameters dsaParameters = dsa.ExportParameters(true); - using DSA dsa = DSAFactory.Create(); - byte[] passwordBytes = Encoding.UTF8.GetBytes("test"); - dsa.ImportFromEncryptedPem(pem, passwordBytes); - DSAParameters dsaParameters = dsa.ExportParameters(true); - - DSAImportExport.AssertKeyEquals(DSATestData.Dsa512Parameters, dsaParameters); + DSAImportExport.AssertKeyEquals(DSATestData.Dsa512Parameters, dsaParameters); + } } [Fact] public static void ImportFromEncryptedPem_Pkcs8_Encrypted_AmbiguousPem() { - string pem = @" + using (DSA dsa = DSAFactory.Create()) + { + string pem = @" -----BEGIN ENCRYPTED PRIVATE KEY----- MIIBLDBXBgkqhkiG9w0BBQ0wSjApBgkqhkiG9w0BBQwwHAQIfcoipdEY/C4CAggA MAwGCCqGSIb3DQIJBQAwHQYJYIZIAWUDBAECBBC9heEphj00fB89aP6chSOjBIHQ @@ -270,27 +285,30 @@ public static void ImportFromEncryptedPem_Pkcs8_Encrypted_AmbiguousPem() dVYwfovccu8ktEAwk5XAOo0r+5CCw2lDDw/hbDeO87BToC5Cc5nu3F5LxAUj8Flc v8pi3w== -----END ENCRYPTED PRIVATE KEY-----"; - - using DSA dsa = DSAFactory.Create(); - byte[] passwordBytes = Encoding.UTF8.GetBytes("test"); - AssertExtensions.Throws("input", () => dsa.ImportFromEncryptedPem(pem, passwordBytes)); + byte[] passwordBytes = Encoding.UTF8.GetBytes("test"); + AssertExtensions.Throws("input", () => dsa.ImportFromEncryptedPem(pem, passwordBytes)); + } } [Fact] public static void ImportFromEncryptedPem_Pkcs8_Byte_NoPem() { - string pem = ""; - using DSA dsa = DSAFactory.Create(); - byte[] passwordBytes = Encoding.UTF8.GetBytes("test"); - AssertExtensions.Throws("input", () => dsa.ImportFromEncryptedPem(pem, passwordBytes)); + using (DSA dsa = DSAFactory.Create()) + { + string pem = ""; + byte[] passwordBytes = Encoding.UTF8.GetBytes("test"); + AssertExtensions.Throws("input", () => dsa.ImportFromEncryptedPem(pem, passwordBytes)); + } } [Fact] public static void ImportFromEncryptedPem_Pkcs8_Char_NoPem() { - string pem = ""; - using DSA dsa = DSAFactory.Create(); - AssertExtensions.Throws("input", () => dsa.ImportFromEncryptedPem(pem, "k")); + using (DSA dsa = DSAFactory.Create()) + { + string pem = ""; + AssertExtensions.Throws("input", () => dsa.ImportFromEncryptedPem(pem, "k")); + } } private static DSAParameters ToPublic(this DSAParameters dsaParams) From 9e6284583fac87067cbd046572594272bb18d76b Mon Sep 17 00:00:00 2001 From: Kevin Jones Date: Mon, 6 Apr 2020 16:04:28 -0400 Subject: [PATCH 13/18] Clearer exception message. --- .../src/Resources/Strings.resx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/libraries/System.Security.Cryptography.Algorithms/src/Resources/Strings.resx b/src/libraries/System.Security.Cryptography.Algorithms/src/Resources/Strings.resx index cadd55c13b545..d162b5c57ddc1 100644 --- a/src/libraries/System.Security.Cryptography.Algorithms/src/Resources/Strings.resx +++ b/src/libraries/System.Security.Cryptography.Algorithms/src/Resources/Strings.resx @@ -82,13 +82,13 @@ Buffer cannot be null. - A supported key was not found. + No supported key formats were found. Check that the input represents the contents of a PEM-encoded key file, not the path to such a file. - Multiple supported keys were found. + The input contains multiple keys, but only one key can be imported. - An encrypted key was found, but attempted to import it without a password. + An encrypted key was found, but no password was provided. Use ImportFromEncryptedPem to import this key. Error occurred during a cryptographic operation. From 58dd3cb7cd9819df39e3346a547dea130122dcb6 Mon Sep 17 00:00:00 2001 From: Kevin Jones Date: Tue, 7 Apr 2020 11:02:46 -0400 Subject: [PATCH 14/18] Documentation feedback. Use para as required. raised -> thrown. Remove confusing text around BER,CER,DER. --- .../src/System/Security/Cryptography/DSA.cs | 89 ++++++++++++------- .../Security/Cryptography/ECDiffieHellman.cs | 89 ++++++++++++------- .../src/System/Security/Cryptography/ECDsa.cs | 89 ++++++++++++------- .../src/System/Security/Cryptography/RSA.cs | 89 ++++++++++++------- .../Cryptography/AsymmetricAlgorithm.cs | 6 +- 5 files changed, 239 insertions(+), 123 deletions(-) diff --git a/src/libraries/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/DSA.cs b/src/libraries/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/DSA.cs index f85834c3af7e5..71c22caff3915 100644 --- a/src/libraries/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/DSA.cs +++ b/src/libraries/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/DSA.cs @@ -1131,15 +1131,21 @@ public int GetMaxSignatureSize(DSASignatureFormat signatureFormat) /// /// The PEM text of the key to import. /// - /// does not contain a PEM-encoded key with a recognized label. - /// - /// -or- - /// - /// contains multiple PEM-encoded keys with a recognized label. - /// - /// -or- - /// - /// contains an encrypted PEM-encoded key. + /// + /// does not contain a PEM-encoded key with a recognized label. + /// + /// + /// -or- + /// + /// + /// contains multiple PEM-encoded keys with a recognized label. + /// + /// + /// -or- + /// + /// + /// contains an encrypted PEM-encoded key. + /// /// /// /// @@ -1181,45 +1187,58 @@ public override void ImportFromPem(ReadOnlySpan input) /// The password to use for decrypting the key material. /// /// - /// does not contain a PEM-encoded key with a recognized label. - /// - /// -or- - /// - /// contains multiple PEM-encoded keys with a recognized label. + /// + /// does not contain a PEM-encoded key with a recognized label. + /// + /// + /// -or- + /// + /// + /// contains multiple PEM-encoded keys with a recognized label. + /// /// /// - /// The password is incorrect. + /// + /// The password is incorrect. + /// /// /// -or- /// - /// The base-64 decoded contents of the PEM text from - /// do not represent an ASN.1-BER-encoded PKCS#8 EncryptedPrivateKeyInfo structure. + /// + /// The base-64 decoded contents of the PEM text from + /// do not represent an ASN.1-BER-encoded PKCS#8 EncryptedPrivateKeyInfo structure. + /// /// /// -or- /// + /// /// The base-64 decoded contents of the PEM text from /// indicate the key is for an algorithm other than the algorithm /// represented by this instance. + /// /// /// -or- /// + /// /// The base-64 decoded contents of the PEM text from /// represent the key in a format that is not supported. + /// /// /// -or- /// + /// /// The algorithm-specific key import failed. + /// /// /// /// /// When the base-64 decoded contents of indicate an algorithm that uses PBKDF1 /// (Password-Based Key Derivation Function 1) or PBKDF2 (Password-Based Key Derivation Function 2), - /// the password is converted to bytes via the UTF-8 encoding. This method - /// only supports the binary (BER/CER/DER) encoding of EncryptedPrivateKeyInfo. + /// the password is converted to bytes via the UTF-8 encoding. /// /// /// Unsupported or malformed PEM-encoded objects will be ignored. If multiple supported PEM labels - /// are found, an exception is raised to prevent importing a key when + /// are found, an exception is thrown to prevent importing a key when /// the key is ambiguous. /// /// This method supports the ENCRYPTED PRIVATE KEY PEM label. @@ -1237,34 +1256,48 @@ public override void ImportFromEncryptedPem(ReadOnlySpan input, ReadOnlySp /// The bytes to use as a password when decrypting the key material. /// /// - /// does not contain a PEM-encoded key with a recognized label. + /// + /// does not contain a PEM-encoded key with a recognized label. + /// /// /// -or- /// - /// contains multiple PEM-encoded keys with a recognized label. + /// + /// contains multiple PEM-encoded keys with a recognized label. + /// /// /// - /// The password is incorrect. + /// + /// The password is incorrect. + /// /// /// -or- /// - /// The base-64 decoded contents of the PEM text from - /// do not represent an ASN.1-BER-encoded PKCS#8 EncryptedPrivateKeyInfo structure. + /// + /// The base-64 decoded contents of the PEM text from + /// do not represent an ASN.1-BER-encoded PKCS#8 EncryptedPrivateKeyInfo structure. + /// /// /// -or- /// + /// /// The base-64 decoded contents of the PEM text from /// indicate the key is for an algorithm other than the algorithm /// represented by this instance. + /// /// /// -or- /// + /// /// The base-64 decoded contents of the PEM text from /// represent the key in a format that is not supported. + /// /// /// -or- /// + /// /// The algorithm-specific key import failed. + /// /// /// /// @@ -1274,12 +1307,8 @@ public override void ImportFromEncryptedPem(ReadOnlySpan input, ReadOnlySp /// passwords with PBKDF2 (Password-Based Key Derivation Function 2). /// /// - /// The base-64 decoded contents of the PEM text only supports - /// the binary (BER/CER/DER) encoding of EncryptedPrivateKeyInfo. - /// - /// /// Unsupported or malformed PEM-encoded objects will be ignored. If multiple supported PEM labels - /// are found, an exception is raised to prevent importing a key when + /// are found, an exception is thrown to prevent importing a key when /// the key is ambiguous. /// /// This method supports the ENCRYPTED PRIVATE KEY PEM label. diff --git a/src/libraries/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/ECDiffieHellman.cs b/src/libraries/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/ECDiffieHellman.cs index 5eee83194deb5..fd7c034f7be31 100644 --- a/src/libraries/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/ECDiffieHellman.cs +++ b/src/libraries/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/ECDiffieHellman.cs @@ -440,15 +440,21 @@ public virtual unsafe bool TryExportECPrivateKey(Span destination, out int /// /// The PEM text of the key to import. /// - /// does not contain a PEM-encoded key with a recognized label. - /// - /// -or- - /// - /// contains multiple PEM-encoded keys with a recognized label. - /// - /// -or- - /// - /// contains an encrypted PEM-encoded key. + /// + /// does not contain a PEM-encoded key with a recognized label. + /// + /// + /// -or- + /// + /// + /// contains multiple PEM-encoded keys with a recognized label. + /// + /// + /// -or- + /// + /// + /// contains an encrypted PEM-encoded key. + /// /// /// /// @@ -495,45 +501,58 @@ public override void ImportFromPem(ReadOnlySpan input) /// The password to use for decrypting the key material. /// /// - /// does not contain a PEM-encoded key with a recognized label. - /// - /// -or- - /// - /// contains multiple PEM-encoded keys with a recognized label. + /// + /// does not contain a PEM-encoded key with a recognized label. + /// + /// + /// -or- + /// + /// + /// contains multiple PEM-encoded keys with a recognized label. + /// /// /// - /// The password is incorrect. + /// + /// The password is incorrect. + /// /// /// -or- /// - /// The base-64 decoded contents of the PEM text from - /// do not represent an ASN.1-BER-encoded PKCS#8 EncryptedPrivateKeyInfo structure. + /// + /// The base-64 decoded contents of the PEM text from + /// do not represent an ASN.1-BER-encoded PKCS#8 EncryptedPrivateKeyInfo structure. + /// /// /// -or- /// + /// /// The base-64 decoded contents of the PEM text from /// indicate the key is for an algorithm other than the algorithm /// represented by this instance. + /// /// /// -or- /// + /// /// The base-64 decoded contents of the PEM text from /// represent the key in a format that is not supported. + /// /// /// -or- /// + /// /// The algorithm-specific key import failed. + /// /// /// /// /// When the base-64 decoded contents of indicate an algorithm that uses PBKDF1 /// (Password-Based Key Derivation Function 1) or PBKDF2 (Password-Based Key Derivation Function 2), - /// the password is converted to bytes via the UTF-8 encoding. This method - /// only supports the binary (BER/CER/DER) encoding of EncryptedPrivateKeyInfo. + /// the password is converted to bytes via the UTF-8 encoding. /// /// /// Unsupported or malformed PEM-encoded objects will be ignored. If multiple supported PEM labels - /// are found, an exception is raised to prevent importing a key when + /// are found, an exception is thrown to prevent importing a key when /// the key is ambiguous. /// /// This method supports the ENCRYPTED PRIVATE KEY PEM label. @@ -551,34 +570,48 @@ public override void ImportFromEncryptedPem(ReadOnlySpan input, ReadOnlySp /// The bytes to use as a password when decrypting the key material. /// /// - /// does not contain a PEM-encoded key with a recognized label. + /// + /// does not contain a PEM-encoded key with a recognized label. + /// /// /// -or- /// - /// contains multiple PEM-encoded keys with a recognized label. + /// + /// contains multiple PEM-encoded keys with a recognized label. + /// /// /// - /// The password is incorrect. + /// + /// The password is incorrect. + /// /// /// -or- /// - /// The base-64 decoded contents of the PEM text from - /// do not represent an ASN.1-BER-encoded PKCS#8 EncryptedPrivateKeyInfo structure. + /// + /// The base-64 decoded contents of the PEM text from + /// do not represent an ASN.1-BER-encoded PKCS#8 EncryptedPrivateKeyInfo structure. + /// /// /// -or- /// + /// /// The base-64 decoded contents of the PEM text from /// indicate the key is for an algorithm other than the algorithm /// represented by this instance. + /// /// /// -or- /// + /// /// The base-64 decoded contents of the PEM text from /// represent the key in a format that is not supported. + /// /// /// -or- /// + /// /// The algorithm-specific key import failed. + /// /// /// /// @@ -588,12 +621,8 @@ public override void ImportFromEncryptedPem(ReadOnlySpan input, ReadOnlySp /// passwords with PBKDF2 (Password-Based Key Derivation Function 2). /// /// - /// The base-64 decoded contents of the PEM text only supports - /// the binary (BER/CER/DER) encoding of EncryptedPrivateKeyInfo. - /// - /// /// Unsupported or malformed PEM-encoded objects will be ignored. If multiple supported PEM labels - /// are found, an exception is raised to prevent importing a key when + /// are found, an exception is thrown to prevent importing a key when /// the key is ambiguous. /// /// This method supports the ENCRYPTED PRIVATE KEY PEM label. diff --git a/src/libraries/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/ECDsa.cs b/src/libraries/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/ECDsa.cs index 1115a27867ca6..59b52bd0eb36d 100644 --- a/src/libraries/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/ECDsa.cs +++ b/src/libraries/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/ECDsa.cs @@ -1304,15 +1304,21 @@ public int GetMaxSignatureSize(DSASignatureFormat signatureFormat) /// /// The PEM text of the key to import. /// - /// does not contain a PEM-encoded key with a recognized label. - /// - /// -or- - /// - /// contains multiple PEM-encoded keys with a recognized label. - /// - /// -or- - /// - /// contains an encrypted PEM-encoded key. + /// + /// does not contain a PEM-encoded key with a recognized label. + /// + /// + /// -or- + /// + /// + /// contains multiple PEM-encoded keys with a recognized label. + /// + /// + /// -or- + /// + /// + /// contains an encrypted PEM-encoded key. + /// /// /// /// @@ -1359,45 +1365,58 @@ public override void ImportFromPem(ReadOnlySpan input) /// The password to use for decrypting the key material. /// /// - /// does not contain a PEM-encoded key with a recognized label. - /// - /// -or- - /// - /// contains multiple PEM-encoded keys with a recognized label. + /// + /// does not contain a PEM-encoded key with a recognized label. + /// + /// + /// -or- + /// + /// + /// contains multiple PEM-encoded keys with a recognized label. + /// /// /// - /// The password is incorrect. + /// + /// The password is incorrect. + /// /// /// -or- /// - /// The base-64 decoded contents of the PEM text from - /// do not represent an ASN.1-BER-encoded PKCS#8 EncryptedPrivateKeyInfo structure. + /// + /// The base-64 decoded contents of the PEM text from + /// do not represent an ASN.1-BER-encoded PKCS#8 EncryptedPrivateKeyInfo structure. + /// /// /// -or- /// + /// /// The base-64 decoded contents of the PEM text from /// indicate the key is for an algorithm other than the algorithm /// represented by this instance. + /// /// /// -or- /// + /// /// The base-64 decoded contents of the PEM text from /// represent the key in a format that is not supported. + /// /// /// -or- /// + /// /// The algorithm-specific key import failed. + /// /// /// /// /// When the base-64 decoded contents of indicate an algorithm that uses PBKDF1 /// (Password-Based Key Derivation Function 1) or PBKDF2 (Password-Based Key Derivation Function 2), - /// the password is converted to bytes via the UTF-8 encoding. This method - /// only supports the binary (BER/CER/DER) encoding of EncryptedPrivateKeyInfo. + /// the password is converted to bytes via the UTF-8 encoding. /// /// /// Unsupported or malformed PEM-encoded objects will be ignored. If multiple supported PEM labels - /// are found, an exception is raised to prevent importing a key when + /// are found, an exception is thrown to prevent importing a key when /// the key is ambiguous. /// /// This method supports the ENCRYPTED PRIVATE KEY PEM label. @@ -1415,34 +1434,48 @@ public override void ImportFromEncryptedPem(ReadOnlySpan input, ReadOnlySp /// The bytes to use as a password when decrypting the key material. /// /// - /// does not contain a PEM-encoded key with a recognized label. + /// + /// does not contain a PEM-encoded key with a recognized label. + /// /// /// -or- /// - /// contains multiple PEM-encoded keys with a recognized label. + /// + /// contains multiple PEM-encoded keys with a recognized label. + /// /// /// - /// The password is incorrect. + /// + /// The password is incorrect. + /// /// /// -or- /// - /// The base-64 decoded contents of the PEM text from - /// do not represent an ASN.1-BER-encoded PKCS#8 EncryptedPrivateKeyInfo structure. + /// + /// The base-64 decoded contents of the PEM text from + /// do not represent an ASN.1-BER-encoded PKCS#8 EncryptedPrivateKeyInfo structure. + /// /// /// -or- /// + /// /// The base-64 decoded contents of the PEM text from /// indicate the key is for an algorithm other than the algorithm /// represented by this instance. + /// /// /// -or- /// + /// /// The base-64 decoded contents of the PEM text from /// represent the key in a format that is not supported. + /// /// /// -or- /// + /// /// The algorithm-specific key import failed. + /// /// /// /// @@ -1452,12 +1485,8 @@ public override void ImportFromEncryptedPem(ReadOnlySpan input, ReadOnlySp /// passwords with PBKDF2 (Password-Based Key Derivation Function 2). /// /// - /// The base-64 decoded contents of the PEM text only supports - /// the binary (BER/CER/DER) encoding of EncryptedPrivateKeyInfo. - /// - /// /// Unsupported or malformed PEM-encoded objects will be ignored. If multiple supported PEM labels - /// are found, an exception is raised to prevent importing a key when + /// are found, an exception is thrown to prevent importing a key when /// the key is ambiguous. /// /// This method supports the ENCRYPTED PRIVATE KEY PEM label. diff --git a/src/libraries/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/RSA.cs b/src/libraries/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/RSA.cs index c8755b5996ad8..56b25ff778825 100644 --- a/src/libraries/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/RSA.cs +++ b/src/libraries/System.Security.Cryptography.Algorithms/src/System/Security/Cryptography/RSA.cs @@ -630,15 +630,21 @@ public override unsafe void ImportEncryptedPkcs8PrivateKey( /// /// The PEM text of the key to import. /// - /// does not contain a PEM-encoded key with a recognized label. - /// - /// -or- - /// - /// contains multiple PEM-encoded keys with a recognized label. - /// - /// -or- - /// - /// contains an encrypted PEM-encoded key. + /// + /// does not contain a PEM-encoded key with a recognized label. + /// + /// + /// -or- + /// + /// + /// contains multiple PEM-encoded keys with a recognized label. + /// + /// + /// -or- + /// + /// + /// contains an encrypted PEM-encoded key. + /// /// /// /// @@ -690,45 +696,58 @@ public override void ImportFromPem(ReadOnlySpan input) /// The password to use for decrypting the key material. /// /// - /// does not contain a PEM-encoded key with a recognized label. - /// - /// -or- - /// - /// contains multiple PEM-encoded keys with a recognized label. + /// + /// does not contain a PEM-encoded key with a recognized label. + /// + /// + /// -or- + /// + /// + /// contains multiple PEM-encoded keys with a recognized label. + /// /// /// - /// The password is incorrect. + /// + /// The password is incorrect. + /// /// /// -or- /// - /// The base-64 decoded contents of the PEM text from - /// do not represent an ASN.1-BER-encoded PKCS#8 EncryptedPrivateKeyInfo structure. + /// + /// The base-64 decoded contents of the PEM text from + /// do not represent an ASN.1-BER-encoded PKCS#8 EncryptedPrivateKeyInfo structure. + /// /// /// -or- /// + /// /// The base-64 decoded contents of the PEM text from /// indicate the key is for an algorithm other than the algorithm /// represented by this instance. + /// /// /// -or- /// + /// /// The base-64 decoded contents of the PEM text from /// represent the key in a format that is not supported. + /// /// /// -or- /// + /// /// The algorithm-specific key import failed. + /// /// /// /// /// When the base-64 decoded contents of indicate an algorithm that uses PBKDF1 /// (Password-Based Key Derivation Function 1) or PBKDF2 (Password-Based Key Derivation Function 2), - /// the password is converted to bytes via the UTF-8 encoding. This method - /// only supports the binary (BER/CER/DER) encoding of EncryptedPrivateKeyInfo. + /// the password is converted to bytes via the UTF-8 encoding. /// /// /// Unsupported or malformed PEM-encoded objects will be ignored. If multiple supported PEM labels - /// are found, an exception is raised to prevent importing a key when + /// are found, an exception is thrown to prevent importing a key when /// the key is ambiguous. /// /// This method supports the ENCRYPTED PRIVATE KEY PEM label. @@ -746,34 +765,48 @@ public override void ImportFromEncryptedPem(ReadOnlySpan input, ReadOnlySp /// The bytes to use as a password when decrypting the key material. /// /// - /// does not contain a PEM-encoded key with a recognized label. + /// + /// does not contain a PEM-encoded key with a recognized label. + /// /// /// -or- /// - /// contains multiple PEM-encoded keys with a recognized label. + /// + /// contains multiple PEM-encoded keys with a recognized label. + /// /// /// - /// The password is incorrect. + /// + /// The password is incorrect. + /// /// /// -or- /// - /// The base-64 decoded contents of the PEM text from - /// do not represent an ASN.1-BER-encoded PKCS#8 EncryptedPrivateKeyInfo structure. + /// + /// The base-64 decoded contents of the PEM text from + /// do not represent an ASN.1-BER-encoded PKCS#8 EncryptedPrivateKeyInfo structure. + /// /// /// -or- /// + /// /// The base-64 decoded contents of the PEM text from /// indicate the key is for an algorithm other than the algorithm /// represented by this instance. + /// /// /// -or- /// + /// /// The base-64 decoded contents of the PEM text from /// represent the key in a format that is not supported. + /// /// /// -or- /// + /// /// The algorithm-specific key import failed. + /// /// /// /// @@ -783,12 +816,8 @@ public override void ImportFromEncryptedPem(ReadOnlySpan input, ReadOnlySp /// passwords with PBKDF2 (Password-Based Key Derivation Function 2). /// /// - /// The base-64 decoded contents of the PEM text only supports - /// the binary (BER/CER/DER) encoding of EncryptedPrivateKeyInfo. - /// - /// /// Unsupported or malformed PEM-encoded objects will be ignored. If multiple supported PEM labels - /// are found, an exception is raised to prevent importing a key when + /// are found, an exception is thrown to prevent importing a key when /// the key is ambiguous. /// /// This method supports the ENCRYPTED PRIVATE KEY PEM label. diff --git a/src/libraries/System.Security.Cryptography.Primitives/src/System/Security/Cryptography/AsymmetricAlgorithm.cs b/src/libraries/System.Security.Cryptography.Primitives/src/System/Security/Cryptography/AsymmetricAlgorithm.cs index 5dd73c8ced548..6c811c578d1a5 100644 --- a/src/libraries/System.Security.Cryptography.Primitives/src/System/Security/Cryptography/AsymmetricAlgorithm.cs +++ b/src/libraries/System.Security.Cryptography.Primitives/src/System/Security/Cryptography/AsymmetricAlgorithm.cs @@ -173,7 +173,7 @@ public virtual bool TryExportSubjectPublicKeyInfo(Span destination, out in /// The password to use for decrypting the key material. /// /// - /// A derived type has not overriden this member. + /// A derived type has not overridden this member. /// /// /// Because each algorithm may have algorithm-specific PEM labels, the @@ -191,7 +191,7 @@ public virtual void ImportFromEncryptedPem(ReadOnlySpan input, ReadOnlySpa /// The bytes to use as a password when decrypting the key material. /// /// - /// A derived type has not overriden this member. + /// A derived type has not overridden this member. /// /// /// Because each algorithm may have algorithm-specific PEM labels, the @@ -206,7 +206,7 @@ public virtual void ImportFromEncryptedPem(ReadOnlySpan input, ReadOnlySpa /// /// The text of the PEM key to import. /// - /// A derived type has not overriden this member. + /// A derived type has not overridden this member. /// /// /// Because each algorithm may have algorithm-specific PEM labels, the From 2cadc5ea12d82a20f01b553645d8a075b7d620e6 Mon Sep 17 00:00:00 2001 From: Kevin Jones Date: Tue, 7 Apr 2020 11:36:06 -0400 Subject: [PATCH 15/18] Report consistent exception regardless of PEM order --- .../Cryptography/PemKeyImportHelpers.cs | 5 ++ .../EC/ECKeyPemTests.cs | 74 +++++++++++++++++-- 2 files changed, 72 insertions(+), 7 deletions(-) diff --git a/src/libraries/Common/src/Internal/Cryptography/PemKeyImportHelpers.cs b/src/libraries/Common/src/Internal/Cryptography/PemKeyImportHelpers.cs index 46a94183dae50..fd3b7f0b892b6 100644 --- a/src/libraries/Common/src/Internal/Cryptography/PemKeyImportHelpers.cs +++ b/src/libraries/Common/src/Internal/Cryptography/PemKeyImportHelpers.cs @@ -110,6 +110,11 @@ public static void ImportPem(ReadOnlySpan input, FindImportActionFunc call } else if (label.SequenceEqual(PemLabels.EncryptedPkcs8PrivateKey)) { + if (importAction != null || containsEncryptedPem) + { + throw new ArgumentException(SR.Argument_PemImport_AmbiguousPem, nameof(input)); + } + containsEncryptedPem = true; } diff --git a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/EC/ECKeyPemTests.cs b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/EC/ECKeyPemTests.cs index 42d6318331915..2df4e54e3a264 100644 --- a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/EC/ECKeyPemTests.cs +++ b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/EC/ECKeyPemTests.cs @@ -10,6 +10,10 @@ namespace System.Security.Cryptography.Tests { public abstract class ECKeyPemTests where TAlg : AsymmetricAlgorithm { + private const string AmbiguousExceptionMarker = "multiple keys"; + private const string EncryptedExceptionMarker = "encrypted key"; + private const string NoPemExceptionMarker = "No supported key"; + protected abstract TAlg CreateKey(); protected abstract ECParameters ExportParameters(TAlg key, bool includePrivateParameters); @@ -18,7 +22,8 @@ public void ImportFromPem_NoPem() { using (TAlg key = CreateKey()) { - AssertExtensions.Throws("input", () => key.ImportFromPem("")); + ArgumentException ae = AssertExtensions.Throws("input", () => key.ImportFromPem("")); + Assert.Contains(NoPemExceptionMarker, ae.Message); } } @@ -136,7 +141,8 @@ public void ImportFromPem_Spki_AmbiguousKey_Spki() MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEgQHs5HRkpurXDPaabivT2IaRoyYt Isuk92Ner/JmgKjYoSumHVmSNfZ9nLTVjxeD08pD548KWrqmJAeZNsDDqQ== -----END PUBLIC KEY-----"; - AssertExtensions.Throws("input", () => key.ImportFromPem(pem)); + ArgumentException ae = AssertExtensions.Throws("input", () => key.ImportFromPem(pem)); + Assert.Contains(AmbiguousExceptionMarker, ae.Message); } } @@ -157,7 +163,30 @@ public void ImportFromPem_Spki_AmbiguousKey_EncryptedPkcs8() MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEgQHs5HRkpurXDPaabivT2IaRoyYt Isuk92Ner/JmgKjYoSumHVmSNfZ9nLTVjxeD08pD548KWrqmJAeZNsDDqQ== -----END PUBLIC KEY-----"; - AssertExtensions.Throws("input", () => key.ImportFromPem(pem)); + ArgumentException ae = AssertExtensions.Throws("input", () => key.ImportFromPem(pem)); + Assert.Contains(AmbiguousExceptionMarker, ae.Message); + } + } + + [Fact] + public void ImportFromPem_Spki_AmbiguousKey_EncryptedPkcs8_Pkcs8First() + { + using (TAlg key = CreateKey()) + { + string pem = @" +-----BEGIN PUBLIC KEY----- +MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEgQHs5HRkpurXDPaabivT2IaRoyYt +Isuk92Ner/JmgKjYoSumHVmSNfZ9nLTVjxeD08pD548KWrqmJAeZNsDDqQ== +-----END PUBLIC KEY----- +-----BEGIN ENCRYPTED PRIVATE KEY----- +MIHgMEsGCSqGSIb3DQEFDTA+MCkGCSqGSIb3DQEFDDAcBAjVvm4KTLb0JgICCAAw +DAYIKoZIhvcNAgkFADARBgUrDgMCBwQIuHgfok8Ytl0EgZDkDSJ9vt8UvSesdyV+ +Evt9yfvEjiP/6yITq59drw1Kcgp6buOCVCY7LZ06aD6WpogiqGDYMuzfvqg5hNFp +opSAJ/pvHONL5kyAJLeNyG9c/mR2qyrP2L9gL0Z5fB9NyPejKTLi0PXMGQWdDTH8 +Qh0fqdrNovgFLubbJFMQN/MwwIAfIuf0Mn0WFYYeQiBJ3kg= +-----END ENCRYPTED PRIVATE KEY-----"; + ArgumentException ae = AssertExtensions.Throws("input", () => key.ImportFromPem(pem)); + Assert.Contains(AmbiguousExceptionMarker, ae.Message); } } @@ -174,7 +203,33 @@ public void ImportFromPem_EncryptedPrivateKeyFails() opSAJ/pvHONL5kyAJLeNyG9c/mR2qyrP2L9gL0Z5fB9NyPejKTLi0PXMGQWdDTH8 Qh0fqdrNovgFLubbJFMQN/MwwIAfIuf0Mn0WFYYeQiBJ3kg= -----END ENCRYPTED PRIVATE KEY-----"; - AssertExtensions.Throws("input", () => key.ImportFromPem(pem)); + ArgumentException ae = AssertExtensions.Throws("input", () => key.ImportFromPem(pem)); + Assert.Contains(EncryptedExceptionMarker, ae.Message); + } + } + + [Fact] + public void ImportFromPem_MultipleEncryptedPrivateKeyAreAmbiguous() + { + using (TAlg key = CreateKey()) + { + string pem = @" +-----BEGIN ENCRYPTED PRIVATE KEY----- +MIHgMEsGCSqGSIb3DQEFDTA+MCkGCSqGSIb3DQEFDDAcBAjVvm4KTLb0JgICCAAw +DAYIKoZIhvcNAgkFADARBgUrDgMCBwQIuHgfok8Ytl0EgZDkDSJ9vt8UvSesdyV+ +Evt9yfvEjiP/6yITq59drw1Kcgp6buOCVCY7LZ06aD6WpogiqGDYMuzfvqg5hNFp +opSAJ/pvHONL5kyAJLeNyG9c/mR2qyrP2L9gL0Z5fB9NyPejKTLi0PXMGQWdDTH8 +Qh0fqdrNovgFLubbJFMQN/MwwIAfIuf0Mn0WFYYeQiBJ3kg= +-----END ENCRYPTED PRIVATE KEY----- +-----BEGIN ENCRYPTED PRIVATE KEY----- +MIHgMEsGCSqGSIb3DQEFDTA+MCkGCSqGSIb3DQEFDDAcBAjVvm4KTLb0JgICCAAw +DAYIKoZIhvcNAgkFADARBgUrDgMCBwQIuHgfok8Ytl0EgZDkDSJ9vt8UvSesdyV+ +Evt9yfvEjiP/6yITq59drw1Kcgp6buOCVCY7LZ06aD6WpogiqGDYMuzfvqg5hNFp +opSAJ/pvHONL5kyAJLeNyG9c/mR2qyrP2L9gL0Z5fB9NyPejKTLi0PXMGQWdDTH8 +Qh0fqdrNovgFLubbJFMQN/MwwIAfIuf0Mn0WFYYeQiBJ3kg= +-----END ENCRYPTED PRIVATE KEY-----"; + ArgumentException ae = AssertExtensions.Throws("input", () => key.ImportFromPem(pem)); + Assert.Contains(AmbiguousExceptionMarker, ae.Message); } } @@ -241,8 +296,10 @@ public void ImportFromEncryptedPem_AmbiguousPem_Byte() -----END ENCRYPTED PRIVATE KEY-----"; byte[] passwordBytes = Encoding.UTF8.GetBytes("test"); - AssertExtensions.Throws("input", () => + ArgumentException ae = AssertExtensions.Throws("input", () => key.ImportFromEncryptedPem(pem, passwordBytes)); + + Assert.Contains(AmbiguousExceptionMarker, ae.Message); } } @@ -266,8 +323,9 @@ public void ImportFromEncryptedPem_AmbiguousPem_Char() opSAJ/pvHONL5kyAJLeNyG9c/mR2qyrP2L9gL0Z5fB9NyPejKTLi0PXMGQWdDTH8 Qh0fqdrNovgFLubbJFMQN/MwwIAfIuf0Mn0WFYYeQiBJ3kg= -----END ENCRYPTED PRIVATE KEY-----"; - AssertExtensions.Throws("input", () => + ArgumentException ae = AssertExtensions.Throws("input", () => key.ImportFromEncryptedPem(pem, "")); + Assert.Contains(AmbiguousExceptionMarker, ae.Message); } } @@ -276,7 +334,9 @@ public void ImportFromEncryptedPem_NoPem() { using(TAlg key = CreateKey()) { - AssertExtensions.Throws("input", () => key.ImportFromEncryptedPem("", "")); + ArgumentException ae = AssertExtensions.Throws("input", () => + key.ImportFromEncryptedPem("", "")); + Assert.Contains(NoPemExceptionMarker, ae.Message); } } } From 0a54b920818d5e4c85b438cb2dca596b5ccf3d93 Mon Sep 17 00:00:00 2001 From: Kevin Jones Date: Tue, 7 Apr 2020 12:20:48 -0400 Subject: [PATCH 16/18] Improve tests. Ensure ArgumentException is thrown with the right reason. Improve ambiguous PEM tests. --- .../DSA/DSAKeyPemTests.cs | 56 +++++++-- .../EC/ECKeyPemTests.cs | 95 +++++++++++++++ .../RSA/RSAKeyPemTests.cs | 108 ++++++++++++++++-- 3 files changed, 242 insertions(+), 17 deletions(-) diff --git a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/DSA/DSAKeyPemTests.cs b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/DSA/DSAKeyPemTests.cs index c7cbed28652e4..fa4dab4a497fb 100644 --- a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/DSA/DSAKeyPemTests.cs +++ b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/DSA/DSAKeyPemTests.cs @@ -10,13 +10,18 @@ namespace System.Security.Cryptography.Dsa.Tests { public static class DSAKeyPemTests { + private const string AmbiguousExceptionMarker = "multiple keys"; + private const string EncryptedExceptionMarker = "encrypted key"; + private const string NoPemExceptionMarker = "No supported key"; + [Fact] public static void ImportFromPem_NoPem() { using (DSA dsa = DSAFactory.Create()) { string pem = "pem? what pem? there is no pem here."; - AssertExtensions.Throws("input", () => dsa.ImportFromPem(pem)); + ArgumentException ae = AssertExtensions.Throws("input", () => dsa.ImportFromPem(pem)); + Assert.Contains(NoPemExceptionMarker, ae.Message); } } @@ -40,6 +45,31 @@ public static void ImportFromPem_Pkcs8UnEncrypted_Simple() } } + [Fact] + public static void ImportFromPem_Pkcs8UnEncrypted_IgnoresUnrelatedAlgorithm() + { + using (DSA dsa = DSAFactory.Create()) + { + string pem = @" +-----BEGIN EC PRIVATE KEY----- +MHcCAQEEIHChLC2xaEXtVv9oz8IaRys/BNfWhRv2NJ8tfVs0UrOKoAoGCCqGSM49 +AwEHoUQDQgAEgQHs5HRkpurXDPaabivT2IaRoyYtIsuk92Ner/JmgKjYoSumHVmS +NfZ9nLTVjxeD08pD548KWrqmJAeZNsDDqQ== +-----END EC PRIVATE KEY----- +-----BEGIN PRIVATE KEY----- +MIHGAgEAMIGoBgcqhkjOOAQBMIGcAkEA1qi38cr3ppZNB2Y/xpHSL2q81Vw3rvWN +IHRnQNgv4U4UY2NifZGSUULc3uOEvgoeBO1b9fRxSG9NmG1CoufflQIVAPq19iXV +1eFkMKHvYw6+M4l8wiT5AkAIRMSQ5S71jgWQLGNtZNHV6yxggqDU87/RzgeOh7Q6 +fve77OGaTv4qbZwinTYAg86p9yHzmwW6+XBS3vxnpYorBBYCFC49eoTIW2Z4Xh9v +55aYKyKwy5i8 +-----END PRIVATE KEY-----"; + dsa.ImportFromPem(pem); + DSAParameters dsaParameters = dsa.ExportParameters(true); + + DSAImportExport.AssertKeyEquals(DSATestData.Dsa512Parameters, dsaParameters); + } + } + [Fact] public static void ImportFromPem_Pkcs8_UnrelatedPrecedingPem() { @@ -127,7 +157,8 @@ public static void ImportFromPem_Pkcs8_AmbiguousKey_Pkcs8() fve77OGaTv4qbZwinTYAg86p9yHzmwW6+XBS3vxnpYorBBYCFC49eoTIW2Z4Xh9v 55aYKyKwy5i8 -----END PRIVATE KEY-----"; - AssertExtensions.Throws("input", () => dsa.ImportFromPem(pem)); + ArgumentException ae = AssertExtensions.Throws("input", () => dsa.ImportFromPem(pem)); + Assert.Contains(AmbiguousExceptionMarker, ae.Message); } } @@ -152,7 +183,8 @@ public static void ImportFromPem_Pkcs8_AmbiguousKey_Spki() fve77OGaTv4qbZwinTYAg86p9yHzmwW6+XBS3vxnpYorBBYCFC49eoTIW2Z4Xh9v 55aYKyKwy5i8 -----END PRIVATE KEY-----"; - AssertExtensions.Throws("input", () => dsa.ImportFromPem(pem)); + ArgumentException ae = AssertExtensions.Throws("input", () => dsa.ImportFromPem(pem)); + Assert.Contains(AmbiguousExceptionMarker, ae.Message); } } @@ -178,7 +210,8 @@ public static void ImportFromPem_Pkcs8_AmbiguousKey_EncryptedPkcs8() fve77OGaTv4qbZwinTYAg86p9yHzmwW6+XBS3vxnpYorBBYCFC49eoTIW2Z4Xh9v 55aYKyKwy5i8 -----END PRIVATE KEY-----"; - AssertExtensions.Throws("input", () => dsa.ImportFromPem(pem)); + ArgumentException ae = AssertExtensions.Throws("input", () => dsa.ImportFromPem(pem)); + Assert.Contains(AmbiguousExceptionMarker, ae.Message); } } @@ -197,7 +230,8 @@ public static void ImportFromPem_EncryptedPrivateKeyFails() dVYwfovccu8ktEAwk5XAOo0r+5CCw2lDDw/hbDeO87BToC5Cc5nu3F5LxAUj8Flc v8pi3w== -----END ENCRYPTED PRIVATE KEY-----"; - AssertExtensions.Throws("input", () => dsa.ImportFromPem(pem)); + ArgumentException ae = AssertExtensions.Throws("input", () => dsa.ImportFromPem(pem)); + Assert.Contains(EncryptedExceptionMarker, ae.Message); } } @@ -286,7 +320,9 @@ public static void ImportFromEncryptedPem_Pkcs8_Encrypted_AmbiguousPem() v8pi3w== -----END ENCRYPTED PRIVATE KEY-----"; byte[] passwordBytes = Encoding.UTF8.GetBytes("test"); - AssertExtensions.Throws("input", () => dsa.ImportFromEncryptedPem(pem, passwordBytes)); + ArgumentException ae = AssertExtensions.Throws("input", () => + dsa.ImportFromEncryptedPem(pem, passwordBytes)); + Assert.Contains(AmbiguousExceptionMarker, ae.Message); } } @@ -297,7 +333,9 @@ public static void ImportFromEncryptedPem_Pkcs8_Byte_NoPem() { string pem = ""; byte[] passwordBytes = Encoding.UTF8.GetBytes("test"); - AssertExtensions.Throws("input", () => dsa.ImportFromEncryptedPem(pem, passwordBytes)); + ArgumentException ae = AssertExtensions.Throws("input", () => + dsa.ImportFromEncryptedPem(pem, passwordBytes)); + Assert.Contains(NoPemExceptionMarker, ae.Message); } } @@ -307,7 +345,9 @@ public static void ImportFromEncryptedPem_Pkcs8_Char_NoPem() using (DSA dsa = DSAFactory.Create()) { string pem = ""; - AssertExtensions.Throws("input", () => dsa.ImportFromEncryptedPem(pem, "k")); + ArgumentException ae = AssertExtensions.Throws("input", () => + dsa.ImportFromEncryptedPem(pem, "")); + Assert.Contains(NoPemExceptionMarker, ae.Message); } } diff --git a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/EC/ECKeyPemTests.cs b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/EC/ECKeyPemTests.cs index 2df4e54e3a264..b07c29c6b4544 100644 --- a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/EC/ECKeyPemTests.cs +++ b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/EC/ECKeyPemTests.cs @@ -44,6 +44,32 @@ public void ImportFromPem_ECPrivateKey_Simple() } } + [Fact] + public void ImportFromPem_ECPrivateKey_IgnoresUnrelatedAlgorithm() + { + using (TAlg key = CreateKey()) + { + key.ImportFromPem(@" +-----BEGIN RSA PRIVATE KEY----- +MIIBOwIBAAJBALc/WfXui9VeJLf/AprRaoVDyW0lPlQxm5NTLEHDwUd7idstLzPX +uah0WEjgao5oO1BEUR4byjYlJ+F89Cs4BhUCAwEAAQJBAK/m8jYvnK9exaSR+DAh +Ij12ip5pB+HOFOdhCbS/coNoIowa6WJGrd3Np1m9BBhouWloF8UB6Iu8/e/wAg+F +9ykCIQDzcnsehnYgVZTTxzoCJ01PGpgESilRyFzNEsb8V60ZewIhAMCyOujqUqn7 +Q079SlHzXuvocqIdt4IM1EmIlrlU9GGvAh8Ijv3FFPUSLfANgfOIH9mX7ldpzzGk +rmaUzxQvyuVLAiEArCTM8dSbopUADWnD4jArhU50UhWAIaM6ZrKqC8k0RKsCIQDC +yZWUxoxAdjfrBGsx+U6BHM0Myqqe7fY7hjWzj4aBCw== +-----END RSA PRIVATE KEY----- +-----BEGIN EC PRIVATE KEY----- +MHcCAQEEIHChLC2xaEXtVv9oz8IaRys/BNfWhRv2NJ8tfVs0UrOKoAoGCCqGSM49 +AwEHoUQDQgAEgQHs5HRkpurXDPaabivT2IaRoyYtIsuk92Ner/JmgKjYoSumHVmS +NfZ9nLTVjxeD08pD548KWrqmJAeZNsDDqQ== +-----END EC PRIVATE KEY-----"); + ECParameters ecParameters = ExportParameters(key, true); + ECParameters expected = EccTestData.GetNistP256ReferenceKey(); + EccTestBase.AssertEqual(expected, ecParameters); + } + } + [Fact] public void ImportFromPem_Pkcs8_Simple() { @@ -61,6 +87,32 @@ public void ImportFromPem_Pkcs8_Simple() } } + [Fact] + public void ImportFromPem_Pkcs8_IgnoresUnrelatedAlgorithm() + { + using (TAlg key = CreateKey()) + { + key.ImportFromPem(@" +-----BEGIN RSA PRIVATE KEY----- +MIIBOwIBAAJBALc/WfXui9VeJLf/AprRaoVDyW0lPlQxm5NTLEHDwUd7idstLzPX +uah0WEjgao5oO1BEUR4byjYlJ+F89Cs4BhUCAwEAAQJBAK/m8jYvnK9exaSR+DAh +Ij12ip5pB+HOFOdhCbS/coNoIowa6WJGrd3Np1m9BBhouWloF8UB6Iu8/e/wAg+F +9ykCIQDzcnsehnYgVZTTxzoCJ01PGpgESilRyFzNEsb8V60ZewIhAMCyOujqUqn7 +Q079SlHzXuvocqIdt4IM1EmIlrlU9GGvAh8Ijv3FFPUSLfANgfOIH9mX7ldpzzGk +rmaUzxQvyuVLAiEArCTM8dSbopUADWnD4jArhU50UhWAIaM6ZrKqC8k0RKsCIQDC +yZWUxoxAdjfrBGsx+U6BHM0Myqqe7fY7hjWzj4aBCw== +-----END RSA PRIVATE KEY----- +-----BEGIN PRIVATE KEY----- +MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgcKEsLbFoRe1W/2jP +whpHKz8E19aFG/Y0ny19WzRSs4qhRANCAASBAezkdGSm6tcM9ppuK9PYhpGjJi0i +y6T3Y16v8maAqNihK6YdWZI19n2ctNWPF4PTykPnjwpauqYkB5k2wMOp +-----END PRIVATE KEY-----"); + ECParameters ecParameters = ExportParameters(key, true); + ECParameters expected = EccTestData.GetNistP256ReferenceKey(); + EccTestBase.AssertEqual(expected, ecParameters); + } + } + [Fact] public void ImportFromPem_Spki_Simple() { @@ -108,6 +160,31 @@ public void ImportFromPem_Spki_PrecedingUnrelatedPemIsIgnored() } } + [Fact] + public void ImportFromPem_Spki_IgnoresUnrelatedAlgorithms() + { + using (TAlg key = CreateKey()) + { + key.ImportFromPem(@" +-----BEGIN RSA PRIVATE KEY----- +MIIBOwIBAAJBALc/WfXui9VeJLf/AprRaoVDyW0lPlQxm5NTLEHDwUd7idstLzPX +uah0WEjgao5oO1BEUR4byjYlJ+F89Cs4BhUCAwEAAQJBAK/m8jYvnK9exaSR+DAh +Ij12ip5pB+HOFOdhCbS/coNoIowa6WJGrd3Np1m9BBhouWloF8UB6Iu8/e/wAg+F +9ykCIQDzcnsehnYgVZTTxzoCJ01PGpgESilRyFzNEsb8V60ZewIhAMCyOujqUqn7 +Q079SlHzXuvocqIdt4IM1EmIlrlU9GGvAh8Ijv3FFPUSLfANgfOIH9mX7ldpzzGk +rmaUzxQvyuVLAiEArCTM8dSbopUADWnD4jArhU50UhWAIaM6ZrKqC8k0RKsCIQDC +yZWUxoxAdjfrBGsx+U6BHM0Myqqe7fY7hjWzj4aBCw== +-----END RSA PRIVATE KEY----- +-----BEGIN PUBLIC KEY----- +MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEgQHs5HRkpurXDPaabivT2IaRoyYt +Isuk92Ner/JmgKjYoSumHVmSNfZ9nLTVjxeD08pD548KWrqmJAeZNsDDqQ== +-----END PUBLIC KEY-----"); + ECParameters ecParameters = ExportParameters(key, false); + ECParameters expected = EccTestData.GetNistP256ReferenceKey(); + EccTestBase.ComparePublicKey(expected.Q, ecParameters.Q, isEqual: true); + } + } + [Fact] public void ImportFromPem_Spki_PrecedingMalformedPem() { @@ -329,6 +406,24 @@ public void ImportFromEncryptedPem_AmbiguousPem_Char() } } + [Fact] + public void ImportFromEncryptedPem_UnencryptedPem_ThrowsNoPem() + { + using (TAlg key = CreateKey()) + { + string pem = @" +-----BEGIN PRIVATE KEY----- +MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgcKEsLbFoRe1W/2jP +whpHKz8E19aFG/Y0ny19WzRSs4qhRANCAASBAezkdGSm6tcM9ppuK9PYhpGjJi0i +y6T3Y16v8maAqNihK6YdWZI19n2ctNWPF4PTykPnjwpauqYkB5k2wMOp +-----END PRIVATE KEY-----"; + byte[] passwordBytes = Array.Empty(); + ArgumentException ae = AssertExtensions.Throws("input", () => + key.ImportFromEncryptedPem(pem, passwordBytes)); + Assert.Contains(NoPemExceptionMarker, ae.Message); + } + } + [Fact] public void ImportFromEncryptedPem_NoPem() { diff --git a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/RSA/RSAKeyPemTests.cs b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/RSA/RSAKeyPemTests.cs index 1268af7642589..6ff68a03a609e 100644 --- a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/RSA/RSAKeyPemTests.cs +++ b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/RSA/RSAKeyPemTests.cs @@ -10,13 +10,18 @@ namespace System.Security.Cryptography.Rsa.Tests { public static class RSAKeyPemTests { + private const string AmbiguousExceptionMarker = "multiple keys"; + private const string EncryptedExceptionMarker = "encrypted key"; + private const string NoPemExceptionMarker = "No supported key"; + [Fact] public static void ImportFromPem_NoPem() { using (RSA rsa = RSAFactory.Create()) { string pem = @"these aren't the PEMs you're looking for"; - AssertExtensions.Throws("input", () => rsa.ImportFromPem(pem)); + ArgumentException ae = AssertExtensions.Throws("input", () => rsa.ImportFromPem(pem)); + Assert.Contains(NoPemExceptionMarker, ae.Message); } } @@ -67,6 +72,35 @@ public static void ImportFromPem_Pkcs8UnEncrypted_Simple() } } + [Fact] + public static void ImportFromPem_Pkcs8UnEncrypted_UnrelatedAlgorithmIsIgnored() + { + using (RSA rsa = RSAFactory.Create()) + { + string pem = @" +-----BEGIN EC PRIVATE KEY----- +MHcCAQEEIHChLC2xaEXtVv9oz8IaRys/BNfWhRv2NJ8tfVs0UrOKoAoGCCqGSM49 +AwEHoUQDQgAEgQHs5HRkpurXDPaabivT2IaRoyYtIsuk92Ner/JmgKjYoSumHVmS +NfZ9nLTVjxeD08pD548KWrqmJAeZNsDDqQ== +-----END EC PRIVATE KEY----- +-----BEGIN PRIVATE KEY----- +MIIBVQIBADANBgkqhkiG9w0BAQEFAASCAT8wggE7AgEAAkEAtz9Z9e6L1V4kt/8C +mtFqhUPJbSU+VDGbk1MsQcPBR3uJ2y0vM9e5qHRYSOBqjmg7UERRHhvKNiUn4Xz0 +KzgGFQIDAQABAkEAr+byNi+cr17FpJH4MCEiPXaKnmkH4c4U52EJtL9yg2gijBrp +Ykat3c2nWb0EGGi5aWgXxQHoi7z97/ACD4X3KQIhAPNyex6GdiBVlNPHOgInTU8a +mARKKVHIXM0SxvxXrRl7AiEAwLI66OpSqftDTv1KUfNe6+hyoh23ggzUSYiWuVT0 +Ya8CHwiO/cUU9RIt8A2B84gf2ZfuV2nPMaSuZpTPFC/K5UsCIQCsJMzx1JuilQAN +acPiMCuFTnRSFYAhozpmsqoLyTREqwIhAMLJlZTGjEB2N+sEazH5ToEczQzKqp7t +9juGNbOPhoEL +-----END PRIVATE KEY-----"; + + rsa.ImportFromPem(pem); + RSAParameters rsaParameters = rsa.ExportParameters(true); + + ImportExport.AssertKeyEquals(TestData.DiminishedDPParameters, rsaParameters); + } + } + [Fact] public static void ImportFromPem_SubjectPublicKeyInfo_Simple() { @@ -77,7 +111,28 @@ public static void ImportFromPem_SubjectPublicKeyInfo_Simple() MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBALc/WfXui9VeJLf/AprRaoVDyW0lPlQx m5NTLEHDwUd7idstLzPXuah0WEjgao5oO1BEUR4byjYlJ+F89Cs4BhUCAwEAAQ== -----END PUBLIC KEY-----"; + rsa.ImportFromPem(pem); + RSAParameters rsaParameters = rsa.ExportParameters(false); + + ImportExport.AssertKeyEquals(TestData.DiminishedDPParameters.ToPublic(), rsaParameters); + } + } + [Fact] + public static void ImportFromPem_SubjectPublicKeyInfo_IgnoresUnrelatedAlgorithm() + { + using (RSA rsa = RSAFactory.Create()) + { + string pem = @" +-----BEGIN EC PRIVATE KEY----- +MHcCAQEEIHChLC2xaEXtVv9oz8IaRys/BNfWhRv2NJ8tfVs0UrOKoAoGCCqGSM49 +AwEHoUQDQgAEgQHs5HRkpurXDPaabivT2IaRoyYtIsuk92Ner/JmgKjYoSumHVmS +NfZ9nLTVjxeD08pD548KWrqmJAeZNsDDqQ== +-----END EC PRIVATE KEY----- +-----BEGIN PUBLIC KEY----- +MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBALc/WfXui9VeJLf/AprRaoVDyW0lPlQx +m5NTLEHDwUd7idstLzPXuah0WEjgao5oO1BEUR4byjYlJ+F89Cs4BhUCAwEAAQ== +-----END PUBLIC KEY-----"; rsa.ImportFromPem(pem); RSAParameters rsaParameters = rsa.ExportParameters(false); @@ -165,6 +220,33 @@ public static void ImportFromPem_RSAPrivateKey_PrecedingMalformedPem() } } + [Fact] + public static void ImportFromPem_RSAPrivateKey_IgnoresOtherAlgorithms() + { + using (RSA rsa = RSAFactory.Create()) + { + string pem = @" +-----BEGIN EC PRIVATE KEY----- +MHcCAQEEIHChLC2xaEXtVv9oz8IaRys/BNfWhRv2NJ8tfVs0UrOKoAoGCCqGSM49 +AwEHoUQDQgAEgQHs5HRkpurXDPaabivT2IaRoyYtIsuk92Ner/JmgKjYoSumHVmS +NfZ9nLTVjxeD08pD548KWrqmJAeZNsDDqQ== +-----END EC PRIVATE KEY----- +-----BEGIN RSA PRIVATE KEY----- +MIIBOwIBAAJBALc/WfXui9VeJLf/AprRaoVDyW0lPlQxm5NTLEHDwUd7idstLzPX +uah0WEjgao5oO1BEUR4byjYlJ+F89Cs4BhUCAwEAAQJBAK/m8jYvnK9exaSR+DAh +Ij12ip5pB+HOFOdhCbS/coNoIowa6WJGrd3Np1m9BBhouWloF8UB6Iu8/e/wAg+F +9ykCIQDzcnsehnYgVZTTxzoCJ01PGpgESilRyFzNEsb8V60ZewIhAMCyOujqUqn7 +Q079SlHzXuvocqIdt4IM1EmIlrlU9GGvAh8Ijv3FFPUSLfANgfOIH9mX7ldpzzGk +rmaUzxQvyuVLAiEArCTM8dSbopUADWnD4jArhU50UhWAIaM6ZrKqC8k0RKsCIQDC +yZWUxoxAdjfrBGsx+U6BHM0Myqqe7fY7hjWzj4aBCw== +-----END RSA PRIVATE KEY-----"; + rsa.ImportFromPem(pem); + RSAParameters rsaParameters = rsa.ExportParameters(true); + + ImportExport.AssertKeyEquals(TestData.DiminishedDPParameters, rsaParameters); + } + } + [Fact] public static void ImportFromPem_RSAPrivateKey_AmbiguousKey_RSAPrivateKey() { @@ -183,7 +265,8 @@ public static void ImportFromPem_RSAPrivateKey_AmbiguousKey_RSAPrivateKey() rmaUzxQvyuVLAiEArCTM8dSbopUADWnD4jArhU50UhWAIaM6ZrKqC8k0RKsCIQDC yZWUxoxAdjfrBGsx+U6BHM0Myqqe7fY7hjWzj4aBCw== -----END RSA PRIVATE KEY-----"; - AssertExtensions.Throws("input", () => rsa.ImportFromPem(pem)); + ArgumentException ae = AssertExtensions.Throws("input", () => rsa.ImportFromPem(pem)); + Assert.Contains(AmbiguousExceptionMarker, ae.Message); } } @@ -205,7 +288,8 @@ public static void ImportFromPem_RSAPrivateKey_AmbiguousKey_SubjectPublicKeyInfo rmaUzxQvyuVLAiEArCTM8dSbopUADWnD4jArhU50UhWAIaM6ZrKqC8k0RKsCIQDC yZWUxoxAdjfrBGsx+U6BHM0Myqqe7fY7hjWzj4aBCw== -----END RSA PRIVATE KEY-----"; - AssertExtensions.Throws("input", () => rsa.ImportFromPem(pem)); + ArgumentException ae = AssertExtensions.Throws("input", () => rsa.ImportFromPem(pem)); + Assert.Contains(AmbiguousExceptionMarker, ae.Message); } } @@ -227,7 +311,8 @@ public static void ImportFromPem_RSAPrivateKey_AmbiguousKey_RSAPublicKey() rmaUzxQvyuVLAiEArCTM8dSbopUADWnD4jArhU50UhWAIaM6ZrKqC8k0RKsCIQDC yZWUxoxAdjfrBGsx+U6BHM0Myqqe7fY7hjWzj4aBCw== -----END RSA PRIVATE KEY-----"; - AssertExtensions.Throws("input", () => rsa.ImportFromPem(pem)); + ArgumentException ae = AssertExtensions.Throws("input", () => rsa.ImportFromPem(pem)); + Assert.Contains(AmbiguousExceptionMarker, ae.Message); } } @@ -249,7 +334,8 @@ public static void ImportFromPem_RSAPrivateKey_AmbiguousKey_EncryptedPkcs8() rmaUzxQvyuVLAiEArCTM8dSbopUADWnD4jArhU50UhWAIaM6ZrKqC8k0RKsCIQDC yZWUxoxAdjfrBGsx+U6BHM0Myqqe7fY7hjWzj4aBCw== -----END RSA PRIVATE KEY-----"; - AssertExtensions.Throws("input", () => rsa.ImportFromPem(pem)); + ArgumentException ae = AssertExtensions.Throws("input", () => rsa.ImportFromPem(pem)); + Assert.Contains(AmbiguousExceptionMarker, ae.Message); } } @@ -271,7 +357,8 @@ public static void ImportFromPem_EncryptedPrivateKeyFails() RkMxT/C7OZVMOlb3HV3fJj7kDmOMqfc6aKEQjLdWtuYRB8CgaudldIpK4jP2+0b5 pBORBb0= -----END ENCRYPTED PRIVATE KEY-----"; - AssertExtensions.Throws("input", () => rsa.ImportFromPem(pem)); + ArgumentException ae = AssertExtensions.Throws("input", () => rsa.ImportFromPem(pem)); + Assert.Contains(EncryptedExceptionMarker, ae.Message); } } @@ -376,8 +463,9 @@ public static void ImportFromEncryptedPem_Pkcs8Encrypted_AmbiguousPem() CA7ffFk= -----END ENCRYPTED PRIVATE KEY-----"; byte[] passwordBytes = Encoding.UTF8.GetBytes("test"); - AssertExtensions.Throws("input", () => + ArgumentException ae = AssertExtensions.Throws("input", () => rsa.ImportFromEncryptedPem(pem, passwordBytes)); + Assert.Contains(AmbiguousExceptionMarker, ae.Message); } } @@ -388,8 +476,9 @@ public static void ImportFromEncryptedPem_Pkcs8Encrypted_Byte_NoPem() { string pem = "these aren't the PEMs we're looking for."; byte[] passwordBytes = Encoding.UTF8.GetBytes("test"); - AssertExtensions.Throws("input", () => + ArgumentException ae = AssertExtensions.Throws("input", () => rsa.ImportFromEncryptedPem(pem, passwordBytes)); + Assert.Contains(NoPemExceptionMarker, ae.Message); } } @@ -400,8 +489,9 @@ public static void ImportFromEncryptedPem_Pkcs8Encrypted_Char_NoPem() { string pem = "go about your business"; string password = "test"; - AssertExtensions.Throws("input", () => + ArgumentException ae = AssertExtensions.Throws("input", () => rsa.ImportFromEncryptedPem(pem, password)); + Assert.Contains(NoPemExceptionMarker, ae.Message); } } From 7a783ef35c0c2ac071dc457ec4c02cce307227a6 Mon Sep 17 00:00:00 2001 From: Kevin Jones Date: Tue, 7 Apr 2020 12:26:20 -0400 Subject: [PATCH 17/18] Explain bytesRead discard. --- .../Common/src/Internal/Cryptography/PemKeyImportHelpers.cs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/libraries/Common/src/Internal/Cryptography/PemKeyImportHelpers.cs b/src/libraries/Common/src/Internal/Cryptography/PemKeyImportHelpers.cs index fd3b7f0b892b6..4a6c1ea13ced4 100644 --- a/src/libraries/Common/src/Internal/Cryptography/PemKeyImportHelpers.cs +++ b/src/libraries/Common/src/Internal/Cryptography/PemKeyImportHelpers.cs @@ -70,6 +70,9 @@ public static void ImportEncryptedPem( Debug.Assert(bytesWritten == base64size); Span decodedBase64 = decodeBuffer.AsSpan(0, bytesWritten); + + // Don't need to check the bytesRead here. We're already operating + // on an input which is already a parsed subset of the input. importAction(password, decodedBase64, out _); } finally @@ -153,6 +156,9 @@ public static void ImportPem(ReadOnlySpan input, FindImportActionFunc call Debug.Assert(bytesWritten == base64size); Span decodedBase64 = decodeBuffer.AsSpan(0, bytesWritten); + + // Don't need to check the bytesRead here. We're already operating + // on an input which is already a parsed subset of the input. importAction(decodedBase64, out _); } finally From 05990dbbc7288a11afeee394e18739158d705915 Mon Sep 17 00:00:00 2001 From: Kevin Jones Date: Tue, 7 Apr 2020 12:31:04 -0400 Subject: [PATCH 18/18] Missing EncryptedPrivateKeyInfo tests. --- .../DSA/DSAKeyPemTests.cs | 19 +++++++++++++++ .../RSA/RSAKeyPemTests.cs | 23 +++++++++++++++++++ 2 files changed, 42 insertions(+) diff --git a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/DSA/DSAKeyPemTests.cs b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/DSA/DSAKeyPemTests.cs index fa4dab4a497fb..6029383756cac 100644 --- a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/DSA/DSAKeyPemTests.cs +++ b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/DSA/DSAKeyPemTests.cs @@ -351,6 +351,25 @@ public static void ImportFromEncryptedPem_Pkcs8_Char_NoPem() } } + [Fact] + public static void ImportFromEncryptedPem_Pkcs8_NoEncryptedPem() + { + using (DSA dsa = DSAFactory.Create()) + { + string pem = @" +-----BEGIN PRIVATE KEY----- +MIHGAgEAMIGoBgcqhkjOOAQBMIGcAkEA1qi38cr3ppZNB2Y/xpHSL2q81Vw3rvWN +IHRnQNgv4U4UY2NifZGSUULc3uOEvgoeBO1b9fRxSG9NmG1CoufflQIVAPq19iXV +1eFkMKHvYw6+M4l8wiT5AkAIRMSQ5S71jgWQLGNtZNHV6yxggqDU87/RzgeOh7Q6 +fve77OGaTv4qbZwinTYAg86p9yHzmwW6+XBS3vxnpYorBBYCFC49eoTIW2Z4Xh9v +55aYKyKwy5i8 +-----END PRIVATE KEY-----"; + ArgumentException ae = AssertExtensions.Throws("input", () => + dsa.ImportFromEncryptedPem(pem, "")); + Assert.Contains(NoPemExceptionMarker, ae.Message); + } + } + private static DSAParameters ToPublic(this DSAParameters dsaParams) { dsaParams.X = null; diff --git a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/RSA/RSAKeyPemTests.cs b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/RSA/RSAKeyPemTests.cs index 6ff68a03a609e..37c90271b66a7 100644 --- a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/RSA/RSAKeyPemTests.cs +++ b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/RSA/RSAKeyPemTests.cs @@ -482,6 +482,29 @@ public static void ImportFromEncryptedPem_Pkcs8Encrypted_Byte_NoPem() } } + [Fact] + public static void ImportFromEncryptedPem_NoEncryptedPem() + { + using (RSA rsa = RSAFactory.Create()) + { + string pem = @" +-----BEGIN PRIVATE KEY----- +MIIBVQIBADANBgkqhkiG9w0BAQEFAASCAT8wggE7AgEAAkEAtz9Z9e6L1V4kt/8C +mtFqhUPJbSU+VDGbk1MsQcPBR3uJ2y0vM9e5qHRYSOBqjmg7UERRHhvKNiUn4Xz0 +KzgGFQIDAQABAkEAr+byNi+cr17FpJH4MCEiPXaKnmkH4c4U52EJtL9yg2gijBrp +Ykat3c2nWb0EGGi5aWgXxQHoi7z97/ACD4X3KQIhAPNyex6GdiBVlNPHOgInTU8a +mARKKVHIXM0SxvxXrRl7AiEAwLI66OpSqftDTv1KUfNe6+hyoh23ggzUSYiWuVT0 +Ya8CHwiO/cUU9RIt8A2B84gf2ZfuV2nPMaSuZpTPFC/K5UsCIQCsJMzx1JuilQAN +acPiMCuFTnRSFYAhozpmsqoLyTREqwIhAMLJlZTGjEB2N+sEazH5ToEczQzKqp7t +9juGNbOPhoEL +-----END PRIVATE KEY-----"; + byte[] passwordBytes = Encoding.UTF8.GetBytes("test"); + ArgumentException ae = AssertExtensions.Throws("input", () => + rsa.ImportFromEncryptedPem(pem, passwordBytes)); + Assert.Contains(NoPemExceptionMarker, ae.Message); + } + } + [Fact] public static void ImportFromEncryptedPem_Pkcs8Encrypted_Char_NoPem() {