Installing client certificates in Windows Store XAML apps - c#

I would like to use client certificate authentication in Windows Store XAML app. Using makecert i have created a self-signed CA and client certificates, the authentication works in IIS/ASP.NET + browser (IE10,Chrome, etc.) fine.
Now I wanted to use it in Windows Store app, but am unsure on how to actually install the certificate. I have a cert.pfx file that i imported to IE10.
Here is the code I use to consume HTTP service over SSL.
HttpClientHandler handler = new HttpClientHandler();
handler.ClientCertificateOptions = ClientCertificateOption.Automatic;
HttpClient client = new HttpClient(handler);
Not sure whats the difference between ClientCertificateOption.Automatic and ClientCertificateOption.Manual.
When I try to connect the certificate is not being presented to the server and i get 401 error I am guessing that the certificate is not present in app cert store and thus nothing is being sent to the server. How do I install the cert then?
Should I use CertificateEnrollmentManager.ImportPfxDataAsync() method? if so how can i convert .pfx to 'Base64-encoded PFX message'
Should pfx contain private key?
Or maybe I should use Certificates extension as described here: http://msdn.microsoft.com/en-us/library/windows/apps/hh464981.aspx#certificates_extension_content

The following code will load a pfx file and create a base64 encoded string that can be used by ImportPfxDataAsync method:
StorageFolder packageLocation = Windows.ApplicationModel.Package.Current.InstalledLocation;
StorageFolder certificateFolder = await packageLocation.GetFolderAsync("Certificates");
StorageFile certificate = await certificateFolder.GetFileAsync("YourCert.pfx");
IBuffer buffer = await Windows.Storage.FileIO.ReadBufferAsync(certificate);
string encodedString = Windows.Security.Cryptography.CryptographicBuffer.EncodeToBase64String(buffer);
This assumes that you put your certificate in 'Certificates' folder.
You may want to have a look at http://www.piotrwalat.net/client-certificate-authentication-in-asp-net-web-api-and-windows-store-apps/ this walks through end-to-end scenario of using client certificates in windows 8 app to communicate with asp.net web api.

Related

How to get Azure Cloud Service details from App service via Code, .NET

Running the following code in Azure App service, which try to get details of a cloud service in the same Azure subscription, and get the exception about Certificate is is not associated with the subscription.
Although, under the subscription blade, under "Management certificates"
the certificate does exists and authorized.
X509Store certStore = new X509Store(StoreName.My, storeLocation);
certStore.Open(OpenFlags.ReadOnly);
X509Certificate2Collection certCollection = certStore.Certificates.Find(X509FindType.FindByThumbprint, prodThumbprint, false);
if (certCollection.Count > 0)
CredentialsProd = new CertificateCloudCredentials(DBConstants.AZURE_SUBSCRIPTION_ID_PROD, certCollection[0]);
using (var client = new ComputeManagementClient(Credentials))
{
var t = client.HostedServices.GetDetailedAsync(serviceName, CancellationToken);
}
The exception:
ForbiddenError: The server failed to authenticate the request. Verify that the certificate is valid and is associated with this subscription.
The certificate in the subscription:
The certificate in the App service
To use a certificate that is uploaded to or imported into App Service, first make it accessible to your application code. You do this with the WEBSITE_LOAD_CERTIFICATES app setting. For more detail information, please refer to Use an SSL certificate in your application code in Azure App Service.
Add an app setting called WEBSITE_LOAD_CERTIFICATES and set its value to the thumbprint of the certificate. To make multiple certificates accessible, use comma-separated thumbprint values. To make all certificates accessible, set the value to *.

Password fails when Installing PFX from Remote Win2012 CA on a Win7/2008 machine

I've crafted a WCF service that accesses a remote CA using CERTENROLL and CERTCLIENT libs. My GenerateCertificate request takes a password that's used in the enrollment request. I return metadata about the generated cert and the Base64 string of the raw bytes in the response XML.
If I take the raw cert string and save it as a local .pfx file I can install it easy breezy on a Win10 or 2012 machine. However, when I try it on a Win7 or 2008 machine the password doesn't match.
I'm supplying an X509CertificateRequestCmc request that's intitialized from an inner X509CertificateRequestPkcs10 request which is initialized from a template.
Upon first encountering this error I tried to apply an OS Version CryptAttribute to either one of the request layers without success.
CX509AttributeOSVersionClass os = new CX509AttributeOSVersionClass();
os.InitializeEncode("6.1.7601");
CX509AttributesClass attribs = new CX509AttributesClass();
attribs.Add((CX509Attribute)os);
CCryptAttributeClass atty = new CCryptAttributeClass();
atty.InitializeFromValues(attribs);
request.CryptAttributes.Add(atty);
I'm only responsible for the WebService tier, I don't have access to the PKI store directly. My dev server app pool has been set to run as an allowed AD account on the PKI server and I don't have that account's password.
Is it me or the store?
I invoked a ticket to MS on this. They said there's a known issue where Base64 pfx files will not install on Win7 & 2008 systems. The answer is to decode the Base64 and install via binary. Careful not to convert to .cer, you'll lose the private key.

