Issue being faced for TLS setup

Hi,

I am trying to implement TLS with temporal. I ran the generate-test-certs.sh and got the certificates generated in certs folder. Now I am using the client.pem and client.key certificates inside samples-java/SslEnabledWorker.java at main · temporalio/samples-java · GitHub
Facing issue as below :

Exception in thread "main" java.lang.IllegalArgumentException: Input stream does not contain valid private key.
	at io.grpc.netty.shaded.io.netty.handler.ssl.SslContextBuilder.keyManager(SslContextBuilder.java:416)
	at io.temporal.serviceclient.SimpleSslContextBuilder.configure(SimpleSslContextBuilder.java:116)
	at io.temporal.serviceclient.SimpleSslContextBuilder.build(SimpleSslContextBuilder.java:141)
	at io.temporal.samples.ssl.SslEnabledWorker.main(SslEnabledWorker.java:52)
Caused by: java.security.spec.InvalidKeySpecException: Neither RSA, DSA nor EC worked
	at io.grpc.netty.shaded.io.netty.handler.ssl.SslContext.getPrivateKeyFromByteBuffer(SslContext.java:1155)
	at io.grpc.netty.shaded.io.netty.handler.ssl.SslContext.toPrivateKey(SslContext.java:1134)
	at io.grpc.netty.shaded.io.netty.handler.ssl.SslContextBuilder.keyManager(SslContextBuilder.java:414)
	... 3 more
Caused by: java.security.spec.InvalidKeySpecException: java.security.InvalidKeyException: IOException : algid parse error, not a sequence
	at jdk.crypto.ec/sun.security.ec.ECKeyFactory.engineGeneratePrivate(ECKeyFactory.java:169)
	at java.base/java.security.KeyFactory.generatePrivate(KeyFactory.java:390)
	at io.grpc.netty.shaded.io.netty.handler.ssl.SslContext.getPrivateKeyFromByteBuffer(SslContext.java:1153)
	... 5 more
Caused by: java.security.InvalidKeyException: IOException : algid parse error, not a sequence
	at java.base/sun.security.pkcs.PKCS8Key.decode(PKCS8Key.java:350)
	at java.base/sun.security.pkcs.PKCS8Key.decode(PKCS8Key.java:355)
	at jdk.crypto.ec/sun.security.ec.ECPrivateKeyImpl.<init>(ECPrivateKeyImpl.java:77)
	at jdk.crypto.ec/sun.security.ec.ECKeyFactory.implGeneratePrivate(ECKeyFactory.java:237)
	at jdk.crypto.ec/sun.security.ec.ECKeyFactory.engineGeneratePrivate(ECKeyFactory.java:165)
	... 7 more
Caused by: java.security.spec.InvalidKeySpecException: Neither RSA, DSA nor EC worked

Caused by: java.security.spec.InvalidKeySpecException: java.security.InvalidKeyException: IOException : algid parse error, not a sequence

Caused by: java.security.InvalidKeyException: IOException : algid parse error, not a sequence

Below is the code reference:

I feel issue is with the private key generation. Please guide.

Is your key PKCS8 format? These scripts currently generate PKCS1.
I think for it to work the ssh tool should use
openssl pkcs8 instead.

There should be a way to use openssl to convert your key/pem to PKCS8, see maybe here if it helps.

Try generating the certificates using the sh script again. This was just now updated to help generate PCKS12 format.
You can use the SimpleSslContextBuilder.forPKCS12 in WorkflowServiceStubsOptions once its generated
Hope it helps.

For PKCS8 follow this issue.

For manual conversion from PKCS1 to PKCS8 you should be able to run:

openssl rsa -RSAPublicKey_in -in <filename> -pubout

Thanks @tihomir . I was able to get through that with both PKCS8 and PKCS12 format.
Also, following command I had used to convert to PKCS8 format :

openssl pkcs8 -topk8 -inform pem -in file.key -outform pem -nocrypt -out file.pem

I have a followup query on the same :
SSLContext is passed while creating WorkflowServiceStubs. So, is it expected to build the Stub and Client artifacts each time before invoking a workflow? I had added the logic to build Stub and Client as Bean in SpringBootApp. Is that the correct approach?

So, is it expected to build the Stub and Client artifacts each time before invoking a workflow?

Creating a client is a heavy-weight operation so you should try not to do it each time you create your workers or client stubs. In your spring boot app you could create a singleton producer and inject it when you create your WorkerFactory and your parts of code that create client workflow stubs. You can also reuse it in your activity code (via injection) if you need the client there.

@tihomir Yes, I understand that. But then if there is a scenario about some updates to certificates, that will not take into effect until and unless there is a restart of the application. Am I correct or I am missing anything?

If you are rolling out new client certs, you should also rotate your client connections. Don’t think thats specific to Temporal itself but probably true for most if not all gRPC/HTTP long lived clients.
There are probably some tricks that could be applied to dynamically change certs for new connections only, but I am not sure what that could be for spring boot. Maybe there is something similar to the Go tls package - crypto/tls - pkg.go.dev (GetCertificate(s)) that could help.

Thanks @tihomir . Will check on these points.