locked
Strange behaviour importing PFX files into the app certificate store RRS feed

  • Question

  • I have tested with the following setup:

    Code used to import the PFX information files (those are not PFX files, you know, the folder MY inside the app folder):

    string base64Encoded = Windows.Security.Cryptography.CryptographicBuffer.EncodeToBase64String(content);
     await CertificateEnrollmentManager.ImportPfxDataAsync(
     base64Encoded,
     credentialPassword,
     ExportOption.NotExportable,
     KeyProtectionLevel.NoConsent,
     InstallOptions.None,
     credentialIdentifier);
    • 2 freshly generated certificates using the special identifier for Windows 8 apps
    • Importing the PFX files using
    Here is what I discovered:
    • If I connect using HttpClilent, to the first subscription (which equals the FIRST PFX information file) it works.
    • Then I connect using HttpClient to the second subscription (which equals the SECOND PFX information file), it works.
    • BUT when I now (in the this order), try to connect to the FIRST subscription again (which equals the FIRST PFX information file imported) it does not work. BUT I can connect with the second one, without any problems, at this specific step

    I honestly think, that the ….ImportPfxDataAsync…. method is broken, in terms of PFX information file registration. Looks like it is loading the required info file, and saving it temporarily in some specific area. At the second call it is doing it right as well, but it is unable to revert to the first information file after overwriting it with the second one.

    And the next thing is: How can I remove those PFX files from the app cert store? Seems to be impossible. If not, how can I do that?




    • Edited by Ilija Injac [MVP] Thursday, November 14, 2013 6:17 PM Added additional question
    Thursday, November 14, 2013 1:47 AM

Answers

  • Here's a sample that I just tested using two client certificates and the Windows.Web.Http.HttpClient class using the code below where I submit two HTTP requests in two successive clicks with two independent Client certificates. The below approach works. It's just a simple approach, to show that it works...There's no special error handling such as multiple certificates found etc.

    If you can share your System.Net code, it will help throw some more light on the issue.

    Btw, the recommended approach starting Windows 8.1, is to use Windows.Web.Http.HttpClient class instead of the old System.Net namespace.

     private async void btnSendRequest_Click(object sender, RoutedEventArgs e)
            {
                Certificate cert = await LoadCertificateAsync();
                await SendHttpRequest(cert);
            }
    
            private async Task<Certificate> LoadCertificateAsync()
            {
                var picker = new FileOpenPicker();
    
                picker.SuggestedStartLocation = PickerLocationId.Desktop;
                picker.FileTypeFilter.Add(".pfx");
                picker.ViewMode = PickerViewMode.List;
    
                var file = await picker.PickSingleFileAsync();
    
                IBuffer buffer = await FileIO.ReadBufferAsync(file);
    
                string certificateData = CryptographicBuffer.EncodeToBase64String(buffer);
    
                string password = "";
    
                await CertificateEnrollmentManager.ImportPfxDataAsync(
                        certificateData,
                        password,
                        ExportOption.NotExportable,
                        KeyProtectionLevel.NoConsent,
                        InstallOptions.None,
                        file.DisplayName);
    
                CertificateQuery query = new CertificateQuery();
                query.FriendlyName = file.DisplayName;
    
                IReadOnlyCollection<Certificate> certs = await CertificateStores.FindAllAsync(query);
                if (certs.Count > 1)
                {
                    txtOut.Text = "Something funny happened";
                    return null;
                }
                else return certs.ElementAt(0);
    
            }
            private async Task<string> SendHttpRequest(Certificate cert)
            {
                try
                {
                    HttpBaseProtocolFilter bpf = new HttpBaseProtocolFilter();
                    bpf.IgnorableServerCertificateErrors.Add(ChainValidationResult.Untrusted);
                    bpf.ClientCertificate = cert;
    
                    HttpClient aClient = new HttpClient(bpf);
                    Uri serverUri = new Uri(txtServer.Text);
                    String response = await aClient.GetStringAsync(serverUri);
                    txtOut.Text = "Response: " + response;
                    return response;
                }
                catch (Exception oEx)
                {
                    return "Exception: " + oEx.Message;
                }
                return "";
            }


    Windows Store Developer Solutions, follow us on Twitter: @WSDevSol|| Want more solutions? See our blog

    Saturday, November 16, 2013 2:09 AM
    Moderator
  • Yes, I don't think you can delete the installed certificate. ImportPfxDataAsync installs the certificate in the MY store, and CertificateStores.GetStoreByName doesn't accept MY string from which you could've retrieved the CertificateStore and then called Delete to remove a cert.


    Windows Store Developer Solutions, follow us on Twitter: @WSDevSol|| Want more solutions? See our blog

    Saturday, November 16, 2013 2:40 AM
    Moderator

