dotnet / runtime

.NET is a cross-platform runtime for cloud, mobile, desktop, and IoT apps.
https://docs.microsoft.com/dotnet/core/
MIT License
15.13k stars 4.7k forks source link

X509Certificate2 Issue in MAUI Project on M1 Macbook #77611

Open yagizhanNY opened 1 year ago

yagizhanNY commented 1 year ago

Description

I am using OPCFoundation/UA-.NETStandard library for one of my application. In this application I have to handle digital certificates. In Windows it's working well but in MacOS it's not.

When I start the app, app is creating the certificate automatically in the directory as below.

image

But the app gives Cannot access certificate private key error.

I opened an issue about this in library's repo. They said the problem might be in dotnet runtime on M1 MacOS.

Reproduction Steps

I wrote a method for receive server's certificate. You can find this method at below.

public async Task<(X509Certificate2, bool)> GetCertificate(string ipAddress)
        {
            if (_application != null) _application = null;
            if (_config != null) _config = null;

            string endpointUrl = $"opc.tcp://{ipAddress}:4840";

            _application = new ApplicationInstance
            {
                ApplicationName = "Pre-Dev OPC UA Client",
                ApplicationType = ApplicationType.Client,
                ConfigSectionName = Utils.IsRunningOnMono() ||
                DeviceInfo.Current.Platform == DevicePlatform.iOS ||
                DeviceInfo.Current.Platform == DevicePlatform.Android ? "Opc.Ua.MonoSampleClient" : "Opc.Ua.SampleClient"
            };

            try
            {
                using var stream = await FileSystem.OpenAppPackageFileAsync(_application.ConfigSectionName + ".Config.xml");
                _config = await _application.LoadApplicationConfiguration(stream, false);
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }

            bool haveAppCertificate = await _application.CheckApplicationInstanceCertificate(false, 0);
            if (!haveAppCertificate)
            {
                throw new Exception("Application instance certificate invalid!");
            }

            if (haveAppCertificate)
            {

                _config.ApplicationUri = X509Utils.GetApplicationUriFromCertificate(_config.SecurityConfiguration.ApplicationCertificate.Certificate);
                if (_config.SecurityConfiguration.AutoAcceptUntrustedCertificates)
                {
                    _autoAccept = true;
                }
                _config.CertificateValidator.CertificateValidation += new CertificateValidationEventHandler(CertificateValidator_CertificateValidation);
            }
            else
            {
                Console.WriteLine("WARN: missing application certificate, using unsecure connection.");
            }

            var selectedEndpoint = CoreClientUtils.SelectEndpoint(endpointUrl, haveAppCertificate, 15000);

            var endpointConfiguration = EndpointConfiguration.Create(_config);
            var endpoint = new ConfiguredEndpoint(null, selectedEndpoint, endpointConfiguration);

            bool isNone = IsCertificateTypeNone(endpoint);

            if (isNone == false) return (new X509Certificate2(endpoint.Description.ServerCertificate), isNone);
            else return (null, isNone);
        }

When I build and start the app firstly on Mac(MacCatalyst) app gives the There is no cert with subject ... exception as below.

Screen Shot 2022-09-28 at 08 42 13

In the second run, app gives the Cannot access certificate private key exception.

Expected behavior

Application must get all certificates successfully.

Actual behavior

It gives Cannot access certificate private key exception.

Regression?

No response

Known Workarounds

No response

Configuration

Other information

No response

dotnet-issue-labeler[bot] commented 1 year ago

I couldn't figure out the best area label to add to this issue. If you have write-permissions please help me learn by adding exactly one area label.

ghost commented 1 year ago

Tagging subscribers to this area: @dotnet/area-system-security, @vcsjones See info in area-owners.md if you want to be subscribed.

