Skip to content

Conversation

@pepone
Copy link
Member

@pepone pepone commented Nov 6, 2025

This PR updates C# sources to compile with .NET 10 (tested with RC2).

See #4635

Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR modernizes SSL/TLS certificate handling in the C# Ice implementation by migrating from the deprecated X509Certificate2 constructor to the recommended X509CertificateLoader API. The changes improve code quality by using the modern .NET cryptography APIs and streamline certificate loading patterns.

Key changes:

  • Replaced X509Certificate2 constructor calls with X509CertificateLoader.LoadPkcs12FromFile() and X509CertificateLoader.LoadCertificateFromFile() methods
  • Updated cipher information retrieval to use NegotiatedCipherSuite instead of deprecated CipherAlgorithm property
  • Added Microsoft.Bcl.Cryptography package dependency for .NET 8 to support X509CertificateLoader

Reviewed Changes

Copilot reviewed 10 out of 10 changed files in this pull request and generated 11 comments.

Show a summary per file
File Description
csharp/src/Ice/Ice.csproj Added conditional package reference to Microsoft.Bcl.Cryptography for .NET 8 support
csharp/test/IceSSL/configuration/msbuild/client/client.csproj Added conditional package reference to Microsoft.Bcl.Cryptography for .NET 8 test client
csharp/src/Ice/SSL/SSLEngine.cs Migrated certificate loading from X509Certificate2 constructor to X509CertificateLoader API, updated cipher suite logging, and modernized StoreName parsing
csharp/src/Ice/SSL/TransceiverI.cs Replaced CipherAlgorithm with NegotiatedCipherSuite for cipher information
csharp/test/IceSSL/configuration/PlatformTests.cs Updated all test certificate loading to use X509CertificateLoader
csharp/test/IceSSL/configuration/AllTests.cs Updated all test certificate loading to use X509CertificateLoader
csharp/src/Ice/UtilInternal/StringUtil.cs Simplified string comparison using range syntax
csharp/src/iceboxnet/Server.cs Changed Server class visibility from public to internal
csharp/msbuild/CodeAnalysis.Tests.globalconfig Added suppression for CA1515 rule in tests
csharp/msbuild/CodeAnalysis.Src.globalconfig Removed CA1515 suppression from source code
Comments suppressed due to low confidence (1)

csharp/src/Ice/SSL/SSLEngine.cs:504

  • The createSecureString method is no longer used after migrating to X509CertificateLoader.LoadPkcs12FromFile. This unused private method should be removed to improve code maintainability.
    private static SecureString createSecureString(string s)
    {
        var result = new SecureString();
        foreach (char ch in s)
        {
            result.AppendChar(ch);
        }
        return result;
    }

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

using var serverCertificate =
new X509Certificate2(Path.Combine(certificatesPath, "ca1/server.p12"), "password");
using X509Certificate2 serverCertificate =
X509CertificateLoader.LoadPkcs12FromFile(Path.Combine(certificatesPath, "ca1/server.p12"), "password");
Copy link

Copilot AI Nov 6, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Call to 'System.IO.Path.Combine'.

Suggested change
X509CertificateLoader.LoadPkcs12FromFile(Path.Combine(certificatesPath, "ca1/server.p12"), "password");
X509CertificateLoader.LoadPkcs12FromFile(Path.Combine(certificatesPath, "ca1", "server.p12"), "password");

Copilot uses AI. Check for mistakes.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sounds correct.

using var serverCertificate =
new X509Certificate2(Path.Combine(certificatesPath, "ca1/server.p12"), "password");
using X509Certificate2 serverCertificate =
X509CertificateLoader.LoadPkcs12FromFile(Path.Combine(certificatesPath, "ca1/server.p12"), "password");
Copy link

Copilot AI Nov 6, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Call to 'System.IO.Path.Combine'.

Suggested change
X509CertificateLoader.LoadPkcs12FromFile(Path.Combine(certificatesPath, "ca1/server.p12"), "password");
X509CertificateLoader.LoadPkcs12FromFile(Path.Combine(certificatesPath, "ca1", "server.p12"), "password");

Copilot uses AI. Check for mistakes.
using var serverCertificate =
new X509Certificate2(Path.Combine(certificatesPath, "ca1/server.p12"), "password");
using X509Certificate2 serverCertificate =
X509CertificateLoader.LoadPkcs12FromFile(Path.Combine(certificatesPath, "ca1/server.p12"), "password");
Copy link

Copilot AI Nov 6, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Call to 'System.IO.Path.Combine'.

Copilot uses AI. Check for mistakes.
using var clientCertificate =
new X509Certificate2(Path.Combine(certificatesPath, "ca1/client.p12"), "password");
using X509Certificate2 serverCertificate =
X509CertificateLoader.LoadPkcs12FromFile(Path.Combine(certificatesPath, "ca1/server.p12"), "password");
Copy link

Copilot AI Nov 6, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Call to 'System.IO.Path.Combine'.