All replies

  • Are you using System.Net.Http.HttpClient class or are you using the new Windows.Web.Http.HttpClient class that was introduced in Windows 8.1?

    Windows Store Developer Solutions, follow us on Twitter: @WSDevSol|| Want more solutions? See our blog

    Saturday, November 16, 2013 12:33 AM
    Moderator
  • I am using System.Net.Http.HttpClient.
    Saturday, November 16, 2013 1:40 AM
  • Here's a sample that I just tested using two client certificates and the Windows.Web.Http.HttpClient class using the code below where I submit two HTTP requests in two successive clicks with two independent Client certificates. The below approach works. It's just a simple approach, to show that it works...There's no special error handling such as multiple certificates found etc.

    If you can share your System.Net code, it will help throw some more light on the issue.

    Btw, the recommended approach starting Windows 8.1, is to use Windows.Web.Http.HttpClient class instead of the old System.Net namespace.

     private async void btnSendRequest_Click(object sender, RoutedEventArgs e)
            {
                Certificate cert = await LoadCertificateAsync();
                await SendHttpRequest(cert);
            }
    
            private async Task<Certificate> LoadCertificateAsync()
            {
                var picker = new FileOpenPicker();
    
                picker.SuggestedStartLocation = PickerLocationId.Desktop;
                picker.FileTypeFilter.Add(".pfx");
                picker.ViewMode = PickerViewMode.List;
    
                var file = await picker.PickSingleFileAsync();
    
                IBuffer buffer = await FileIO.ReadBufferAsync(file);
    
                string certificateData = CryptographicBuffer.EncodeToBase64String(buffer);
    
                string password = "";
    
                await CertificateEnrollmentManager.ImportPfxDataAsync(
                        certificateData,
                        password,
                        ExportOption.NotExportable,
                        KeyProtectionLevel.NoConsent,
                        InstallOptions.None,
                        file.DisplayName);
    
                CertificateQuery query = new CertificateQuery();
                query.FriendlyName = file.DisplayName;
    
                IReadOnlyCollection<Certificate> certs = await CertificateStores.FindAllAsync(query);
                if (certs.Count > 1)
                {
                    txtOut.Text = "Something funny happened";
                    return null;
                }
                else return certs.ElementAt(0);
    
            }
            private async Task<string> SendHttpRequest(Certificate cert)
            {
                try
                {
                    HttpBaseProtocolFilter bpf = new HttpBaseProtocolFilter();
                    bpf.IgnorableServerCertificateErrors.Add(ChainValidationResult.Untrusted);
                    bpf.ClientCertificate = cert;
    
                    HttpClient aClient = new HttpClient(bpf);
                    Uri serverUri = new Uri(txtServer.Text);
                    String response = await aClient.GetStringAsync(serverUri);
                    txtOut.Text = "Response: " + response;
                    return response;
                }
                catch (Exception oEx)
                {
                    return "Exception: " + oEx.Message;
                }
                return "";
            }


    Windows Store Developer Solutions, follow us on Twitter: @WSDevSol|| Want more solutions? See our blog

    Saturday, November 16, 2013 2:09 AM
    Moderator
  • That's quite interesting and I have to admit, that I NEVER thought, to get answer, and especially not a detailed answer like this :) Thanks!

    My code is hosted on GitHub. Here is the CertificateCredentails class, that I am using to load the certificate information files into the app-cert-store: https://github.com/Injac/AzureManagmentWinRT/blob/master/AzureManamgentWinRT/Credentials/CertificateCredentials.cs

    The main difference is that I use System.Net.Http.HttpClient, and that I am not listing the certificates. I need the different certificates to be able to manage different Azure subscriptions with and/or different management certificates.

    How can I remove those certificates from the app-cert-store? I don't think that is possible.

    Saturday, November 16, 2013 2:22 AM
  • Yes, I don't think you can delete the installed certificate. ImportPfxDataAsync installs the certificate in the MY store, and CertificateStores.GetStoreByName doesn't accept MY string from which you could've retrieved the CertificateStore and then called Delete to remove a cert.


    Windows Store Developer Solutions, follow us on Twitter: @WSDevSol|| Want more solutions? See our blog

    Saturday, November 16, 2013 2:40 AM
    Moderator
  • Ok. Those files are about 3KB in size. That's acceptable. The user has to uninstall the app, to clean that local directory where the PFX files are located. That is for example:

    C:\Users\[UserName]\AppData\Local\Packages\exgripLLC.ExGripLiveSDKTestApp_znpms8j888tp8\AC\Microsoft\SystemCertificates\My\Certificates

    I will change the implementation today, and add the "account-management" functionality as well.

    Thank you for your help Prashant.

    Saturday, November 16, 2013 2:44 AM