Issue Details
### Description I am using [OPCFoundation/UA-.NETStandard library](https://github.com/OPCFoundation/UA-.NETStandard) for one of my application. In this application I have to handle digital certificates. In Windows it's working well but in MacOS it's not. When I start the app, app is creating the certificate automatically in the directory as below. ![image](https://user-images.githubusercontent.com/41087670/198717780-ccd4f9bd-614c-4636-8819-082b3df874ae.png) But the app gives `Cannot access certificate private key` error. I opened an issue about this in [library's repo](https://github.com/OPCFoundation/UA-.NETStandard/issues/1939). They said the problem might be in dotnet runtime on M1 MacOS. ### Reproduction Steps I wrote a method for receive server's certificate. You can find this method at below. ```csharp public async Task<(X509Certificate2, bool)> GetCertificate(string ipAddress) { if (_application != null) _application = null; if (_config != null) _config = null; string endpointUrl = $"opc.tcp://{ipAddress}:4840"; _application = new ApplicationInstance { ApplicationName = "Pre-Dev OPC UA Client", ApplicationType = ApplicationType.Client, ConfigSectionName = Utils.IsRunningOnMono() || DeviceInfo.Current.Platform == DevicePlatform.iOS || DeviceInfo.Current.Platform == DevicePlatform.Android ? "Opc.Ua.MonoSampleClient" : "Opc.Ua.SampleClient" }; try { using var stream = await FileSystem.OpenAppPackageFileAsync(_application.ConfigSectionName + ".Config.xml"); _config = await _application.LoadApplicationConfiguration(stream, false); } catch (Exception ex) { Console.WriteLine(ex.Message); } bool haveAppCertificate = await _application.CheckApplicationInstanceCertificate(false, 0); if (!haveAppCertificate) { throw new Exception("Application instance certificate invalid!"); } if (haveAppCertificate) { _config.ApplicationUri = X509Utils.GetApplicationUriFromCertificate(_config.SecurityConfiguration.ApplicationCertificate.Certificate); if (_config.SecurityConfiguration.AutoAcceptUntrustedCertificates) { _autoAccept = true; } _config.CertificateValidator.CertificateValidation += new CertificateValidationEventHandler(CertificateValidator_CertificateValidation); } else { Console.WriteLine("WARN: missing application certificate, using unsecure connection."); } var selectedEndpoint = CoreClientUtils.SelectEndpoint(endpointUrl, haveAppCertificate, 15000); var endpointConfiguration = EndpointConfiguration.Create(_config); var endpoint = new ConfiguredEndpoint(null, selectedEndpoint, endpointConfiguration); bool isNone = IsCertificateTypeNone(endpoint); if (isNone == false) return (new X509Certificate2(endpoint.Description.ServerCertificate), isNone); else return (null, isNone); } ``` When I build and start the app firstly on Mac(MacCatalyst) app gives the `There is no cert with subject ...` exception as below. ![Screen Shot 2022-09-28 at 08 42 13](https://user-images.githubusercontent.com/41087670/192700816-cf53303f-06c4-4bd1-86db-fd964fe5f3a4.png) In the second run, app gives the `Cannot access certificate private key` exception. ### Expected behavior Application must get all certificates successfully. ### Actual behavior It gives `Cannot access certificate private key` exception. ### Regression? _No response_ ### Known Workarounds _No response_ ### Configuration - .Net6.0.402 MAUI with Blazor project. - MacOS Monterey 12.6.1 - M1 Macbook ### Other information _No response_
Author: yagizhanNY
Assignees: -
Labels: `area-System.Security`, `untriaged`
Milestone: -
vcsjones commented 1 year ago

Mac(MacCatalyst)

Can you reproduce the issue as a standard macOS application? That is, does it only occur as a catalyst application?

Secondly, is it possible for you to put together a fully-runnable sample application that reproduces the behavior?

yagizhanNY commented 1 year ago

@vcsjones thanks for comment.

It's also same on iOS application not just MacOS app.

I created a simple MAUI app for test this issue. Please change OPC UA url before tests.

yagizhanNY commented 1 year ago

I have an update. The issue still ongoing on .Net7. I created the application from scratch on my Macbook, then I tried to create the certificate in store, it worked. I am able to use certificate management with store but it still won't working with directory.

ghost commented 1 year ago

