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.cert.Certificate;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;

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) throws IOException, CertificateException, NoSuchAlgorithmException, KeyStoreException {
        InputStream caCertStream = new ByteArrayInputStream(pemEncodedCaCert.getBytes());
        SSLCertificateSocketFactory factory = getSocketFactory(caCertStream);

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

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

    private SSLCertificateSocketFactory getSocketFactory(InputStream caCertStream) throws CertificateException, IOException, KeyStoreException, NoSuchAlgorithmException {
        SSLCertificateSocketFactory factory = (SSLCertificateSocketFactory)SSLCertificateSocketFactory.getDefault(60 * 1000, null);
        CertificateFactory cf = CertificateFactory.getInstance("X.509");

        Certificate ca;
        try {
            ca = cf.generateCertificate(caCertStream);
        } finally {
            caCertStream.close();
        }

        KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
        keyStore.load(null, null);
        keyStore.setCertificateEntry("ca", ca);
        String tmfAlgorithm = TrustManagerFactory.getDefaultAlgorithm();
        TrustManagerFactory tmf = TrustManagerFactory.getInstance(tmfAlgorithm);
        tmf.init(keyStore);
        factory.setTrustManagers(tmf.getTrustManagers());

        return factory;
    }
}

@@ -292,32 +292,80 @@
 rithmException;%0A
+import java.security.UnrecoverableKeyException;%0A
 import java.secu
@@ -474,32 +474,72 @@
 ficateFactory;%0A%0A
+import javax.net.ssl.KeyManagerFactory;%0A
 import javax.net
@@ -805,16 +805,45 @@
 edCaCert
+, String pemEncodedClientCert
 ) throws
@@ -921,27 +921,104 @@
 xception
- %7B%0A        
+, UnrecoverableKeyException %7B%0A        SSLCertificateSocketFactory factory;%0A        try (
 InputStr
@@ -1103,35 +1103,116 @@
     
-SSLCertificateSocketFactory
+     InputStream clientCertStream = new ByteArrayInputStream(pemEncodedClientCert.getBytes())) %7B%0A           
  fac
@@ -1247,18 +1247,46 @@
 rtStream
-);
+, clientCertStream);%0A        %7D
 %0A%0A      
@@ -1307,16 +1307,17 @@
 LSocket)
+ 
 factory.
@@ -1513,16 +1513,46 @@
 rtStream
+, InputStream clientCertStream
 ) throws
@@ -1622,32 +1622,59 @@
 gorithmException
+, UnrecoverableKeyException
  %7B%0A        SSLCe
@@ -1735,16 +1735,17 @@
 Factory)
+ 
 SSLCerti
@@ -1784,32 +1784,65 @@
 0 * 1000, null);
+%0A%0A        // set CA cert to trust
 %0A        Certifi
@@ -1899,17 +1899,16 @@
 .509%22);%0A
-%0A
         
@@ -1923,38 +1923,8 @@
 ate 
-ca;%0A        try %7B%0A            
 ca =
@@ -1966,73 +1966,8 @@
 m);%0A
-        %7D finally %7B%0A            caCertStream.close();%0A        %7D%0A%0A
     
@@ -1979,17 +1979,19 @@
 eyStore 
-k
+caK
 eyStore 
@@ -2041,33 +2041,35 @@
 ype());%0A        
-k
+caK
 eyStore.load(nul
@@ -2086,17 +2086,19 @@
         
-k
+caK
 eyStore.
@@ -2140,30 +2140,66 @@
     
-String tmfAlgorithm = 
+TrustManagerFactory tmf = TrustManagerFactory.getInstance(
 Trus
@@ -2235,16 +2235,17 @@
 orithm()
+)
 ;%0A      
@@ -2250,106 +2250,304 @@
     
-TrustManagerFactory tmf = TrustManagerFactory.getInstance(tmfAlgorithm);%0A        tmf.init(keyStore
+tmf.init(caKeyStore);%0A        factory.setTrustManagers(tmf.getTrustManagers());%0A%0A        // set client cert%0A        Certificate cl = cf.generateCertificate(clientCertStream);%0A        KeyStore clientKeyStore = KeyStore.getInstance(KeyStore.getDefaultType());%0A        clientKeyStore.load(null, null
 );%0A 
@@ -2557,55 +2557,224 @@
     
-factory
+clientKeyStore
 .set
-TrustManagers(tmf.getTrustManagers()
+KeyEntry(%22client%22, null, new Certificate%5B%5D%7Bcl%7D);%0A        KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());%0A        kmf.init(clientKeyStore, new char%5B%5D%7B%7D
 );%0A%0A

add client cert provider