From 8c56ec1bba15a164a636c1ea4ead31a3ddc5f7d7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20K=C3=B6plinger?= Date: Wed, 10 Jul 2024 12:21:17 +0200 Subject: [PATCH 1/2] Don't use obsolete X509Certificate2 constructor on net9.0 Fixes https://github.com/NuGet/Home/issues/13612 --- .../SignCommand/CertificateProvider.cs | 17 ++++++++++- .../Settings/Items/FileClientCertItem.cs | 4 +++ .../Utility/CertificateChainUtility.cs | 4 +++ .../ClientCertificateProviderTests.cs | 4 +++ .../HttpSource/ClientCertificatesTests.cs | 4 +++ .../SelfSignedCertificateMockServer.cs | 4 +++ .../Signing/CertificateUtilities.cs | 4 +++ .../Signing/SigningTestUtility.cs | 28 +++++++++++++++++++ .../TestServer/TcpListenerServer.cs | 4 +++ 9 files changed, 72 insertions(+), 1 deletion(-) diff --git a/src/NuGet.Core/NuGet.Commands/SignCommand/CertificateProvider.cs b/src/NuGet.Core/NuGet.Commands/SignCommand/CertificateProvider.cs index c6ea7124366..b90c5974282 100644 --- a/src/NuGet.Core/NuGet.Commands/SignCommand/CertificateProvider.cs +++ b/src/NuGet.Core/NuGet.Commands/SignCommand/CertificateProvider.cs @@ -32,6 +32,9 @@ internal static class CertificateProvider private const int MACOS_INVALID_CERT = -25257; +#if NET9_0_OR_GREATER + private const int CRYPT_E_BAD_DECODE = unchecked((int)0x80092002); +#endif #if IS_SIGNING_SUPPORTED && IS_CORECLR //Generic exception ASN1 corrupted data @@ -83,6 +86,9 @@ public static async Task GetCertificatesAsync(Certif options.CertificatePath))); case CRYPT_E_NO_MATCH_HRESULT: +#if NET9_0_OR_GREATER + case CRYPT_E_BAD_DECODE: +#endif #if IS_SIGNING_SUPPORTED && IS_CORECLR case OPENSSL_ASN1_CORRUPTED_DATA_ERROR: #else @@ -122,7 +128,12 @@ private static async Task LoadCertificateFromFileAsync(Certifi if (!string.IsNullOrEmpty(options.CertificatePassword)) { - cert = new X509Certificate2(options.CertificatePath, options.CertificatePassword); // use the password if the user provided it. + // use the password if the user provided it +#if NET9_0_OR_GREATER + cert = X509CertificateLoader.LoadPkcs12FromFile(options.CertificatePath, options.CertificatePassword); +#else + cert = new X509Certificate2(options.CertificatePath, options.CertificatePassword); +#endif } else { @@ -147,8 +158,12 @@ private static async Task LoadCertificateFromFileAsync(Certifi throw; } } +#else +#if NET9_0_OR_GREATER + cert = X509CertificateLoader.LoadPkcs12FromFile(options.CertificatePath, null); #else cert = new X509Certificate2(options.CertificatePath); +#endif #endif } diff --git a/src/NuGet.Core/NuGet.Configuration/Settings/Items/FileClientCertItem.cs b/src/NuGet.Core/NuGet.Configuration/Settings/Items/FileClientCertItem.cs index 774281b77a1..e2edb733034 100644 --- a/src/NuGet.Core/NuGet.Configuration/Settings/Items/FileClientCertItem.cs +++ b/src/NuGet.Core/NuGet.Configuration/Settings/Items/FileClientCertItem.cs @@ -167,7 +167,11 @@ public override IEnumerable Search() Resources.FileCertItemPathFileNotExist)); } +#if NET9_0_OR_GREATER + return new[] { string.IsNullOrWhiteSpace(Password) ? X509CertificateLoader.LoadPkcs12FromFile(filePath, null) : X509CertificateLoader.LoadPkcs12FromFile(filePath, Password) }; +#else return new[] { string.IsNullOrWhiteSpace(Password) ? new X509Certificate2(filePath) : new X509Certificate2(filePath, Password) }; +#endif } public void Update(string filePath, string? password, bool storePasswordInClearText) diff --git a/src/NuGet.Core/NuGet.Packaging/Signing/Utility/CertificateChainUtility.cs b/src/NuGet.Core/NuGet.Packaging/Signing/Utility/CertificateChainUtility.cs index d23123a81cd..efbac7861de 100644 --- a/src/NuGet.Core/NuGet.Packaging/Signing/Utility/CertificateChainUtility.cs +++ b/src/NuGet.Core/NuGet.Packaging/Signing/Utility/CertificateChainUtility.cs @@ -127,7 +127,11 @@ public static IX509CertificateChain GetCertificateChain(X509Chain x509Chain) // Return a new certificate object. // This allows the chain and its chain element certificates to be disposed // in both success and error cases. +#if NET9_0_OR_GREATER + certs.Add(X509CertificateLoader.LoadCertificate(item.Certificate.RawData)); +#else certs.Add(new X509Certificate2(item.Certificate.RawData)); +#endif } return certs; diff --git a/test/NuGet.Core.Tests/NuGet.Configuration.Test/ClientCertificateProviderTests.cs b/test/NuGet.Core.Tests/NuGet.Configuration.Test/ClientCertificateProviderTests.cs index 3925f29532a..7c383a3dc77 100644 --- a/test/NuGet.Core.Tests/NuGet.Configuration.Test/ClientCertificateProviderTests.cs +++ b/test/NuGet.Core.Tests/NuGet.Configuration.Test/ClientCertificateProviderTests.cs @@ -147,7 +147,11 @@ private byte[] CreateCertificate() private X509Certificate2 GetCertificate() { +#if NET9_0_OR_GREATER + return X509CertificateLoader.LoadPkcs12(CreateCertificate(), CertificatePassword); +#else return new X509Certificate2(CreateCertificate(), CertificatePassword); +#endif } private void RemoveCertificateFromStorage() diff --git a/test/NuGet.Core.Tests/NuGet.Protocol.Tests/HttpSource/ClientCertificatesTests.cs b/test/NuGet.Core.Tests/NuGet.Protocol.Tests/HttpSource/ClientCertificatesTests.cs index 83b3be6f483..51e1ac490f2 100644 --- a/test/NuGet.Core.Tests/NuGet.Protocol.Tests/HttpSource/ClientCertificatesTests.cs +++ b/test/NuGet.Core.Tests/NuGet.Protocol.Tests/HttpSource/ClientCertificatesTests.cs @@ -41,7 +41,11 @@ private X509Certificate2 GetCertificate() var end = start.AddYears(1); var cert = request.CreateSelfSigned(start, end); var data = cert.Export(X509ContentType.Pfx); +#if NET9_0_OR_GREATER + return X509CertificateLoader.LoadPkcs12(data, null); +#else return new X509Certificate2(data); +#endif } } } diff --git a/test/TestUtilities/Test.Utility/SelfSignedCertificateMockServer.cs b/test/TestUtilities/Test.Utility/SelfSignedCertificateMockServer.cs index 330089ca7e6..3ba0611e8f0 100644 --- a/test/TestUtilities/Test.Utility/SelfSignedCertificateMockServer.cs +++ b/test/TestUtilities/Test.Utility/SelfSignedCertificateMockServer.cs @@ -198,7 +198,11 @@ private static X509Certificate2 GenerateSelfSignedCertificate() var end = DateTime.UtcNow.AddYears(1); var cert = request.CreateSelfSigned(start, end); var certBytes = cert.Export(X509ContentType.Pfx, "password"); +#if NET9_0_OR_GREATER + return X509CertificateLoader.LoadPkcs12(certBytes, "password", X509KeyStorageFlags.Exportable); +#else return new X509Certificate2(certBytes, "password", X509KeyStorageFlags.Exportable); +#endif } } diff --git a/test/TestUtilities/Test.Utility/Signing/CertificateUtilities.cs b/test/TestUtilities/Test.Utility/Signing/CertificateUtilities.cs index 6e9232634dd..c4aa29fc745 100644 --- a/test/TestUtilities/Test.Utility/Signing/CertificateUtilities.cs +++ b/test/TestUtilities/Test.Utility/Signing/CertificateUtilities.cs @@ -60,7 +60,11 @@ public static X509Certificate2 GetCertificateWithPrivateKey(X509Certificate bcCe X509Certificate2 certificate; +#if NET9_0_OR_GREATER + using (var certificateTmp = X509CertificateLoader.LoadCertificate(bcCertificate.GetEncoded())) +#else using (var certificateTmp = new X509Certificate2(bcCertificate.GetEncoded())) +#endif { certificate = RSACertificateExtensions.CopyWithPrivateKey(certificateTmp, privateKey); } diff --git a/test/TestUtilities/Test.Utility/Signing/SigningTestUtility.cs b/test/TestUtilities/Test.Utility/Signing/SigningTestUtility.cs index 2fd28b4e3d8..646d80f7d7b 100644 --- a/test/TestUtilities/Test.Utility/Signing/SigningTestUtility.cs +++ b/test/TestUtilities/Test.Utility/Signing/SigningTestUtility.cs @@ -458,7 +458,11 @@ private static X509Certificate2 GenerateCertificate( } } +#if NET9_0_OR_GREATER + return X509CertificateLoader.LoadPkcs12(certResult.Export(X509ContentType.Pkcs12), password: (string)null, keyStorageFlags: X509KeyStorageFlags.Exportable); +#else return new X509Certificate2(certResult.Export(X509ContentType.Pkcs12), password: (string)null, keyStorageFlags: X509KeyStorageFlags.Exportable); +#endif } private static RSASignaturePadding ToPadding(this RSASignaturePaddingMode mode) @@ -497,7 +501,11 @@ public static X509Certificate2 GenerateCertificate(string subjectName, RSA key) var certResult = request.CreateSelfSigned(notBefore: DateTime.UtcNow.Subtract(TimeSpan.FromHours(1)), notAfter: DateTime.UtcNow.Add(TimeSpan.FromHours(1))); +#if NET9_0_OR_GREATER + return X509CertificateLoader.LoadPkcs12(certResult.Export(X509ContentType.Pkcs12), password: (string)null, keyStorageFlags: X509KeyStorageFlags.Exportable); +#else return new X509Certificate2(certResult.Export(X509ContentType.Pkcs12), password: (string)null, keyStorageFlags: X509KeyStorageFlags.Exportable); +#endif } public static X509Certificate2 GenerateCertificate( @@ -534,7 +542,11 @@ public static X509Certificate2 GenerateCertificate( using (var temp = request.Create(issuerDN, generator, notBefore, notAfter, serialNumber)) { var certResult = temp.CopyWithPrivateKey(algorithm); +#if NET9_0_OR_GREATER + return X509CertificateLoader.LoadPkcs12(certResult.Export(X509ContentType.Pkcs12), password: (string)null, keyStorageFlags: X509KeyStorageFlags.Exportable); +#else return new X509Certificate2(certResult.Export(X509ContentType.Pkcs12), password: (string)null, keyStorageFlags: X509KeyStorageFlags.Exportable); +#endif } } @@ -571,7 +583,11 @@ public static X509Certificate2 GenerateSelfIssuedCertificate(bool isCa) var now = DateTime.UtcNow; var certResult = request.CreateSelfSigned(notBefore: now, notAfter: now.AddHours(1)); +#if NET9_0_OR_GREATER + return X509CertificateLoader.LoadPkcs12(certResult.Export(X509ContentType.Pkcs12), password: (string)null, keyStorageFlags: X509KeyStorageFlags.Exportable); +#else return new X509Certificate2(certResult.Export(X509ContentType.Pkcs12), password: (string)null, keyStorageFlags: X509KeyStorageFlags.Exportable); +#endif } } @@ -655,7 +671,11 @@ public static SignedCms GenerateRepositoryCountersignedSignedCms(X509Certificate /// public static X509Certificate2 GetPublicCert(X509Certificate2 cert) { +#if NET9_0_OR_GREATER + return X509CertificateLoader.LoadCertificate(cert.Export(X509ContentType.Cert)); +#else return new X509Certificate2(cert.Export(X509ContentType.Cert)); +#endif } /// @@ -664,7 +684,11 @@ public static X509Certificate2 GetPublicCert(X509Certificate2 cert) public static X509Certificate2 GetPublicCertWithPrivateKey(X509Certificate2 cert) { var password = new Guid().ToString(); +#if NET9_0_OR_GREATER + return X509CertificateLoader.LoadPkcs12(cert.Export(X509ContentType.Pfx, password), password, X509KeyStorageFlags.PersistKeySet | X509KeyStorageFlags.Exportable); +#else return new X509Certificate2(cert.Export(X509ContentType.Pfx, password), password, X509KeyStorageFlags.PersistKeySet | X509KeyStorageFlags.Exportable); +#endif } public static TrustedTestCert GenerateTrustedTestCertificate() @@ -761,7 +785,11 @@ public static X509Certificate2 GetCertificate(string name) { var bytes = GetResourceBytes(name); +#if NET9_0_OR_GREATER + return X509CertificateLoader.LoadCertificate(bytes); +#else return new X509Certificate2(bytes); +#endif } public static byte[] GetHash(X509Certificate2 certificate, NuGet.Common.HashAlgorithmName hashAlgorithm) diff --git a/test/TestUtilities/Test.Utility/TestServer/TcpListenerServer.cs b/test/TestUtilities/Test.Utility/TestServer/TcpListenerServer.cs index db8034c083c..36c1e08d009 100644 --- a/test/TestUtilities/Test.Utility/TestServer/TcpListenerServer.cs +++ b/test/TestUtilities/Test.Utility/TestServer/TcpListenerServer.cs @@ -83,7 +83,11 @@ private static X509Certificate2 GenerateSelfSignedCertificate() var cert = request.CreateSelfSigned(start, end); var certBytes = cert.Export(X509ContentType.Pfx, "password"); +#if NET9_0_OR_GREATER + return X509CertificateLoader.LoadPkcs12(certBytes, "password", X509KeyStorageFlags.Exportable); +#else return new X509Certificate2(certBytes, "password", X509KeyStorageFlags.Exportable); +#endif } } From 085f2ff060bebd480e08c170354a0117e9776823 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20K=C3=B6plinger?= Date: Wed, 10 Jul 2024 12:30:43 +0200 Subject: [PATCH 2/2] Upgrade dotnet used in nuget.client source-build job --- eng/dotnet-build/global.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/eng/dotnet-build/global.json b/eng/dotnet-build/global.json index edf01b63e04..070074d4e25 100644 --- a/eng/dotnet-build/global.json +++ b/eng/dotnet-build/global.json @@ -1,8 +1,8 @@ { "tools": { - "dotnet": "9.0.100-preview.2.24157.14" + "dotnet": "9.0.100-preview.7.24357.2" }, "msbuild-sdks": { - "Microsoft.DotNet.Arcade.Sdk": "9.0.0-beta.24208.8" + "Microsoft.DotNet.Arcade.Sdk": "9.0.0-beta.24352.2" } }