Tagging subscribers to 'os-maccatalyst': @steveisok, @akoeplinger See info in area-owners.md if you want to be subscribed.

Issue Details
### Description I am using [OPCFoundation/UA-.NETStandard library](https://github.com/OPCFoundation/UA-.NETStandard) for one of my application. In this application I have to handle digital certificates. In Windows it's working well but in MacOS it's not. When I start the app, app is creating the certificate automatically in the directory as below. ![image](https://user-images.githubusercontent.com/41087670/198717780-ccd4f9bd-614c-4636-8819-082b3df874ae.png) But the app gives `Cannot access certificate private key` error. I opened an issue about this in [library's repo](https://github.com/OPCFoundation/UA-.NETStandard/issues/1939). They said the problem might be in dotnet runtime on M1 MacOS. ### Reproduction Steps I wrote a method for receive server's certificate. You can find this method at below. ```csharp public async Task<(X509Certificate2, bool)> GetCertificate(string ipAddress) { if (_application != null) _application = null; if (_config != null) _config = null; string endpointUrl = $"opc.tcp://{ipAddress}:4840"; _application = new ApplicationInstance { ApplicationName = "Pre-Dev OPC UA Client", ApplicationType = ApplicationType.Client, ConfigSectionName = Utils.IsRunningOnMono() || DeviceInfo.Current.Platform == DevicePlatform.iOS || DeviceInfo.Current.Platform == DevicePlatform.Android ? "Opc.Ua.MonoSampleClient" : "Opc.Ua.SampleClient" }; try { using var stream = await FileSystem.OpenAppPackageFileAsync(_application.ConfigSectionName + ".Config.xml"); _config = await _application.LoadApplicationConfiguration(stream, false); } catch (Exception ex) { Console.WriteLine(ex.Message); } bool haveAppCertificate = await _application.CheckApplicationInstanceCertificate(false, 0); if (!haveAppCertificate) { throw new Exception("Application instance certificate invalid!"); } if (haveAppCertificate) { _config.ApplicationUri = X509Utils.GetApplicationUriFromCertificate(_config.SecurityConfiguration.ApplicationCertificate.Certificate); if (_config.SecurityConfiguration.AutoAcceptUntrustedCertificates) { _autoAccept = true; } _config.CertificateValidator.CertificateValidation += new CertificateValidationEventHandler(CertificateValidator_CertificateValidation); } else { Console.WriteLine("WARN: missing application certificate, using unsecure connection."); } var selectedEndpoint = CoreClientUtils.SelectEndpoint(endpointUrl, haveAppCertificate, 15000); var endpointConfiguration = EndpointConfiguration.Create(_config); var endpoint = new ConfiguredEndpoint(null, selectedEndpoint, endpointConfiguration); bool isNone = IsCertificateTypeNone(endpoint); if (isNone == false) return (new X509Certificate2(endpoint.Description.ServerCertificate), isNone); else return (null, isNone); } ``` When I build and start the app firstly on Mac(MacCatalyst) app gives the `There is no cert with subject ...` exception as below. ![Screen Shot 2022-09-28 at 08 42 13](https://user-images.githubusercontent.com/41087670/192700816-cf53303f-06c4-4bd1-86db-fd964fe5f3a4.png) In the second run, app gives the `Cannot access certificate private key` exception. ### Expected behavior Application must get all certificates successfully. ### Actual behavior It gives `Cannot access certificate private key` exception. ### Regression? _No response_ ### Known Workarounds _No response_ ### Configuration - .Net6.0.402 MAUI with Blazor project. - MacOS Monterey 12.6.1 - M1 Macbook ### Other information _No response_
Author: yagizhanNY
Assignees: -
Labels: `area-System.Security`, `untriaged`, `os-maccatalyst`
Milestone: -
jeffhandley commented 1 year ago

I'm moving this out to Future as we won't be able to address it during .NET 8. I'm also going to label this as https://github.com/dotnet/runtime/labels/help%20wanted; we could use help further debugging this to get to a root cause and proposed fix.