Failure to find private key in X509 Certificate on eToken - certificate

I have been issued a certificate that is stored on a SafeNet eToken. The public key is saved in a database on each user account. I use the code below to find a certificate on an eToken using the thumbprint. I then use the private key to generate a digital signature. It works perfectly when I run my code on my PC using IISExpress. However, when I publish the application to a server on IIS the application fails to find the certificate and therefore is unable to get the private key to sign.
I am new to cryptography and this could be the reason I am facing this issue. I am seeking your help:
Below is my code that works on IISExpress
public static X509Certificate2 GetCertificateFromStore(string thumbprint)
{
X509Store store = new X509Store(StoreName.My);
try
{
store.Open(OpenFlags.ReadOnly);
X509Certificate2Collection certCollection = (X509Certificate2Collection)store.Certificates;
X509Certificate2Collection currentCerts = certCollection.Find(X509FindType.FindByTimeValid, DateTime.Now, false);
if (currentCerts.Count > 0)
{
X509Certificate2Collection signingCert = currentCerts.Find(X509FindType.FindByThumbprint, thumbprint, true);
if (signingCert.Count > 0)
return signingCert[0];
}
return null;
}
finally
{
store.Close();
}
}
Our security team who issue me the certificate on the eToken told me to try installing the SafeNet drivers on the server which I did but has not resolved the issue. I have also tried that goes through all possible store locations and store names searching for the certificate but still not able to find the certificate

Related

403 Forbidden error while accessing Azure web api using certificate authentication

I am getting 403 Forbidden exception while accessing simple azure webapi with certificate authentication, only while accessing from asp.net web application. I am using WebClient inherited object to overide GetWebRequest to add client certificate.
public class CertificateWebClient : WebClient
{
private readonly X509Certificate2 certificate;
public CertificateWebClient(X509Certificate2 cert)
{
certificate = cert;
}
protected override WebRequest GetWebRequest(Uri address)
{
HttpWebRequest request = (HttpWebRequest)base.GetWebRequest(address);
request.ClientCertificates.Add(certificate);
return request;
}
}
And I am using the object CertificateWebClient DownloadString function to access the web api.
X509Certificate2 newCertificate = new X509Certificate2("bytearray");
CertificateWebClient webClient = new CertificateWebClient(newCertificate)
{
Proxy = new WebProxy("proxy address")
};
var result = webClient.DownloadString("https://webapiaddress/api/Values");
I am accessing the web api in the similar manner in windows forms and it works absolutely fine.
I could resolve this issue by storing and retrieving the certificate from Azure key vault in Base 64 string format. Using Convert.ToBase64String("raw certificate data") and Convert.FromBase64String("base64 cert string"), so I had to modify the above code as
X509Certificate2 newCertificate = new X509Certificate2(Convert.FromBase64String("base64 cert string"));
Only base 64 format keeps the certificate raw data intact while Adding/Retrieving certificate data to azure key vault.
The Certificate should have been ideally added to Azure key vault certificate store but the project requirement was to store it as key.

Unity WebClient SSL Timeout

