How to pass client ceritficate in Retrofit API call (kotlin) - kotlin

I am trying to convert the below curl command to retrofit api call
curl -k https:/api/health --cert client.crt --key client.key
The below code seems to not work.
var keyStore: KeyStore = KeyStore.getInstance("PKCS12")
val trustManagerFactory: TrustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm())
val t = trustManagerFactory.init(keyStore)
var trustManagers = trustManagerFactory.trustManagers
var trustManager = trustManagers[0] as X509TrustManager
var sslContext: SSLContext = SSLContext.getInstance("TLS")
val y= sslContext.init(null, arrayOf(trustManager), null)
var sslSocketFactory: SSLSocketFactory = sslContext.socketFactory

Related

How to use SSL certificate in groovy script with http builder

How I can use SSL (CA) certificate (.pem file) in a Groovy script while using http-builder for making API calls.
I am looking for something like the line below but sslContext is not available in http-builder:0.7.2
http.client.sslContext = sslContext
I have tried the below code
def health() {
HTTPBuilder http = new HTTPBuilder(baseURL)
def sslContext = SSLContext.getInstance('TLS')
sslContext.init(null, [certificate] as TrustManager[], null)
**http.client.sslContext = sslContext**
http.get(path: "/health") { req ->
response.success = { resp, json ->
println "Success! ${resp.status}"
}
response.failure = { resp, json ->
println "Request failed with status ${resp.status}"
}
}
}
Expectation:
HttpBuilder should take SSL certificate and make an API call (GET) to fetch response from the server.

LetsEncrypt certificate returns CertPathValidatorException

Good evening everyone,
I'm trying to do do SSL Pinning for my app and the Lets Encrypt certificate (ISRG Root X1) is returning CertPathValidatorException: Trust anchor for certification path not found.
I'm on Android Studios using Kotlin, using Fuel for the web requests, here is the code I have
fun pinning(ctx: Context): Pair<SSLSocketFactory, KeyStore> {
val cf: CertificateFactory = CertificateFactory.getInstance("X.509")
val caInput: InputStream = BufferedInputStream(ctx.resources.openRawResource(R.raw.isrgrootx1))
val ca: X509Certificate = caInput.use {
cf.generateCertificate(it) as X509Certificate
}
Log.println(Log.DEBUG, "SYSTEM-CA", ca.subjectDN.toString())
// Create a KeyStore containing our trusted CAs
val keyStoreType = KeyStore.getDefaultType()
val keyStore = KeyStore.getInstance(keyStoreType).apply {
load(null, null)
setCertificateEntry("ca", ca)
}
// Create a TrustManager that trusts the CAs inputStream our KeyStore
val tmfAlgorithm: String = TrustManagerFactory.getDefaultAlgorithm()
val tmf: TrustManagerFactory = TrustManagerFactory.getInstance(tmfAlgorithm).apply {
init(keyStore)
}
// Create an SSLContext that uses our TrustManager
val context: SSLContext = SSLContext.getInstance("TLS").apply {
init(null, tmf.trustManagers, null)
}
return Pair(context.socketFactory, keyStore)
}
val (pin, key) = pinning(this)
FuelManager.instance.socketFactory = pin
FuelManager.instance.keystore = key
Log.println(Log.INFO, "FUEL-MANAGER", "Imported instances successfully")
The FuelManager is run as soon as the app starts (override fun onStart())

NSUrlSession: Challenge NSURLAuthenticationMethodServerTrust fails only when client certificate is also needed

we want to connect our app to our IIS webservice. We use self signed certificates and also a client certificate for authentication.
When the webservice doesn't require client certificate authentication, everything works fine, NSURLAuthenticationMethodServerTrust gets called and the request continues.
But when I activate client certificate authentication on our server, after DidReceiveChallenge with NSURLAuthenticationMethodServerTrust as the challenge, DidCompleteWithError gets called. Error message is: "The certificate for this server is invalid. You might be connecting to a server that is pretending to be "192.168.221.118" which could put your confidential information at risk.
Note: "NSURLAuthenticationMethodClientCertificate" never gets called, the app crashes before that.
The client certificate is signed by the intermediate certificate, so I don't understand why the ServerTrust Challenge fails.
Also: in my opinion it should not be necessary, but I also tried adding the client certificate to the collection of AnchorCertificates of the Sectrust.
Thanks in advance for your help.
Here is my code:
private class SessionDelegate : NSUrlSessionDataDelegate, INSUrlSessionDelegate
{
private Action<bool, string> completed_callback;
private string antwortCache;
private int status_code;
public SessionDelegate(Action<bool, string> completed)
{
completed_callback = completed;
antwortCache = "";
}
public override void DidReceiveChallenge(NSUrlSession session, NSUrlSessionTask task, NSUrlAuthenticationChallenge challenge, Action<NSUrlSessionAuthChallengeDisposition, NSUrlCredential> completionHandler)
{
if (challenge.PreviousFailureCount == 0)
{
if (challenge.ProtectionSpace.AuthenticationMethod.Equals("NSURLAuthenticationMethodServerTrust"))
{
// GetParent is correct, because I'm too lazy to copy the certs into to the correct folders...
var path = Directory.GetParent(GlobaleObjekte.SSLZertifikatePath);
var caPath = Path.Combine(path.FullName, "ca.cert.der");
var caByteArray = File.ReadAllBytes(caPath);
var caCert = new X509Certificate2(caByteArray);
var interPath = Path.Combine(path.FullName, "intermediate.cert.der");
var interByteArray = File.ReadAllBytes(interPath);
var interCert = new X509Certificate2(interByteArray);
var secTrust = challenge.ProtectionSpace.ServerSecTrust;
var certCollection = new X509CertificateCollection();
certCollection.Add(caCert);
certCollection.Add(interCert);
secTrust.SetAnchorCertificates(certCollection);
var credential = new NSUrlCredential(secTrust);
completionHandler(NSUrlSessionAuthChallengeDisposition.UseCredential, credential);
return;
}
if (challenge.ProtectionSpace.AuthenticationMethod.Equals("NSURLAuthenticationMethodClientCertificate"))
{
var path = Directory.GetParent(GlobaleObjekte.SSLZertifikatePath);
var certPath = Path.Combine(path.FullName, "client.pfx");
var certByteArray = File.ReadAllBytes(certPath);
var cert = new X509Certificate2(certByteArray, Settings.WSClientCertPasswort);
var ident = SecIdentity.Import(certByteArray, Settings.WSClientCertPasswort);
var credential = new NSUrlCredential(ident, new SecCertificate[] { new SecCertificate(cert) }, NSUrlCredentialPersistence.ForSession);
completionHandler(NSUrlSessionAuthChallengeDisposition.UseCredential, credential);
return;
}
if (challenge.ProtectionSpace.AuthenticationMethod.Equals("NSURLAuthenticationMethodHTTPBasic"))
{
var credential = new NSUrlCredential(Settings.WebserviceBenutzer, Settings.WebservicePasswort, NSUrlCredentialPersistence.ForSession);
completionHandler(NSUrlSessionAuthChallengeDisposition.UseCredential, credential);
return;
}
completed_callback(false, "Unbekannte Authentifizierungsanfrage: " + challenge?.ProtectionSpace?.AuthenticationMethod);
}
else
{
completed_callback(false, "Authentifizierung fehlgeschlagen: " + challenge?.ProtectionSpace?.AuthenticationMethod);
}
}
}
I finally found a solution. I had to create the credential object in a different way. Instead of adding the certificates to the SecTrust and create the credential with the SecTrust as a parameter, I had to create a identity from the client certificate and then create the credential with the identity and the other certificates as parameters:
if (challenge.ProtectionSpace.AuthenticationMethod.Equals("NSURLAuthenticationMethodServerTrust"))
{
var path = Directory.GetParent(GlobaleObjekte.SSLZertifikatePath);
var caPath = Path.Combine(path.FullName, "ca.cert.der");
var caByteArray = File.ReadAllBytes(caPath);
var caCert = new SecCertificate(caByteArray);
var interPath = Path.Combine(path.FullName, "intermediate.cert.der");
var interByteArray = File.ReadAllBytes(interPath);
var interCert = new SecCertificate(interByteArray);
var clientPath = Path.Combine(path.FullName, "client.pfx");
var clientByteArray = File.ReadAllBytes(clientPath);
var clientCert = new X509Certificate2(clientByteArray, Settings.WSClientCertPasswort);
//var secTrust = challenge.ProtectionSpace.ServerSecTrust;
//var certCollection = new X509CertificateCollection();
//certCollection.Add(caCert);
//certCollection.Add(interCert);
//certCollection.Add(cert);
//secTrust.SetAnchorCertificates(certCollection);
//var credential = new NSUrlCredential(secTrust);
var identity = SecIdentity.Import(clientCert);
var credential = new NSUrlCredential(identity, new SecCertificate[] { caCert, interCert }, NSUrlCredentialPersistence.ForSession);
completionHandler(NSUrlSessionAuthChallengeDisposition.UseCredential, credential);
return;
}

"X509.LocalMachine.My.SubjectDistinguishedName.Find" always return null

