Good day. I do client-server application, client for Android. Need a TLS session with a server on which Netty is involved. I decided to use Netty on the Android client too. I do two-way certificate authentication.

  1. For tests, I created my CA certificate, server certificate, client certificate (I don’t cite the creation logs, I don’t need it). But I will say that before writing the Android client, I wrote the Desktop-Java client, and the scheme worked.

  2. Added a client certificate to the server in the list of trusted (cacerts).

  3. Made a Keystore-file of the BKS format (Using BouncyCastleProvider) with server and client certificates, slipped this keystore to the client. I tried to create with both keytool and Portecle:

    keytool -importcert -v -trustcacerts -file server / server_chain.pem -alias server -keystore server.bks -provider org.bouncycastle.jce.provider.BouncyCastleProvider -storetype BKS -storepass "changeit"

Client code:

File client_tls_cert = new File("/sdcard/GreatParents/tls/client/client1.pem"); File client_tls_key = new File("/sdcard/GreatParents/tls/client/client1.key.pkcs8"); TrustManagerFactory tmf = null; KeyStore ks; try { ks = KeyStore.getInstance(KeyStore.getDefaultType()); ks.load(new FileInputStream("/sdcard/GreatParents/tls/server.bks"),"changeit".toCharArray()); tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); tmf.init(ks); } catch (KeyStoreException | NoSuchAlgorithmException | CertificateException | IOException e) { e.printStackTrace(); } if (tmf != null) { SslContext sslCtx = null; // Строим клиентский SSL контекст try { sslCtx = new JdkSslClientContext(null,tmf,client_tls_cert,client_tls_key, "44j3k2b0", null, null, IdentityCipherSuiteFilter.INSTANCE,(ApplicationProtocolConfig) null,0,0); } catch (SSLException e) { e.printStackTrace(); logger.error("TLS Session not initialized"); return; } } 

I get an Exception:

 Caused by: java.security.NoSuchAlgorithmException: No provider found for pbeWithMD5AndDES-CBC 

What kind of algorithm is how to get rid of it? I tried to look at the supported algorithms with this code, there is no such as in Exception there:

 Provider[] providers = Security.getProviders(); for (Provider provider : providers) { logger.info("CRYPTO provider: " + provider.getName()); Set<Provider.Service> services = provider.getServices(); for (Provider.Service service : services) { logger.info("CRYPTO algorithm: "+ service.getAlgorithm()); } } 

Tell me in which direction to dig? I read that Android is not a priority for Netty developers. But so far, there is hope that this is where I am mistaken somewhere simply.

UPDATE

Thank you lsillarionov, you were right. If when converting a key to pkcs8 you specify an algorithm (argument -v2), or put -nocrypt, the problem goes away. But another problem comes. And so, the code is:

 // Контейнер закрытого ключа клиента File client_tls_key = new File("/sdcard/GreatParents/tls/client_key.pkcs8"); KeyManagerFactory kmf = null; KeyStore ks; try { ks = KeyStore.getInstance("BKS"); ks.load(new FileInputStream("/sdcard/GreatParents/tls/client_ks.bks"), "changeit".toCharArray()); String kmf_type = KeyManagerFactory.getDefaultAlgorithm(); kmf = KeyManagerFactory.getInstance(kmf_type); kmf.init(ks, "changeit".toCharArray()); } catch (KeyStoreException | CertificateException | NoSuchAlgorithmException | IOException | UnrecoverableKeyException e) { e.printStackTrace(); } TrustManagerFactory tmf = null; KeyStore ts; try { ts = KeyStore.getInstance("BKS"); ts.load(new FileInputStream("/sdcard/GreatParents/tls/client_ts.bks"), "changeit".toCharArray()); String tmf_type = TrustManagerFactory.getDefaultAlgorithm(); tmf = TrustManagerFactory.getInstance(tmf_type); tmf.init(ts); } catch (KeyStoreException | NoSuchAlgorithmException | CertificateException | IOException e) { e.printStackTrace(); } if (tmf != null) { SslContext sslCtx = null; try { sslCtx = SslContext.newClientContext(SslProvider.JDK,null,tmf,null,client_tls_key,keypass,kmf,null,IdentityCipherSuiteFilter.INSTANCE,(ApplicationProtocolConfig) null,0,0); } catch (SSLException e) { e.printStackTrace(); logger.error("TLS Session not initialized"); return; } } 

The server certificate is stored in client_ts.bks, and the client certificate is stored in client_ks.bks.

When starting, I get the error:

 java.security.NoSuchAlgorithmException: KeyStore JKS implementation not found 

At first it was not clear where JKS came from, if I specifically placed all the certificates in Keystore of the BKS format, but I found a method in stacktrace

 io.netty.handler.ssl.JdkSslContext.buildKeyManagerFactory 

with this line:

 KeyStore ks = KeyStore.getInstance("JKS"); 

That is, Netty "forcibly" creates Keystore in JKS format ?! Then you can put an end to trying to use Netty in an Android application.

I will try to turn to English-language SOF, some Netty developer can explain there directly.

  • It seems that in pbeWithMD5AndDES-CBC you have client1.key.pkcs8 client key. Try to decrypt it temporarily (remove the password), or change the algorithm to a more modern one. Somehow weird you read the keys directly from / sdcard / GreatParents. Are you sure that this path will be available to you everywhere? - lsillarionov
  • Thanks for the tip! Here is an excerpt from the docks of the Openssl utility: "Normally PKCS # 8 private keys are encrypted algorithm called pbeWithMD5AndDES-CBC" - Nik
  • Regarding the appeal to / sdcard - yes, I have so far "hardcoded" the way, I will correct it when I solve problems with working capacity. - Nik
  • Made UPDATE post. There are new problems. - Nik

1 answer 1

lsillarionov on the original problem was right. On the second problem (KeyStore JKS implementation not found), the problem was solved only by getting rid of Netty on the client.