For creating SSL server socket on android you need to provide two KeyStore.
- keyManager key store.
- Trust manager key store.
Creating KeyManager.
For creating keyManager, You need to generate PKCS12
with the .crt
and .key
file.
openssl pkcs12 -export -in [cert_file]-inkey [key_file] -out store.p12
Then you have to create JKS
file with this command.
keytool -importkeystore \-srckeystore store.p12 -srcstoretype PKCS12 \-destkeystore store.jks -deststoretype BKS \-providerclass org.bouncycastle.jce.provider.BouncyCastleProvider \-providerpath [bouncy file like :”bcprov-jdk15on-167.jar”]
Tip : for creating this file you need BouncyCastleProvider.
Now your file Key Manager is ready. You can put it in your resource and use it with this code.
Java:
private KeyManager[] createKeyManagers(InputStream keyStoreIS, String keystorePassword, String keyPassword) throws Exception {
KeyStore keyStore = KeyStore.getInstance(CERTIFICATE_TYPE);
keyStore.load(keyStoreIS, keystorePassword.toCharArray());
keyStoreIS.close();
KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
kmf.init(keyStore, keyPassword.toCharArray());
return kmf.getKeyManagers();
}
Kotlin:
@Throws(java.lang.Exception::class)
fun createKeyManagers(keyStoreIS: InputStream, keystorePassword: String, keyPassword: String): Array<KeyManager> {
val keyStore = KeyStore.getInstance("BKS")
keyStore.load(keyStoreIS, keystorePassword.toCharArray())
keyStoreIS.close()
val algorithm = KeyManagerFactory.getDefaultAlgorithm()
val kmf = KeyManagerFactory.getInstance(algorithm)
kmf.init(keyStore, keyPassword.toCharArray())
return kmf.keyManagers
}
Creating TrustManager.
You need to create a BKS file with this command.
keytool -importcert -v -trustcacerts -file [cer_file] -alias IntermediateCA -keystore [output.bks] -provider org.bouncycastle.jce.provider.BouncyCastleProvider -providerpath [bouncy file like :”bcprov-jdk15on-159.jar”] -storetype BKS -storepass mysecret
Now your key trust is ready. You can put it in your resource and use it with this code.
Java :
private TrustManager[] createTrustManagers(InputStream trustStoreIS, String keystorePassword) throws Exception {
KeyStore trustStore = KeyStore.getInstance("BKS");
trustStore.load(trustStoreIS, keystorePassword.toCharArray());
trustStoreIS.close();
String algorithm = TrustManagerFactory.getDefaultAlgorithm();
TrustManagerFactory trustFactory = TrustManagerFactory.getInstance(algorithm);
trustFactory.init(trustStore);
return trustFactory.getTrustManagers();
}
Kotlin :
@Throws(java.lang.Exception::class)
fun createTrustManagers(trustStoreIS: InputStream, keystorePassword: String): Array<TrustManager> {
val trustStore = KeyStore.getInstance("BKS")
trustStore.load(trustStoreIS, keystorePassword.toCharArray())
trustStoreIS.close()
val algorithm = TrustManagerFactory.getDefaultAlgorithm()
val trustFactory = TrustManagerFactory.getInstance(algorithm);
trustFactory.init(trustStore);
return trustFactory.trustManagers
}
Create SSLServerSocket.
Then you can create SSLServerSocket with this code.
Java :
public static SSLServerSocket getSSLServerSocket(InputStream server, InputStream cacerts, Integer port) throws Exception {
String keyPass = "mysecret";
String keyStorePass = "mysecret";
SSLContext context = SSLContext.getInstance("TLSv1.2");
context.init(createKeyManagers(server, keyStorePass, keyPass), createTrustManagers(cacerts, keyPass), new SecureRandom());
SSLServerSocketFactory factory = context.getServerSocketFactory();
SSLServerSocket serverSocket = (SSLServerSocket)factory.createServerSocket(port);
serverSocket.setEnabledProtocols(serverSocket.getSupportedProtocols());
serverSocket.setEnabledCipherSuites(serverSocket.getSupportedCipherSuites());
serverSocket.setNeedClientAuth(false);
serverSocket.setWantClientAuth(false);
serverSocket.setUseClientMode(false);
return serverSocket;
}
Kotlin :
@Throws(Exception::class)
fun getSSLServerSocket(server: InputStream, cacerts: InputStream, port: Int): SSLServerSocket {
val keyPass = "mysecret"
val keyStorePass = "mysecret"
val context = SSLContext.getInstance("TLSv1.2")
context.init(
createKeyManagers(server, keyStorePass, keyPass),
createTrustManagers(cacerts, keyPass),
SecureRandom()
)
val factory = context.serverSocketFactory
val serverSocket = factory.createServerSocket(port) as SSLServerSocket
serverSocket.enabledProtocols = serverSocket.supportedProtocols
serverSocket.enabledCipherSuites = serverSocket.supportedCipherSuites
serverSocket.needClientAuth = false
serverSocket.wantClientAuth = false
serverSocket.useClientMode = false
return serverSocket
}
your server socket is ready now and you can start listening. Due to this purpose you need to run socket in thread and by using this code you can wait for new client to connect and handshake with client.
Java :
SSLSocket socket = (SSLSocket) serverSocket.accept();
socket.addHandshakeCompletedListener(event -> {
//start to communicate
});
socket.startHandshake();
Kotlin :
val socket = serverSocket.accept() as SSLSocket
socket.addHandshakeCompletedListener { handShake ->
//start to communicate
}
socket.startHandshake()