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.
Related
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
There is already a valid cert in my keystore and handshake process with server is working. When another cert with different CN is added in the same keystore and connect with server, get the error from server "Access denied, invalid endpoint". I think when connecting with server, the second cert is used in ssl connection when there are two valid certs for client certs usage (the existing one and the newly imported one). What I want to know is which one is used if there are one than more valid certs in keystore. Is it related with certs alias?
The following is code snippet for socket connection.
try {
SSLSocketFactory factory = null;
try {
SSLContext ctx;
KeyManagerFactory kmf;
KeyStore ks;
char[] passphrase = "*****".toCharArray();
ctx = SSLContext.getInstance("TLSv1.2");
kmf = KeyManagerFactory.getInstance("SunX509");
ks = KeyStore.getInstance("JKS");
ks.load(new FileInputStream("testkeys"), passphrase);
kmf.init(ks, passphrase);
ctx.init(kmf.getKeyManagers(), null, null);
factory = ctx.getSocketFactory();
} catch (Exception e) {
throw new IOException(e.getMessage());
}
SSLSocket socket = (SSLSocket)factory.createSocket(host, port);
String[] cipherSuites = socket.getSupportedCipherSuites();
socket.setEnabledCipherSuites( cipherSuites );
socket.setNeedClientAuth(false);
socket.startHandshake();
Similar Which key and certificate from keystore and truststore is used when there are many? for server.
For SunX509 KeyManagerFactory:
at initialization it creates a HashMap containing all the privatekey entries from the keystore, keyed by alias;
handshake calls chooseClientAlias which, for each <=1.2 certificate_type or 1.3 sigalg specified/requested by the server (either called keyType in the code) checks each HashMap entry in HashIterator order (which is determined by a variable number of low bits of a value derived from the hashcode of the alias) to see if the leaf cert has that keytype, and any cert in the chain is issued by one of the CAs specified by the server unless the server left the CA list empty in which case this part of the check is skipped.
If you're getting the wrong cert-and-key selected, check if the server is specifying a correct CA-list in its CertificateRequest message. You can do this on the Java client side by running with sysprop javax.net.debug=ssl:handshake, or except in 1.3 a network level tool like wireshark or tcpdump.
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.
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.
}
How can I enable certificate pinning using OkHttp for my Android / Java application?
The OkHttp documentation gives us a clear way to do this complete with sample code. In case it goes away, here it is pasted in below:
1. Add a broken CertificatePinner and make a request.
Any request will do, even if it doesn't exist. You can do this in your Android application, or just create a dummy Java application and run this as well.
For example, to pin https://publicobject.com, start with a broken
configuration:
String hostname = "publicobject.com";
CertificatePinner certificatePinner = new CertificatePinner.Builder()
.add(hostname, "sha256/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=")
.build();
OkHttpClient client = OkHttpClient.Builder()
.certificatePinner(certificatePinner)
.build();
Request request = new Request.Builder()
.url("https://" + hostname)
.build();
client.newCall(request).execute();
As expected, this fails with a certificate pinning exception:
javax.net.ssl.SSLPeerUnverifiedException: Certificate pinning failure!
Peer certificate chain:
sha256/afwiKY3RxoMmLkuRW1l7QsPZTJPwDS2pdDROQjXw8ig=: CN=publicobject.com, OU=PositiveSSL
sha256/klO23nT2ehFDXCfx3eHTDRESMz3asj1muO+4aIdjiuY=: CN=COMODO RSA Secure Server CA
sha256/grX4Ta9HpZx6tSHkmCrvpApTQGo67CYDnvprLg5yRME=: CN=COMODO RSA Certification Authority
sha256/lCppFqbkrlJ3EcVFAkeip0+44VaoJUymbnOaEUk7tEU=: CN=AddTrust External CA Root
Pinned certificates for publicobject.com:
sha256/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=
at okhttp3.CertificatePinner.check(CertificatePinner.java)
at okhttp3.Connection.upgradeToTls(Connection.java)
at okhttp3.Connection.connect(Connection.java)
at okhttp3.Connection.connectAndSetOwner(Connection.java)
2. Configure your OkHttp Client Correctly:
CertificatePinner certificatePinner = new CertificatePinner.Builder()
.add("publicobject.com", "sha256/afwiKY3RxoMmLkuRW1l7QsPZTJPwDS2pdDROQjXw8ig=")
.add("publicobject.com", "sha256/klO23nT2ehFDXCfx3eHTDRESMz3asj1muO+4aIdjiuY=")
.add("publicobject.com", "sha256/grX4Ta9HpZx6tSHkmCrvpApTQGo67CYDnvprLg5yRME=")
.add("publicobject.com", "sha256/lCppFqbkrlJ3EcVFAkeip0+44VaoJUymbnOaEUk7tEU=")
.build();
That's all there is to it!
This method will give you all your certificates in the entire chain. This is advantageous since it's safer as only one certificate in the chain has to match for the request to succeed. It's likely at some point in the future, your certificates will be updated, but as long as the entire chain isn't updated, your application shouldn't break.