Security: TLS 1.3, ChaCha20-Poly1305, and Curve25519 (JEP 329, 332, 324)
Security Improvements Across Java 9–11
| JEP | Release | Feature |
|---|---|---|
| JEP 287 | Java 9 | SHA-3 hash algorithms |
| JEP 273 | Java 9 | DRBG-based SecureRandom |
| JEP 288 | Java 9 | Disable SHA-1 certificates |
| JEP 324 | Java 11 | Key Agreement with Curve25519 and Curve448 |
| JEP 329 | Java 11 | ChaCha20 and Poly1305 cryptographic algorithms |
| JEP 332 | Java 11 | Transport Layer Security (TLS) 1.3 |
| JEP 181 | Java 11 | Nest-Based Access Control |
TLS 1.3 (JEP 332)
TLS 1.3 is the current version of the Transport Layer Security protocol, finalised in RFC 8446 (August 2018). Java 11 delivers a complete implementation in JSSE (Java Secure Socket Extension).
What changed vs TLS 1.2
| Aspect | TLS 1.2 | TLS 1.3 |
|---|---|---|
| Handshake round trips | 2 RTT | 1 RTT (0-RTT for resumed sessions) |
| Cipher suites | Many (including weak ones) | 5 strong suites only |
| Key exchange | RSA key exchange (vulnerable) | Only forward-secret ECDHE/DHE |
| Signature algorithms | MD5, SHA-1 | SHA-256 minimum |
| Session resumption | Ticket-based | PSK (pre-shared key) based |
| Forward secrecy | Optional | Mandatory |
TLS 1.3 eliminates several known-weak options that TLS 1.2 still supported (RC4, DES, 3DES, MD5, SHA-1 signatures, RSA key exchange without PFS).
TLS 1.3 in Java 11 — what is supported
- All five TLS 1.3 cipher suites:
TLS_AES_128_GCM_SHA256TLS_AES_256_GCM_SHA384TLS_CHACHA20_POLY1305_SHA256TLS_AES_128_CCM_SHA256TLS_AES_128_CCM_8_SHA256
- 1-RTT handshake
- Session resumption (PSK)
- 0-RTT is supported but disabled by default (replay attack risk)
Enabling and configuring TLS 1.3
By default, Java 11 negotiates TLS 1.3 when both client and server support it. No code changes are needed for most HTTPS clients and servers — the upgrade is automatic.
To force TLS 1.3 explicitly:
SSLContext sslContext = SSLContext.getInstance("TLSv1.3");
sslContext.init(null, null, null);
SSLServerSocketFactory factory = sslContext.getServerSocketFactory();
SSLServerSocket server = (SSLServerSocket) factory.createServerSocket(8443);
// Restrict to TLS 1.3 and specify cipher suites
server.setEnabledProtocols(new String[]{"TLSv1.3"});
server.setEnabledCipherSuites(new String[]{
"TLS_AES_256_GCM_SHA384",
"TLS_CHACHA20_POLY1305_SHA256"
});
Using TLS 1.3 with HttpClient
var sslParams = new SSLParameters();
sslParams.setProtocols(new String[]{"TLSv1.3"});
sslParams.setCipherSuites(new String[]{
"TLS_AES_256_GCM_SHA384",
"TLS_CHACHA20_POLY1305_SHA256"
});
var client = HttpClient.newBuilder()
.sslParameters(sslParams)
.build();
Disabling TLS 1.0 and 1.1 system-wide
Edit $JAVA_HOME/conf/security/java.security:
# Disable TLS 1.0 and 1.1 (already partially restricted in Java 11)
jdk.tls.disabledAlgorithms=SSLv3, TLSv1, TLSv1.1, RC4, DES, MD5withRSA, \
DH keySize < 1024, EC keySize < 224, 3DES_EDE_CBC, anon, NULL
Or set via system property at startup:
java -Djdk.tls.disabledAlgorithms="SSLv3,TLSv1,TLSv1.1,RC4,DES" -jar myapp.jar
ChaCha20 and Poly1305 (JEP 329)
ChaCha20-Poly1305 is a modern AEAD (Authenticated Encryption with Associated Data) cipher suite added to Java 11.
ChaCha20 vs AES-GCM
| Aspect | AES-GCM | ChaCha20-Poly1305 |
|---|---|---|
| Type | Block cipher (with GCM mode) | Stream cipher |
| Hardware acceleration | AES-NI (Intel/AMD x64, ARM AES) | None required |
| Software speed | Slow without AES-NI | Constant high speed |
| Nonce reuse risk | Critical vulnerability | Less catastrophic |
| TLS 1.3 suite | TLS_AES_128_GCM_SHA256 | TLS_CHACHA20_POLY1305_SHA256 |
When to prefer ChaCha20-Poly1305: on mobile devices, IoT hardware, or ARM servers without hardware AES acceleration. Without AES-NI, AES-GCM is 3–5× slower; ChaCha20 runs at the same speed regardless.
Using ChaCha20-Poly1305 in Java
// Stream cipher — encrypt
Cipher cipher = Cipher.getInstance("ChaCha20-Poly1305");
byte[] nonce = new byte[12];
new SecureRandom().nextBytes(nonce);
IvParameterSpec ivSpec = new IvParameterSpec(nonce);
SecretKey key = new SecretKeySpec(keyBytes, "ChaCha20");
cipher.init(Cipher.ENCRYPT_MODE, key, ivSpec);
byte[] ciphertext = cipher.doFinal(plaintext);
// Decrypt
cipher.init(Cipher.DECRYPT_MODE, key, ivSpec);
byte[] decrypted = cipher.doFinal(ciphertext);
Note: ChaCha20-Poly1305 is the AEAD variant (includes authentication tag). The raw ChaCha20 stream cipher is also available separately.
Curve25519 and Curve448 Key Agreement (JEP 324)
Java 11 adds Curve25519 and Curve448 for elliptic-curve Diffie-Hellman key agreement. These modern curves are used in TLS 1.3 and replace the older NIST curves (P-256, P-384) in contexts where their design assumptions are questioned.
Curve25519 characteristics
- Designed by Daniel Bernstein (djb) in 2005
- Fixed-time scalar multiplication — resistant to timing side-channel attacks
- 128-bit security level
- Used in TLS 1.3, SSH, WireGuard, Signal Protocol
Key agreement example
import java.security.*;
import java.security.spec.*;
import javax.crypto.*;
// Generate Curve25519 key pairs
KeyPairGenerator kpg = KeyPairGenerator.getInstance("X25519");
KeyPair aliceKP = kpg.generateKeyPair();
KeyPair bobKP = kpg.generateKeyPair();
// Alice computes shared secret using her private key + Bob's public key
KeyAgreement aliceKA = KeyAgreement.getInstance("X25519");
aliceKA.init(aliceKP.getPrivate());
aliceKA.doPhase(bobKP.getPublic(), true);
byte[] aliceSecret = aliceKA.generateSecret();
// Bob computes shared secret using his private key + Alice's public key
KeyAgreement bobKA = KeyAgreement.getInstance("X25519");
bobKA.init(bobKP.getPrivate());
bobKA.doPhase(aliceKP.getPublic(), true);
byte[] bobSecret = bobKA.generateSecret();
// aliceSecret and bobSecret are equal
assert Arrays.equals(aliceSecret, bobSecret);
SHA-3 Hash Algorithms (JEP 287, Java 9)
Java 9 added SHA-3 (Secure Hash Algorithm 3) — the Keccak-based hash family standardised in FIPS 202. SHA-3 is the backup to SHA-2, designed to be structurally different so that a break in SHA-2 does not affect SHA-3.
// SHA-3 variants: SHA3-224, SHA3-256, SHA3-384, SHA3-512
MessageDigest md = MessageDigest.getInstance("SHA3-256");
byte[] hash = md.digest("Hello, Java 11".getBytes(StandardCharsets.UTF_8));
// Hex string
String hexHash = HexFormat.of().formatHex(hash); // Java 17+
// For Java 11: use String.format or a loop
StringBuilder sb = new StringBuilder();
for (byte b : hash) sb.append(String.format("%02x", b));
System.out.println(sb);
// HMAC with SHA-3
Mac mac = Mac.getInstance("HmacSHA3-256");
SecretKeySpec secretKey = new SecretKeySpec(keyBytes, "HmacSHA3-256");
mac.init(secretKey);
byte[] hmac = mac.doFinal(data);
SHA-3 vs SHA-2 — when to use SHA-3
Use SHA-3 when:
- Your security policy requires it (FIPS 202 compliance)
- You want independence from SHA-2’s Merkle-Damgård construction
- Integrating with systems that specify SHA-3
SHA-2 (SHA-256, SHA-512) is still the practical default — it is widely supported and has no known weaknesses.
DRBG-Based SecureRandom (JEP 273, Java 9)
Java 9 added DRBG (Deterministic Random Bit Generator) implementations to SecureRandom, as specified in NIST SP 800-90Ar1.
// Request a DRBG instance by name and strength
SecureRandom drbg = SecureRandom.getInstance("DRBG",
DrbgParameters.instantiation(
256, // security strength in bits
DrbgParameters.Capability.PR_AND_RESEED, // prediction resistance + reseeding
"my-personalization".getBytes() // optional personalisation string
));
byte[] randomBytes = new byte[32];
drbg.nextBytes(randomBytes,
DrbgParameters.nextBytes(256, true, "additional-input".getBytes()));
DRBG instances are FIPS-compliant — use them when targeting FIPS 140-2/140-3 environments.
Nest-Based Access Control (JEP 181)
Nest-based access control is a JVM-level change (not a developer-facing API) that affects reflection behaviour and bytecode generation.
The pre-Java 11 problem
In Java 8, when a nested class accessed a private member of its enclosing class (or vice versa), the compiler silently generated package-private bridge methods:
class Outer {
private int secret = 42;
class Inner {
void read() {
System.out.println(secret); // compiler generates a bridge method: access$000(Outer)
}
}
}
These synthetic bridge methods were visible in reflection, could be invoked by bytecode manipulation libraries, and added unnecessary overhead.
Java 11 fix
JEP 181 introduces nestmates — logically related classes that share a nest and can access each other’s private members without bridge methods. The JVM enforces nest membership via two new class file attributes:
NestHost— in a nested class, names the host (outer) classNestMembers— in the host class, lists all nested class members
// Java 11 — no bridge methods generated; access is direct at JVM level
class Outer {
private int secret = 42;
class Inner {
void read() {
System.out.println(secret); // direct JVM-level access; no bridge method
}
}
}
Impact on reflection
// Java 11 reflection API additions
Class<?> hostClass = Inner.class.getNestHost(); // returns Outer.class
Class<?>[] members = Outer.class.getNestMembers(); // returns [Outer.class, Inner.class]
boolean areNestmates = Outer.class.isNestmateOf(Inner.class); // true
This matters for libraries that do bytecode manipulation (ASM, Byte Buddy, cglib): they must be updated to emit correct NestHost/NestMembers attributes when generating or transforming nested classes.
SHA-1 Certificate Restriction (JEP 288, Java 9)
Java 9 tightened certificate validation by blocking TLS connections that present SHA-1-signed certificates. SHA-1 has been cryptographically broken since 2017 (SHAttered attack).
If your application connects to a server with a SHA-1 certificate and gets:
javax.net.ssl.SSLHandshakeException: PKIX path building failed
Check the server certificate:
openssl s_client -connect myserver.com:443 </dev/null 2>/dev/null | \
openssl x509 -text -noout | grep "Signature Algorithm"
# If it shows "sha1WithRSAEncryption" — the server cert uses SHA-1
Fix: replace the server certificate with a SHA-256 (or better) signed certificate. As a temporary workaround (not recommended for production), you can re-enable SHA-1 in java.security:
# Remove sha1dsa and sha1withrsa from the disabled list — NOT recommended
jdk.certpath.disabledAlgorithms=MD2, MD5, RSA keySize < 1024, DSA keySize < 1024
What’s Next
Next: Removed and Deprecated APIs: Java EE, JavaFX, Nashorn (JEP 320, 335, 336)