Hakky54 / sslcontext-kickstart

🔐 A lightweight high level library for configuring a http client or server based on SSLContext or other properties such as TrustManager, KeyManager or Trusted Certificates to communicate over SSL TLS for one way authentication or two way authentication provided by the SSLFactory. Support for Java, Scala and Kotlin based clients with examples. Available client examples are: Apache HttpClient, OkHttp, Spring RestTemplate, Spring WebFlux WebClient Jetty and Netty, the old and the new JDK HttpClient, the old and the new Jersey Client, Google HttpClient, Unirest, Retrofit, Feign, Methanol, Vertx, Scala client Finagle, Featherbed, Dispatch Reboot, AsyncHttpClient, Sttp, Akka, Requests Scala, Http4s Blaze, Kotlin client Fuel, http4k Kohttp and Ktor. Also gRPC, WebSocket and ElasticSearch examples are included
https://sslcontext-kickstart.com/
Apache License 2.0
498 stars 76 forks source link

the alias of CertificateEntry #166

Closed manbucy closed 2 years ago

manbucy commented 2 years ago

Describe the bug Hello, I am going to create an SSLContext with the following code, but the resulting SSLContext does not appear to be complete and its trustedCerts is empty.

    SSLFactory sslFactory = SSLFactory.builder()
            .withTrustMaterial(CertificateUtils.loadCertificate("ca.crt"))
            .build();
    SSLContext sslContext = sslFactory.getSslContext();

image

the content of ca.crt

-----BEGIN CERTIFICATE-----
MIIFWTCCA0GgAwIBAgIUW4b6bPPPyRAm0DrDKKJJ8YlSqOkwDQYJKoZIhvcNAQEL
BQAwPDE6MDgGA1UEAxMxRWxhc3RpY3NlYXJjaCBzZWN1cml0eSBhdXRvLWNvbmZp
Z3VyYXRpb24gSFRUUCBDQTAeFw0yMjA0MDUxMjQ1MzVaFw0yNTA0MDQxMjQ1MzVa
MDwxOjA4BgNVBAMTMUVsYXN0aWNzZWFyY2ggc2VjdXJpdHkgYXV0by1jb25maWd1
cmF0aW9uIEhUVFAgQ0EwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDB
q3aR//NaqXBUqI0AVHuVWJmFMLYwpi/DQLUYifwOlGx4iAb6ePuiA8b7tXAGPn0z
TWFQ82t0DZf/1nXoRmNJO8ardAVWcL7z+VDUY7Hab08GJzRRP/V5b7VL+J+WBQOG
auN0cal3jM14k3FeZApyoL+XqmJ36MSY3WtAPfF3ySH1ltcMguXqN79k3Bxw0mGq
AJt+z4q8Lq2e8vsMKKpSO1vZ0grvffj6MBni2stfZ4ifA6Kubh/yePShKsG/N8nY
K6iJYjwLuVUQ1Eaw6X3s78c+eESTlzZiM6I7qTR1JzW5Fuyz/ZPbDcI1zg+p9H4g
NRaX76Fv9XG/XehLeYxNoTBLytY2d9kdEmW9MIGCqaROabDdxygxcJ5l3aqkBTiA
tq42vguuiQvpLndfGIEA4qh5AFyo+iqP1226+1onHfeXtbtyqjpHIV6RZa8RqNLg
ynmf96NzzHQq1CfKp5CgQB/l3yaAtFxguNyhKftHia518iTjcUpn9f3gmSzDlZy2
KgzZMaw8GwdtT+qac3XCVI7vwjY21uEHbCEklh8ZycAt28Dc0h747MqG9A3xdMDV
lf8iBtGjuxQNJSsOBRY6Up8ajEWeYvEqpKDHVHYxc78qdjGCzltgGIvjzah389mH
UC458l4Ey4Lns4C7NVAteHva9L71CE/zDTwJ3nECqwIDAQABo1MwUTAdBgNVHQ4E
FgQUphpsq/WD1QUsRkr9EQaGinawo9owHwYDVR0jBBgwFoAUphpsq/WD1QUsRkr9
EQaGinawo9owDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAgEAlg8X
PnpSKIkt+a9imOFcddUgoNSCgwAyBuGdnUKTjuDnV2630O7cRky4Ly8gI3hxuV3j
I0JHatPA4Xw8m/8rAkgoega4zCQ89L7w8g1b54NnvnMOQIKs4aQ7TsYQUgyGxj6j
hhs1uLEBgF/uCJR1INZbiw4tjGTJssRSGMUsn7Mto0+3UL3AHqbmQY4IavRDEd2s
zpyGN1acwh9jl50pcKjgM/UYhNgWvGQgOF7MP8+4BWXBn9O7ufdUt4n08yPFP5hn
sOKrScnTCPIVn3uExcYDLDEuRDsQXfDvD03Bm6aFPC+qwr+W7k8WZPc7UW3vLzTg
TPtvnFwTunD3Bzv14b+2BOQH+caOKVyjBn73HzXQ6Xp8KM6ef3+6RZTeomHhqAwr
TG2vVsLzDhZiNjOE1Le3UeT4eAz7psgg+piouaXkY5FnVmMlNqWGkXfmvtMC8JzG
uWGUtSV2plImhQMgfrF4wMhntiNQcHa0Fge0k4I4ajt/HD5Al4yMYCMzx7ocbZLg
bTSDn+PuRt1NBZYC/Icz6L3CaSAVCMIEw145G/ytyu9annHs+hXSx+1ji3MHkF/g
yE65FKuMXoHLhCdN9MoKFEDr6eLlY7l9HWbcfQGpePoX4L/g1nGMVQmssCChkH5r
h5BvtLZEjAtAP6q1Al0phYV6eYQvLE8Dzbw0RQ0=
-----END CERTIFICATE-----

