JDK-8322767 : TLS full handshake is slow with PKCS12KeyStore and X509KeyManagerImpl
  • Type: Enhancement
  • Component: security-libs
  • Sub-Component: javax.net.ssl
  • Priority: P3
  • Status: Open
  • Resolution: Unresolved
  • Submitted: 2023-12-29
  • Updated: 2024-05-01
Related Reports
Relates :  
Relates :  
Relates :  
Description
If JMH test java/security/SSLHandshake.java uses PKCS12 keystore and PKIX KeyManagerFactory, the throughputs on TLS full handshake are much slower.

1. KeyStore: JKS, KeyManagerFactory: SunX509
Benchmark                 (resume)  (tlsVersion)   Mode  Cnt     Score     Error  Units
SSLHandshake.doHandshake      true       TLSv1.2  thrpt   15  6950.013 ? 704.233  ops/s
SSLHandshake.doHandshake      true           TLS  thrpt   15   862.246 ?  35.570  ops/s
SSLHandshake.doHandshake     false       TLSv1.2  thrpt   15   576.458 ?  17.235  ops/s
SSLHandshake.doHandshake     false           TLS  thrpt   15   502.704 ?  14.180  ops/s

2. KeyStore: PKCS12, KeyManagerFactory: PKIX
Benchmark                 (resume)  (tlsVersion)   Mode  Cnt     Score     Error  Units
SSLHandshake.doHandshake      true       TLSv1.2  thrpt   15  8759.169 ? 332.370  ops/s
SSLHandshake.doHandshake      true           TLS  thrpt   15   864.751 ?  30.114  ops/s
SSLHandshake.doHandshake     false       TLSv1.2  thrpt   15    96.037 ?   4.704  ops/s
SSLHandshake.doHandshake     false           TLS  thrpt   15    92.632 ?   3.235  ops/s

The combination FullHandshake+JKS+SunX509 is 4+ times faster than the combination FullHandshake+PKCS12+PKIX.
Comments
attached the flamegraph for reference
28-03-2024

A pull request was submitted for review. URL: https://git.openjdk.org/jdk/pull/17956 Date: 2024-02-22 01:14:24 +0000
19-03-2024

I can confirm that PKIX+PKCS12 is much slower than the other combinations (2-3x slower on my machine). PKIX does not cache KeyStore entries, and retrieves them directly from the KeyStore when they are needed. SunX509 retrieves the entries during initialization only. PKCS12 key stores encrypt entries, and the entries need to be decrypted before every use. JKS stores do not decrypt entries on every use. Most of the time is spent in PBES2Core.engineInit -> PBKDF2Core.engineGenerateSecret; the time is spent on SHA256 hashing. PKIX KM is documented to access KeyStore on every use, so caching is out of the question. KeyStore getEntry is supposed to use the given password, so we can't cache the entries on the KeyStore level. I suppose we could consider caching the derived keys.
03-01-2024

SunX509 key manager (SunX509KeyManagerImpl) has a cache, namely credentialsMap, which raises the throughput, however PKIX/NewSunX509 key manager (X509KeyManagerImpl) doesn't have such cache. PKCS12KeyStore::engineGetKey calls RetryWithZero::run, and this action looks slow.
02-01-2024