Installing a pfx file with C# seems different to manually installing it

I have a c# program which installs a pfx file (Code below)
X509Certificate2 cert;
cert = new X509Certificate2(#"myCert.pfx", "password");
if (cert != null)
{
var store = new X509Store(StoreName.Root, StoreLocation.CurrentUser);
store.Open(OpenFlags.ReadWrite);
if (!store.Certificates.Contains(cert))
{
store.Add(cert);
}
}
This seems to add the cert into the correct place when I view it in the management console. However I have a websocket server in c# that will pick it out of the store and use it for its ssl connections to the browser however the browsers all fail due to not having authentication to the cert.
However if I were to install it manually (clicking the cert) and installing it to the same location everything works fine.
NOTE:It is Self-Signed
How would I fix this problem
If the certificate is self-signed, you have to use it as well for the HTTPS page that holds the javascript code connecting to the websocket, so the browser can prompt you to accept the certificate.
You can retrieve the certificate using for example:
X509Store store = new X509Store(StoreName.My, StoreLocation.LocalMachine);
store.Open(OpenFlags.ReadOnly);
var certificate = store.Certificates[1];
store.Close();
And then use it for your WebSocket server. I don't know which .NET WebSocket server are you using, but in WebSocketListener is done this way.

Using secured websocket in C#

I'm using Fleck to implement websocket functionality in my MVC application. On the local setup I have https scheme with self signed certificate, whereas on production setup, I have paid certificate.
This is the syntax given in docs.
var server = new WebSocketServer("wss://0.0.0.0:8431");
server.Certificate = new X509Certificate2("MyCert.pfx");
server.Start(socket =>
{
//...use as normal
});
Here instead of MyCert.pfx, what should be given in case of self signed certificate / [aid certificate? Should it be a path? After providing only name, it gives error System.Security.Cryptography.CryptographicException: The system cannot find the file specified..
Yes, The parameter should be a file path, you can placed pfx file in AppData directory, And use Server.MapPath("~/App_Data/MyCert.pfx")

How to load another's certificate to my local certificate store?

I have a certificate (.pem file) that is distributed by another service vendor. I downloaded the certificate from the vendor and saved it to my local drive. In my WCF client, I am trying to load this certificate from the local drive and it is giving me an error “The private key is not present in the X.509 certificate” when communicating with the service. I was told that I need to load this certificate to my local certificate store to resolve this error. Can anyone provide some directions? Thanks!
I have the below function to load certificate from the path specified in the file parameter.
public static X509Certificate LoadCertificate(string file)
{
try
{
return X509Certificate.CreateFromCertFile(file);
}
catch (System.Security.Cryptography.CryptographicException)
{
string filestr = File.ReadAllText(file);
StringBuilder sb = new StringBuilder(filestr.Remove(0, filestr.IndexOf("-----BEGIN CERTIFICATE-----")));
sb.Replace("-----BEGIN CERTIFICATE-----", "");
sb.Replace("-----END CERTIFICATE-----", "");
//Decode
try
{ //see if the file is a valid Base64 encoded cert
byte[] certBytes = Convert.FromBase64String(sb.ToString());
return new X509Certificate(certBytes);
}
catch (System.FormatException)
{
throw;
}
}
}
In my WCF client, it is loading the certificate that was created from LoadCertificate() function.
public X509Certificate Certificate { get; set; }
ClientCredentials loginCredentials = new ClientCredentials();
loginCredentials.UserName.UserName = this.UserId;
loginCredentials.UserName.Password = this.Password;
loginCredentials.ClientCertificate.Certificate = new X509Certificate2(this.Certificate);
Your code says you are trying to use the certificate to authenticate the client to the server, in addition to providing a username and a password. That's pretty bizarre but I guess possible. You will need the private keys associated with that certificate for that purpose, as the client will need them to encrypt the communication so the server can use the certificate to decrypt and verify that the client is legit. A .pem file can contain both public and private keys but maybe the one that was sent to you does not?
My guess is that really you only wanted the client to connect to a server that is using this certificate to identity itself and encrypt the communication. If so, all the client needs to do is import the certificate locally so it can compare against this local version when the server sends it when the client first connects to it.
Do to that, Microsoft made double clicking on a .pem file in a file browser start the certificate import wizard. But in case that does not work for you, here is the hard way:
Start - run - mmc
File - Add/Remove snap-in
Select "certificates" - click Add - choose Computer Account - Local computer
Close snap-in window with OK
Now browse to Certificates (Local computer) - Personal - Certificates
Right click - All Tasks - Import

Categories

Resources