I'm working on a Unity project that is reliyng on fetching data from a web API I set up on a public webserver. The server is currently set to self-signed ssl and requires the client to send certification to be able to read the data, if the client fails to send the cert the website returns with "403 forbidden".
I've tested this in the browser and postman and everything works fine.
I've also tested the exact same function in a pure visual studio project and it worked like a charm.
However, when I try this function in Unity I am met with the WebException "The request timed out
".
The way I'm currently doing it is via a WebClient, with an overrided method of WebRequest:
private void Connect()
{
ServicePointManager.CheckCertificateRevocationList = false;
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls;
ServicePointManager.ServerCertificateValidationCallback += ignoreCertCallback;
ServicePointManager.Expect100Continue = true;
using (var wc = new CertificateWebClient())
{
try
{
var responseBytes = wc.DownloadString(url);
Debug.Log(responseBytes);
Debug.Log(wc.ResponseHeaders);
}
catch (WebException e)
{
Debug.Log(e.ToString());
}
}
}
Override of WebRequest:
protected override WebRequest GetWebRequest(Uri address)
{
HttpWebRequest request = (HttpWebRequest)base.GetWebRequest(address);
X509Certificate2 certificate = new X509Certificate2(#"C:\temp\ClientCert.pfx", "password");
request.ServerCertificateValidationCallback = delegate (System.Object obj, X509Certificate X509certificate, X509Chain chain, System.Net.Security.SslPolicyErrors errors)
{
return true;
};
Debug.Log(request.RequestUri);
(request as HttpWebRequest).ClientCertificates.Add(certificate);
request.Timeout = 2000;
return request;
}
Important to note is that I've tried the exact same functions inside of Unity with the "client.badssl.com" and their cert, and that also worked like a charm, returning the correct error codes when no cert is sent and everything and If I turn off client certification on my website, everything also works like charm...
From What I understand, It might be Mono that might be the problem as the certification is self-signed and not from a verified CA... But i've not been able to find a workaround... so any help would be great
What are your BG settings? I mean: is it on AWS? Express/NodeJS? WebGL? I am facing the same issue but when testing locally it works like a charm
I would suggest: to check if it is an infrastructure problem you might want to create a certificate for your domain (eg 'goodboy.mytest.io") that is certified from some free SSL providers (I can say LetsEncrypt just for testing) and launch a local server that's using that certificate, then go in your "hosts" file (depending on OS that you are currently running) and mock your localhost as "goodboy.mytest.io", so you can check if connecting to that domain everything goes fine without additional layers (usually placed between connection "bouncing" on web)
I'm following up this too

Dart Add SSL certificate and key to HttpClient

I'm trying to secure a REST API using TLS/SSL, to do so I needed to update my client to use the public key and certificate.
The client is written in dart and here's how I implemented the SecurityContext :
SecurityContext clientContext = SecurityContext.defaultContext;
var certificate = (await rootBundle.load("assets/ssl/coastr.crt")).buffer.asInt8List();
print(certificate.toString());
clientContext.setTrustedCertificatesBytes(certificate);
/*var authorities = (await rootBundle.load('assets/ssl/coastr.ca-bundle')).buffer.asUint8List();
print(authorities.toString());
clientContext.setClientAuthoritiesBytes(authorities);*/
var key = (await rootBundle.load("assets/ssl/coastr_public.key")).buffer.asInt8List();
print(key.toString());
clientContext.usePrivateKeyBytes(key);
HttpClient client = HttpClient(context: clientContext);
HttpClientRequest request = await client.getUrl(Uri.parse(url));
HttpClientResponse response = await request.close();
The certificate (.crt file) is added without issue to the clientContext but adding the key to it returns me this error :
[ERROR:flutter/lib/ui/ui_dart_state.cc(148)] Unhandled Exception:
TlsException: Failure in usePrivateKeyBytes (OS Error:
BAD_PKCS12_DATA(pkcs8_x509.c:606)
passed a null parameter(ssl_privkey.cc:375), errno = 0)
The files I'm using are :
coastr.crt with this as a header : -----BEGIN CERTIFICATE-----
coastr_public.key with header : -----BEGIN PUBLIC KEY-----
I have no idea if I'm providing the wrong files to the client or if the error comes from elsewhere.
The files where generated using openssl.
Thank you for your help.
In general, you shouldn't have to add anything to the client to allow it to connect to a correctly configured HTTPS server. Hopefully, the server has a signed server side certificate. If that certificate is signed by a reputable CA, the client should automatically trust it. If it is signed by an in house CA, or self signed, you need to do some work. You need to provide the client with the signing certificate. In the former case that would be the root CA's certificate. In the latter case, supplying the server's certificate may work, though it's probably easier to disable the client check altogether.
The signing certificate is likely to be in CRT form as you've found. And you need to supply that exactly as you are doing. There's no need to supply any public keys as the are distributed in the certificates sent with the server hello.
Unless you want to use a client side certificate, there's no need to supply a private key, so you can skip the step that is failing. And supplying a public key to it is definitely not going to work, anyway.

Reading PKCS7 and .p12 file certificate information(subjectDN,vaildstartfrom,ValildTo..) through java

I am trying to implement Digital certificate validity utility using java. I can able to read the certification information(subjectDN, Issure info, validitity..etc) if the certificate in .cert,.cer but can't able to read certificate information from .p7b and .p12 certificate format. I have used the BouncyCastle security provider to read .p7b and .p12 certificate content but not able to get with that security provider might be i was missing on this. I am referring online resources to get some idea on this but not get guideline for this.Could you please someone give suggestion on this.
I suggest if you're looking for validity of the certificate from p12, it can be done as below :
try {
Security.addProvider(new BouncyCastleProvider());
KeyStore keyStore = KeyStore.getInstance("pkcs12");
InputStream input = new FileInputStream("pathToYourP12");
keyStore.load(input, "password");
certFromKeyStore = (X509Certificate)keyStore.getCertificate("keyStoreAllias");
certFromKeyStore.checkValidity();
}
catch(Exception e)
{
// catch exception like if no valid p12 existing at the location, invalid password, or any other exception should get catch properly.
}

Using custom certificate in FiddlerCore

This is the process I followed :-`
var certX = Fiddler.CertMaker.oCertProvider.GetCertificateForHost("<Machine Name>");
File.WriteAllBytes(#"D:\PFX.pfx", certX.Export(X509ContentType.SerializedCert));
Once done with this. I restarted the Demo application and tried to load certificate from disk
X509Certificate2 certTry = new X509Certificate2(#"D:\PFX.PFX", "1", X509KeyStorageFlags.UserKeySet |
X509KeyStorageFlags.PersistKeySet |
X509KeyStorageFlags.Exportable);
oSecureEndpoint = FiddlerApplication.CreateProxyEndpoint(iSecureEndpointPort, true, certTry);
This works but when I do.
WriteCommandResponse("Result: " + Fiddler.CertMaker.trustRootCert().ToString());
It fails with error saying cannot trust root certification; Not Found
What am I doing wrong here?
My intent is the Decrypt HTTPS traffic using a custom certificate.
Let's step back a bit-- what do you hope to accomplish by storing the certificate Fiddler generates to disk, then reloading it later?
The likely problem here is that your method doesn't write the private key to the target PFX file, so you can't subsequently use the PFX to encrypt traffic.
As #EricLaw pointed out issue was with the PFX. Certificate that
Fiddler.CertMaker.GetRootCertificate();
generates does not have the private key of the certificate. So to save the certificate just writing the above certificate won't be enough. The way around it is to open user's root cert store and then get the certificate out of it along with it's private key (code example below). This certificate can then be used in future sessions.
X509Store certStore = new X509Store(StoreName.Root, StoreLocation.CurrentUser);
// Try to open the store.
certStore.Open(OpenFlags.ReadOnly);
// Find the certificate that matches the name.
X509Certificate2Collection certCollection = certStore.Certificates.Find(X509FindType.FindBySubjectName, "DO_NOT_TRUST_FiddlerRoot", false);
X509Certificate2 certTry = new X509Certificate2(#"D:\PFX.PFX", "1", X509KeyStorageFlags.UserKeySet |
X509KeyStorageFlags.PersistKeySet |
X509KeyStorageFlags.Exportable);
Exportable is optional, but PersistKeySet is required otherwise the certificate won't contain the private key.