Environmental Data:

Additional context I found out the cause of the problem, when create X509TrustManagerImpl, its trustedCerts is already empty. sun.security.ssl.X509TrustManagerImpl image

sun.security.validator.KeyStores.getTrustedCerts(KeyStore var0) image

java.security.KeyStore.isCertificateEntry(String alias) image

sun.security.pkcs12.PKCS12KeyStore.engineIsCertificateEntry(String var1) the entries keys has the capital letters, but the parameter var1 is lowercase letters image

Can you consider changing alias to lowercase in the nl.altindag.ssl.util.KeyStoreUtils.createTrustStore(List<T> certificates) image or nl.altindag.ssl.util.CertificateUtils.generateAlias(Certificate certificate) image

Hakky54 commented 2 years ago

Hi @manbucy

Thank you for the very detailed issue description. It is very helpful when investigating this issue, I really appreciate it! I have tried this out locally and for me this issue is not happening, see below for the screenshot:

Screenshot 2022-04-09 at 17 22 40

As you can see one certificate is loaded and also visible within the trustmanager of the sslcontext. I think this issue is caused by CertificateUtils not being able to find the certificate on your classpath, but to be sure I need to ask if you can retry something on your side. Can you put the statement of CertificateUtils on a separate line and check whether the list is empty or has elements? So basically the following snippet:

List<Certificate> certificates = CertificateUtils.loadCertificate("ca.crt");

SSLFactory sslFactory = SSLFactory.builder()
        .withTrustMaterial(certificates)
        .build();
manbucy commented 2 years ago

@Hakky54 Thank you for your reply, i have put the statement of CertificateUtils on a separate line, but the trustedCerts is still emply. image

but when i use jdk11, I found the sslcontext become correct. sun.security.pkcs12.PKCS12KeyStore.setCertEntry(String alias, Certificate cert, Set<Attribute> attributes) image image

manbucy commented 2 years ago

JDK-10+0 and previous versions are entries.put(alias, certEntry); source code

JDK-10+1 and later versions are entries.put(alias.toLowerCase(Locale.ENGLISH), certEntry); source code

Hakky54 commented 2 years ago

I tried jdk 1.8.0_302 which did not have this issue. I currently don't have my dev environment next to me, so i will come back to you in 4 hours and try out with jdk 1.8.0_202 locally

Hakky54 commented 2 years ago

I have retried it with jdk 1.8.0_202 and indeed that issue is present over there and your PR changes fixes it. Very well investigated! I am amazed for your detailed research. Thank you very much for this issue and pull request. I have approved the PR and merged it.

Just out of curiosity, why are you using jdk 1.8.0_202 and not using the latest version of jdk 1.8?

manbucy commented 2 years ago

Just out of curiosity, why are you using jdk 1.8.0_202 and not using the latest version of jdk 1.8?

This JDK1.8.0_202 was installed in 2019 when it was the latest version and I haven't updated it since. Jdk1.8.0_202, on the other hand, is the last OTN License release that many companies will choose.

Hakky54 commented 2 years ago

Yes, very understandable and I didn't know about the OTN license! I have just released your fix which is now available at version 7.4.1. Good luck, please let me know if you have any other improvements 😄