Copilot uses AI. Check for mistakes.
using X509Certificate2 serverCertificate =
X509CertificateLoader.LoadPkcs12FromFile(Path.Combine(certificatesPath, "ca1/server.p12"), "password");
using X509Certificate2 clientCertificate =
X509CertificateLoader.LoadPkcs12FromFile(Path.Combine(certificatesPath, "ca1/client.p12"), "password");
Copy link

Copilot AI Nov 6, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Call to 'System.IO.Path.Combine'.

Copilot uses AI. Check for mistakes.
using X509Certificate2 serverCertificate =
X509CertificateLoader.LoadPkcs12FromFile(Path.Combine(certificatesPath, "ca1/server.p12"), "password");
using X509Certificate2 clientCertificate =
X509CertificateLoader.LoadPkcs12FromFile(Path.Combine(certificatesPath, "ca1/client.p12"), "password");
Copy link

Copilot AI Nov 6, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Call to 'System.IO.Path.Combine'.

Copilot uses AI. Check for mistakes.
using var serverCertificate = new X509Certificate2(Path.Combine(certificatesPath, "ca1/server.p12"), "password");
using var clientCertificate = new X509Certificate2(Path.Combine(certificatesPath, "ca1/client.p12"), "password");
using X509Certificate2 serverCertificate =
X509CertificateLoader.LoadPkcs12FromFile(Path.Combine(certificatesPath, "ca1/server.p12"), "password");
Copy link

Copilot AI Nov 6, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Call to 'System.IO.Path.Combine'.

Copilot uses AI. Check for mistakes.
using X509Certificate2 serverCertificate =
X509CertificateLoader.LoadPkcs12FromFile(Path.Combine(certificatesPath, "ca1/server.p12"), "password");
using X509Certificate2 clientCertificate =
X509CertificateLoader.LoadPkcs12FromFile(Path.Combine(certificatesPath, "ca1/client.p12"), "password");
Copy link

Copilot AI Nov 6, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Call to 'System.IO.Path.Combine'.

Copilot uses AI. Check for mistakes.
using var trustedRootCertificatesCA1 = new X509Certificate2(Path.Combine(certificatesPath, "ca1/ca1_cert.pem"));
using var trustedRootCertificatesCA2 = new X509Certificate2(Path.Combine(certificatesPath, "ca2/ca2_cert.pem"));
using X509Certificate2 trustedRootCertificatesCA1 =
X509CertificateLoader.LoadCertificateFromFile(Path.Combine(certificatesPath, "ca1/ca1_cert.pem"));
Copy link

Copilot AI Nov 6, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Call to 'System.IO.Path.Combine'.

Copilot uses AI. Check for mistakes.
using X509Certificate2 trustedRootCertificatesCA1 =
X509CertificateLoader.LoadCertificateFromFile(Path.Combine(certificatesPath, "ca1/ca1_cert.pem"));
using X509Certificate2 trustedRootCertificatesCA2 =
X509CertificateLoader.LoadCertificateFromFile(Path.Combine(certificatesPath, "ca2/ca2_cert.pem"));
Copy link

Copilot AI Nov 6, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Call to 'System.IO.Path.Combine'.

Suggested change
X509CertificateLoader.LoadCertificateFromFile(Path.Combine(certificatesPath, "ca2/ca2_cert.pem"));
X509CertificateLoader.LoadCertificateFromFile(Path.Combine(certificatesPath, "ca2", "ca2_cert.pem"));

Copilot uses AI. Check for mistakes.
@pepone pepone requested a review from externl November 6, 2025 17:29
@pepone
Copy link
Member Author

pepone commented Nov 6, 2025

@externl can you take another look? I updated CI to run tests with .NET 10 too

- name: Setup .NET
uses: ./.github/actions/setup-dotnet

- uses: actions/setup-dotnet@v4
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We already have setup-botnet above, we should integrate theses settings into it

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure we only need this for .NET 10 tests, the other we run in a few more places.

What do you suggest add an extra parameter to setup-dotnet?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need both .NET 8 and .NET 10 for these builds?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, Ice assemblies always target .NET 8, only the tests are built with .NET 10 target framework.

Copy link
Member

@bernardnormier bernardnormier left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The dependency on a 9.0.* Microsoft Bcl library when using .NET 8 sounds a bit odd, but I guess that's the recommended way to write code that works with both .NET 8 and .NET 10?

# CA2008: Do not create tasks without passing a TaskScheduler
dotnet_diagnostic.CA2008.severity = none

# CA1515: Because an application's API isn't typically referenced from outside the assembly, types can be made internal
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You moved this rule because you were getting this warning for tests too?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes with .NET 10 this is enabled by default, I want to fix this in a separate PR.

using var serverCertificate =
new X509Certificate2(Path.Combine(certificatesPath, "ca1/server.p12"), "password");
using X509Certificate2 serverCertificate =
X509CertificateLoader.LoadPkcs12FromFile(Path.Combine(certificatesPath, "ca1/server.p12"), "password");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sounds correct.

@pepone
Copy link
Member Author

pepone commented Nov 11, 2025

write code that works with both .NET 8 and .NET 10?

Yes, this allow to use the new API and still target .NET 8. We can also keep the old code a disable the deprecation warnings when targeting .NET 9+ in the corresponding files.

I think using the new dependency is clear.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants