package com.nbusy.sdk.titan.jsonrpc.neptulon;

import android.net.SSLCertificateSocketFactory;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.UnrecoverableKeyException;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;

import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLSocket;
import javax.net.ssl.TrustManagerFactory;

/**
 * Neptulon client implementation: https://github.com/neptulon/neptulon
 */
public class NeptulonClient implements Neptulon {
    private SSLSocket socket;

    public void connect(String pemEncodedCaCert, String pemEncodedClientCert) throws IOException, CertificateException, NoSuchAlgorithmException, KeyStoreException, UnrecoverableKeyException {
        SSLCertificateSocketFactory factory;
        try (InputStream caCertStream = new ByteArrayInputStream(pemEncodedCaCert.getBytes());
             InputStream clientCertStream = new ByteArrayInputStream(pemEncodedClientCert.getBytes())) {
            factory = getSocketFactory(caCertStream, clientCertStream);
        }

        socket = (SSLSocket) factory.createSocket("localhost", 8081);
    }

    public void close() throws IOException {
        socket.close();
    }

    private SSLCertificateSocketFactory getSocketFactory(InputStream caCertStream, InputStream clientCertStream) throws CertificateException, IOException, KeyStoreException, NoSuchAlgorithmException, UnrecoverableKeyException {
        SSLCertificateSocketFactory factory = (SSLCertificateSocketFactory) SSLCertificateSocketFactory.getDefault(60 * 1000, null);

        // set CA cert to trust
        CertificateFactory cf = CertificateFactory.getInstance("X.509");
        X509Certificate ca = (X509Certificate)cf.generateCertificate(caCertStream);
        KeyStore caKeyStore = KeyStore.getInstance(KeyStore.getDefaultType());
        caKeyStore.load(null, null);
        caKeyStore.setCertificateEntry(ca.getSubjectX500Principal().getName(), ca);
        TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
        tmf.init(caKeyStore);
        factory.setTrustManagers(tmf.getTrustManagers());

        // set client cert
        X509Certificate cl = (X509Certificate)cf.generateCertificate(clientCertStream);
        KeyStore clientKeyStore = KeyStore.getInstance(KeyStore.getDefaultType());
        clientKeyStore.load(null, null);
        clientKeyStore.setKeyEntry(cl.getSubjectX500Principal().getName(), null, new Certificate[]{cl});
        KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
        kmf.init(clientKeyStore, new char[]{});

        return factory;
    }
}

@@ -877,16 +877,35 @@
 ientCert
+, byte%5B%5D privateKey
 ) throws
@@ -1319,32 +1319,44 @@
 clientCertStream
+, privateKey
 );%0A        %7D%0A%0A  
@@ -1617,16 +1617,35 @@
 rtStream
+, byte%5B%5D privateKey
 ) throws
@@ -2789,20 +2789,26 @@
 Name(), 
-null
+privateKey
 , new Ce
@@ -2974,24 +2974,256 @@
 char%5B%5D%7B%7D);%0A%0A
+        // todo: alternative approach if above doesn't work%0A//        keyStore = KeyStore.getInstance(%22PKCS12%22);%0A//        fis = new FileInputStream(certificateFile);%0A//        keyStore.load(fis, clientCertPassword.toCharArray());%0A%0A
         retu

add alternative client cert loader note