I am trying to implement a wrapper around a X509KeyManager
to execute other code inside the callbacks and then call the the default KeyManager after but this isn't working.
Here's my simplified code:
class MyKeyManager(): X509ExtendedKeyManager() {
private val defaultKeyManager: X509ExtendedKeyManager
init {
val keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm())
keyManagerFactory.init(null, null)
val keyManagers = keyManagerFactory.keyManagers
check(keyManagers.size == 1 && keyManagers[0] is X509ExtendedKeyManager) {
"Error Creating KeyManager"
}
defaultKeyManager = keyManagers[0] as X509ExtendedKeyManager
}
override fun getClientAliases(keyType: String?, issuers: Array<out Principal>?): Array<String> {
return defaultKeyManager.getClientAliases(keyType, issuers)
}
override fun chooseClientAlias(keyType: Array<out String>?, issuers: Array<out Principal>?, socket: Socket?): String {
// execute code
return defaultKeyManager.chooseClientAlias(keyType, issuers, socket)
}
override fun getServerAliases(keyType: String?, issuers: Array<out Principal>?): Array<String> {
return defaultKeyManager.getServerAliases(keyType, issuers)
}
override fun chooseServerAlias(keyType: String?, issuers: Array<out Principal>?, socket: Socket?): String {
return defaultKeyManager.chooseServerAlias(keyType, issuers, socket)
}
override fun getCertificateChain(alias: String?): Array<X509Certificate> {
// execute code
return defaultKeyManager.getCertificateChain(alias)
}
override fun getPrivateKey(alias: String?): PrivateKey {
// execute code
return defaultKeyManager.getPrivateKey(alias)
}
override fun chooseEngineClientAlias(keyType: Array<out String>?, issuers: Array<out Principal>?, engine: SSLEngine?): String {
return defaultKeyManager.chooseEngineClientAlias(keyType, issuers, engine)
}
override fun chooseEngineServerAlias(keyType: String?, issuers: Array<out Principal>?, engine: SSLEngine?): String {
return defaultKeyManager.chooseEngineServerAlias(keyType, issuers, engine)
}
}
and when I run my app I get this exception:
E/AndroidRuntime: FATAL EXCEPTION: OkHttp Dispatcher
Process: com.example.mytestapp1, PID: 20624
java.lang.Error: javax.net.ssl.SSLHandshakeException: defaultKeyManager.choose…keyType, issuers, socket) must not be null
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1173)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
at java.lang.Thread.run(Thread.java:920)
Caused by: javax.net.ssl.SSLHandshakeException: defaultKeyManager.choose…keyType, issuers, socket) must not be null
at com.android.org.conscrypt.SSLUtils.toSSLHandshakeException(SSLUtils.java:363)
at com.android.org.conscrypt.ConscryptEngineSocket.doHandshake(ConscryptEngineSocket.java:285)
at com.android.org.conscrypt.ConscryptEngineSocket.access$1000(ConscryptEngineSocket.java:54)
at com.android.org.conscrypt.ConscryptEngineSocket$SSLInputStream.renegotiate(ConscryptEngineSocket.java:929)
at com.android.org.conscrypt.ConscryptEngineSocket$SSLInputStream.processDataFromSocket(ConscryptEngineSocket.java:884)
at com.android.org.conscrypt.ConscryptEngineSocket$SSLInputStream.readUntilDataAvailable(ConscryptEngineSocket.java:824)
at com.android.org.conscrypt.ConscryptEngineSocket$SSLInputStream.read(ConscryptEngineSocket.java:797)
...
I am using OkHttp to run this code and I create my Client like this:
val keyManager = MyKeyManager()
sslContext.init(arrayOf<X509KeyManager>(keyManager), TrustAllTrusManager, null)
val builder = OkHttpClient.Builder().protocols(listOf(Protocol.HTTP_1_1))
.sslSocketFactory(sslContext.socketFactory, TrustAllTrusManager[0])
Does anyone anyone know if this is the correct way of creating the default X509KeyManager or why this exception is thrown?
Turns out that the exception was thrown because the methods overwritten from x509ExtendedKeyManager
needed to be marked as nullable.
All of these methods in the java interface can return null
and I wasn't making them nullable when implementing them in Kotlin