I have a service that provides a key and private RSA certificate that I need to turn into an SSLSocketFactory. I am able to initialize everything, but when calling getKeyManagers on the KeyManagerFactory, a RuntimeException saying "java.lang.RuntimeException: forget something!" is thrown. What am I missing?
return try {
val sslContext = SSLContext.getDefault()
val keyManager = KeyManagerFactory.getInstance("PKIX")
val keyStore = KeyStore.getInstance(KeyStore.getDefaultType())
val certificateFactory = CertificateFactory.getInstance("X.509")
keyStore.load(null)
keyStore.setKeyEntry(
"agragps",
privateCertificate.toByteArray(),
arrayOf(certificateFactory.generateCertificate(publicCertificate.byteInputStream())))
keyManager.init(keyStore, charArrayOf())
val managers = keyManager.keyManagers
sslContext.init(managers, null, null)
sslContext.socketFactory
} catch (e: Exception) {
null
}
Here is the full exception:
java.lang.RuntimeException: forget something!
at com.android.org.bouncycastle.jcajce.provider.keystore.bc.BcKeyStoreSpi$StoreEntry.getObject(BcKeyStoreSpi.java:329)
at com.android.org.bouncycastle.jcajce.provider.keystore.bc.BcKeyStoreSpi.engineGetKey(BcKeyStoreSpi.java:619)
at java.security.KeyStoreSpi.engineGetEntry(KeyStoreSpi.java:511)
at java.security.KeyStore.getEntry(KeyStore.java:1581)
at com.android.org.conscrypt.KeyManagerImpl.<init>(KeyManagerImpl.java:74)
at com.android.org.conscrypt.KeyManagerFactoryImpl.engineGetKeyManagers(KeyManagerFactoryImpl.java:120)
at javax.net.ssl.KeyManagerFactory.getKeyManagers(KeyManagerFactory.java:305)
at com.agragps.agragps.?.?Kt.loadCertificates(ThingStreamClientAndroid.kt:64)
at com.agragps.agragps.?.?Kt.loadCertificates(ThingStreamClientAndroid.kt:38)
at com.agragps.agragps.services.?.?$connectPointPerfect$2.invokeSuspend(MQTTService.kt:113)
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:106)
at kotlinx.coroutines.internal.LimitedDispatcher$Worker.run(LimitedDispatcher.kt:115)
at kotlinx.coroutines.scheduling.TaskImpl.run(Tasks.kt:100)
at kotlinx.coroutines.scheduling.CoroutineScheduler.runSafely(CoroutineScheduler.kt:584)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.executeTask(CoroutineScheduler.kt:793)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.runWorker(CoroutineScheduler.kt:697)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.run(CoroutineScheduler.kt:684)
Converting the public PEM to DER gives the same result:
val publicDER = Base64.decode(publicCertificate
.replace("-----BEGIN CERTIFICATE-----\n", "")
.replace("\n-----END CERTIFICATE-----\n", "")
.encodeToByteArray(), Base64.DEFAULT)
keyStore.setKeyEntry(
"agragps",
privateCertificate.toByteArray(),
arrayOf(certificateFactory.generateCertificate(publicDER.inputStream())))
privateCertificate
is a String starting with "-----BEGIN RSA PRIVATE KEY-----" and ending in "-----END RSA PRIVATE KEY-----". publicCertificate
is a String starting with "-----BEGIN CERTIFICATE-----" and ending in "-----END CERTIFICATE-----".
I'm not very experienced with working with certificates. Any help is really appreciated.