We are loading the X509 certificates for IdentityServer4 in .NET Core Web Application, but it always returns null. What is the default store location when we use X509.LocalMachine.My.SubjectDistinguishedName.Find method? How we can load certificate if we embedded source certificates with solution?
Here is our startup.cs file:
private static void ConfigureSigningCerts(IServiceCollection services)
{
var keys = new List<SecurityKey>();
var name = "CertName_IdentityServer";
//The one that expires last at the top
var certs = X509.LocalMachine.My.SubjectDistinguishedName.Find("CN=" + name, false)
.Where(o => DateTime.UtcNow >= o.NotBefore)
.OrderByDescending(o => o.NotAfter);
if (!certs.Any()) throw new Exception("No valid certificates could be found.");
//Get first (in desc order of expiry) th
var signingCert = certs.FirstOrDefault();
if (signingCert == null) throw new InvalidOperationException("No valid signing certificate could be found.");
var signingCredential = new SigningCredentials(new X509SecurityKey(signingCert), "RS256");
services.AddSingleton<ISigningCredentialStore>(new DefaultSigningCredentialsStore(signingCredential));
foreach (var cert in certs)
{
var validationCredential = new SigningCredentials(new X509SecurityKey(cert), "RS256");
keys.Add(validationCredential.Key);
}
services.AddSingleton<IValidationKeysStore>(new DefaultValidationKeysStore(keys));
}
We have used following command to create self-signed certificate:
makecert -r -pe -n "CN=CertName_IdentityServer" -b 01/01/2015 -e 01/01/2039 -eku 1.3.6.1.5.5.7.3.3 -sky signature -a sha256 -len 2048 identityserver.cer
The X509Certificate2 class can be constructed using a byte[] or file path as well as being returned from the certificate store.
e.g:
var assembly = typeof(Startup).GetTypeInfo().Assembly;
/*
* IdentityServer\
* Certificates\
* cert.cer
*
* {assembly name}.{directory}.{file name}
*/
using (Stream resource = assembly.GetManifestResourceStream("IdentityServer.Certificates.cert.cer"))
using (var reader = new BinaryReader(resource))
{
signingCert = new System.Security.Cryptography.X509Certificates.X509Certificate2(reader.ReadBytes((int)resource.Length));
}
Or something very similar.

cassandra ssl handshake exception : no cipher suites in common

HI i have installed Cassandra 1.2.18 in my local and trying to setup secure connection but getting the below exception in the server. Here is My Java class, Cassandra configuration and the stack trace. I am really stuck with this issue kindly help.
I am using IBM jdk 1.6.
Java Class
public class CassandraClientDatastax {
private Cluster cluster;
private Session session;
public void connect(String node) throws Exception {
SSLContext context =
getSSLContext("client-truststore.jks", "cassandrapw",
"client-keystore.jks", "cassandrapw");
String[] cipherSuites = {
"TLS_RSA_WITH_NULL_SHA256","SSL_RSA_WITH_NULL_MD5","SSL_RSA_WITH_NULL_SHA","TLS_RSA_WITH_AES_128_CBC_SHA"
};
System.out.println("Building cluster ************* ");
cluster =
Cluster.builder().addContactPoints("localhost")
.withPort(9042)
.withSSL(new SSLOptions(context, cipherSuites))
.build();
}
private SSLContext getSSLContext(String truststorePath, String truststorePassword, String keystorePath,
String keystorePassword) throws Exception
{
FileInputStream tsf = new FileInputStream(Thread.currentThread().getContextClassLoader().getResource((truststorePath)).getPath());
FileInputStream ksf = new FileInputStream(Thread.currentThread().getContextClassLoader().getResource((keystorePath)).getPath());
/*InputStream tsf = Thread.currentThread().getContextClassLoader().getResource((truststorePath));
InputStream ksf = Thread.currentThread().getContextClassLoader().getResource((keystorePath));*/
SSLContext ctx = SSLContext.getInstance("TLS");
KeyStore ts = KeyStore.getInstance("JKS");
ts.load(tsf, truststorePassword.toCharArray());
TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
tmf.init(ts);
KeyStore ks = KeyStore.getInstance("JKS");
ks.load(ksf, keystorePassword.toCharArray());
KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
kmf.init(ks, keystorePassword.toCharArray());
ctx.init(kmf.getKeyManagers(), tmf.getTrustManagers(), new SecureRandom());
System.out.println("SSL Context Build Done ...................");
return ctx;
}
}
Cassandra Configuration :
client_encryption_options:
enabled: true
keystore: C:/Dev/apache-cassandra-1.2.18/conf/client-keystore.jks
keystore_password: cassandrapw
require_client_auth: true
# Set trustore and truststore_password if require_client_auth is true
truststore: C:/Dev/apache-cassandra-1.2.18/conf/client-truststore.jks
truststore_password: cassandrapw
# More advanced defaults below:
#protocol: TLS
# algorithm: SunX509
# store_type: JKS
# cipher_suites: [TLS_RSA_WITH_AES_128_CBC_SHA,TLS_RSA_WITH_AES_256_CBC_SHA,TLS_DHE_RSA_WITH_AES_128_CBC_SHA,TLS_DHE_RSA_WITH_AES_256_CBC_SHA,TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA]
cipher_suites: [TLS_RSA_WITH_NULL_SHA256,SSL_RSA_WITH_NULL_MD5,SSL_RSA_WITH_NULL_SHA,TLS_RSA_WITH_AES_128_CBC_SHA]
I am getting the below exception
ERROR 15:34:48,551 Unexpected exception during request
javax.net.ssl.SSLHandshakeException: no cipher suites in common
at sun.security.ssl.Handshaker.checkThrown(Handshaker.java:1290)
at sun.security.ssl.SSLEngineImpl.checkTaskThrown(SSLEngineImpl.java:513)
at sun.security.ssl.SSLEngineImpl.readNetRecord(SSLEngineImpl.java:790)
at sun.security.ssl.SSLEngineImpl.unwrap(SSLEngineImpl.java:758)