I tried verifying TLS connections using PQ key exchange supported in Aurora MySQL 8.4.8
This page has been translated by machine translation. View original
Introduction
The Aurora MySQL 8.4.8 announced on September 3, 2026 was introduced in a previous article.
This article covers the PQC support that was mentioned in the previous article as something to be introduced at a later date.
8.4.8 supports X25519MLKEM768 and SecP256r1MLKEM768 as PQC hybrid key exchange in TLS 1.3.
This time, we connected from a JDK 27 client and verified the key exchange group selected during the TLS handshake.
Verification Details
We placed one EC2 instance (Amazon Linux 2023, ARM64) in the same VPC as Aurora, and connected from a JDK 27 container running on it.
Verification Environment
For verification, we used JDK 27 (build 27+35) before GA, Aurora MySQL 8.4.8, and MySQL Connector/J 9.0.0. The JDK version is as follows.
openjdk version "27" 2026-09-15
OpenJDK Runtime Environment (build 27+35-2325)
OpenJDK 64-Bit Server VM (build 27+35-2325, mixed mode, sharing)
The Aurora version and TLS settings for the connection destination were verified with the following queries.
SELECT VERSION();
SHOW VARIABLES LIKE 'tls%';
SHOW VARIABLES LIKE 'ssl%';
- VERSION(): 8.4.8
- tls_version: TLSv1.2,TLSv1.3
- tls_ciphersuites: TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384
No items for enabling or disabling PQ key exchange were found in the tls% and ssl% variables.
Connection Client
The JDK source and Connector/J version are as shown in the Dockerfile.
Dockerfile for JDK 27 client
FROM debian:bookworm-slim
RUN apt-get update && apt-get install -y --no-install-recommends \
curl ca-certificates \
&& rm -rf /var/lib/apt/lists/*
ARG JDK_URL=https://download.java.net/java/GA/jdk27/55ce5470a6294008af0057ff4626d0e5/35/GPL/openjdk-27_linux-aarch64_bin.tar.gz
RUN curl -fsSL ${JDK_URL} | tar -xz -C /opt \
&& ln -s /opt/jdk-27 /opt/java
ENV JAVA_HOME=/opt/java
ENV PATH="${JAVA_HOME}/bin:${PATH}"
WORKDIR /app
ADD https://repo1.maven.org/maven2/com/mysql/mysql-connector-j/9.0.0/mysql-connector-j-9.0.0.jar /app/mysql-connector-j.jar
COPY MysqlTlsTest.java .
RUN javac -cp mysql-connector-j.jar MysqlTlsTest.java
CMD ["java", "-Djavax.net.debug=ssl:handshake", "-cp", ".:mysql-connector-j.jar", "MysqlTlsTest"]
The configuration section of the code used for the connection is as follows. The handshake log obtained with this configuration is from a connection with certificate verification disabled.
String url = String.format("jdbc:mysql://%s:%s/%s", host, port, database);
Properties props = new Properties();
props.setProperty("user", user);
props.setProperty("password", password);
props.setProperty("useSSL", "true");
props.setProperty("requireSSL", "true");
props.setProperty("verifyServerCertificate", "false");
The three SSL-related properties above are deprecated since Connector/J 8. The way to write them when enabling certificate verification will be described later.
The build and execution were performed with the following commands.
docker build -f Dockerfile.jdk27 -t mysql-tls-java-jdk27 java-client/
docker run --rm \
-e MYSQL_HOST="$MYSQL_HOST" \
-e MYSQL_PORT=3306 \
-e MYSQL_USER=admin \
-e MYSQL_PASSWORD="$MYSQL_PASSWORD" \
-e MYSQL_DATABASE=mysql \
mysql-tls-java-jdk27 > jdk27-handshake.log 2>&1
The key exchange group only appears in the handshake log. We ran it with -Djavax.net.debug=ssl:handshake in the Dockerfile's CMD and read the ServerHello from the output log.
Quick Verification with OpenSSL
If you cannot immediately prepare a PQC-compatible JDK, you can first check whether the source OpenSSL has X25519MLKEM768. We ran the following commands on this EC2.
openssl version
openssl list -tls-groups
The OpenSSL version and supported groups were as follows.
OpenSSL 3.5.7 9 Jun 2026 (Library: OpenSSL 3.5.7 9 Jun 2026)
secp256r1:secp384r1:secp521r1:x25519:x448:brainpoolP256r1tls13:brainpoolP384r1tls13:brainpoolP512r1tls13:ffdhe2048:ffdhe3072:ffdhe4096:ffdhe6144:ffdhe8192:MLKEM512:MLKEM768:MLKEM1024:SecP256r1MLKEM768:X25519MLKEM768:SecP384r1MLKEM1024
MLKEM-based groups were listed in the latter half of the list, and X25519MLKEM768 was also included. This can be used as a way to first isolate the client-side support status when PQ key exchange does not succeed. However, a group existing in the library and that group being presented and selected during connection are different things. Whether it succeeded or not is read from the handshake log below.
Handshake Verification
The JDK 27 client presented X25519MLKEM768 in the supported_groups of the ClientHello.
"supported_groups (10)": {
"named groups": [X25519MLKEM768, x25519, secp256r1, secp384r1, secp521r1, x448, ffdhe2048, ffdhe3072, ffdhe4096]
},
In the subsequent ServerHello, Aurora selected X25519MLKEM768.
"ServerHello": {
"server version" : "TLSv1.2",
"cipher suite" : "TLS_AES_256_GCM_SHA384(0x1302)",
"compression methods" : "00",
"extensions" : [
"key_share (51)": {
"server_share": {
"named group": X25519MLKEM768
The key_share in TLS 1.3 is the agreed key exchange group itself. From this "named group": X25519MLKEM768, we can confirm that this group was used by both the server and the client. The server version in the quote is a field that contains TLSv1.2 for compatibility. The actually negotiated version appears in Negotiated protocol version in the log.
javax.net.ssl|DEBUG|30|main|2026-09-07 04:41:02.984 UTC|ServerHello.java:1049|Negotiated protocol version: TLSv1.3
Not only the handshake but also the connection was established, and the cipher suite and TLS version of the session were as follows.
Connected successfully!
=== TLS Session Status ===
Ssl_cipher: TLS_AES_256_GCM_SHA384
Ssl_version: TLSv1.3
Combined Use with Certificate Verification
We verified whether the same group would be selected even with certificate verification enabled.
We set Connector/J's sslMode to VERIFY_IDENTITY, imported the RDS CA bundle into the truststore, and ran it. The bundle used was https://truststore.pki.rds.amazonaws.com/ap-northeast-1/ap-northeast-1-bundle.pem (retrieved on 2026-09-07). The connection properties are as follows.
Properties props = new Properties();
props.setProperty("user", user);
props.setProperty("password", password);
props.setProperty("sslMode", "VERIFY_IDENTITY");
props.setProperty("trustCertificateKeyStoreUrl", "file:/app/rds-truststore.p12");
props.setProperty("trustCertificateKeyStoreType", "PKCS12");
props.setProperty("trustCertificateKeyStorePassword", "changeit");
Even with this configuration, the server_share in ServerHello was the same X25519MLKEM768.
Summary
With Aurora MySQL 8.4.8, which supports PQC key exchange, PQ key exchange was established by making the client PQC-compatible. This was confirmed in the ServerHello of the handshake log.
Government agencies and similar organizations have indicated policies aimed at transitioning to PQC by 2035.
PQ key exchange became available in Aurora MySQL 8.4.8, following MySQL 26.7.0 in July 2026. On the client side, JDK 27, which has PQ key exchange enabled by default, is scheduled to GA on 2026-09-15.
If you plan to adopt Aurora MySQL in the future and there is a possibility of being required to support PQC, we recommend verifying whether PQ key exchange can be used with the combination of Aurora MySQL 8.4.8, PQC-compatible middleware, and JDK.
Reference Links
