RDS for PostgreSQL でポスト量子 TLS 鍵交換を試してみた

RDS for PostgreSQL でポスト量子 TLS 鍵交換を試してみた

RDS for PostgreSQL 18.6 のパラメータグループで ssl_groups に X25519MLKEM768 を設定し、OpenSSL と JDK 27 の JDBC からポスト量子鍵交換で接続できることを確認しました。
2026.09.25

はじめに

2026年9月24日、Amazon RDS for PostgreSQL が TLS のポスト量子鍵交換に対応しました。

https://aws.amazon.com/jp/about-aws/whats-new/2026/09/postgresql-post-quantum-tls-key-exchange/

Aurora MySQL のポスト量子鍵交換は、先行記事で紹介しています。

https://dev.classmethod.jp/articles/aurora-mysql-pqtls-jdk27/

RDS for PostgreSQL も対応したので、OpenSSL と JDK 27(Corretto 27)から接続して鍵交換グループを確認しました。Corretto 27 側のポスト量子 TLS 対応は次の記事で扱っています。

https://dev.classmethod.jp/articles/amazon-corretto27-ga-pq-tls/

検証環境

項目 値
RDS エンジン PostgreSQL 18.6
接続元 EC2 Amazon Linux 2023(aarch64)
OpenSSL(接続元 EC2) 3.5.8
JDK Amazon Corretto 27
PostgreSQL JDBC ドライバ 42.7.7
リージョン ap-northeast-1

ssl_groups に X25519MLKEM768 を設定する

対象の DB インスタンスには、あらかじめ作成したパラメータグループ pq-tls-pg18 を適用しています。このパラメータグループの ssl_groups に、ポスト量子グループ X25519MLKEM768 を設定しました。

aws rds modify-db-parameter-group \
  --db-parameter-group-name pq-tls-pg18 \
  --parameters "ParameterName=ssl_groups,ParameterValue=X25519MLKEM768,ApplyMethod=immediate" \
  --region ap-northeast-1

設定後の値と、指定できる値(AllowedValues)は次のとおりです。

[
    {
        "ParameterName": "ssl_groups",
        "ParameterValue": "X25519MLKEM768",
        "Description": "Sets the named group(s) to use for TLS key exchange",
        "Source": "user",
        "ApplyType": "dynamic",
        "DataType": "list",
        "AllowedValues": "X25519MLKEM768, SecP256r1MLKEM768, X25519, prime256v1, secp384r1",
        "IsModifiable": true,
        "ApplyMethod": "immediate"
    }
]

指定できるのは AllowedValues にあるグループのみです。今回はポスト量子鍵交換を確認するため X25519MLKEM768 のみを設定しました。

OpenSSL で接続して鍵交換グループを確認する

接続元 EC2 から s_client で接続しました。

echo "" | openssl s_client \
  -connect pq-tls-pg18.xxxxxxxxxxxx.ap-northeast-1.rds.amazonaws.com:5432 \
  -starttls postgres \
  -tls1_3 \
  -groups X25519MLKEM768:x25519:prime256v1 \
  -trace 2>&1

出力のうち、鍵交換グループ・暗号スイート・プロトコルの行だけ抜き出すと次のとおりです。

Negotiated TLS1.3 group: X25519MLKEM768
New, TLSv1.3, Cipher is TLS_AES_256_GCM_SHA384
Protocol: TLSv1.3

ssl_groups に設定した X25519MLKEM768 で鍵交換が成立しました。

Corretto 27 の JDBC 接続で確認する

次に、接続元 EC2 上の Docker コンテナで動かした Corretto 27 から JDBC で接続しました。接続プロパティはユーザー、パスワード、ssl、sslmode だけで、鍵交換グループは指定していません(コードは節末尾に置いています)。ハンドシェイクのログは -Djavax.net.debug=ssl:handshake で採りました。

ClientHello の supported_groups は次の並びでした。

"supported_groups (10)": {
  "named groups": [X25519MLKEM768, x25519, secp256r1, secp384r1, secp521r1, x448, ffdhe2048, ffdhe3072, ffdhe4096]
}

アプリ側で何も指定していなくても、X25519MLKEM768 が先頭に来ています。これに対してサーバーが返した ServerHello の key_share も X25519MLKEM768 でした。

"key_share (51)": {
  "server_share": {
    "named group": X25519MLKEM768

プロトコルは TLS 1.3 です。

Negotiated protocol version: TLSv1.3

サーバーが許す唯一のグループである X25519MLKEM768 で、JDBC からも接続できました。

接続に使った Dockerfile・Java コードと実行手順

Dockerfile

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 TARGETARCH
RUN case "${TARGETARCH}" in \
      amd64) JDK_URL="https://corretto.aws/downloads/latest/amazon-corretto-27-x64-linux-jdk.tar.gz" ;; \
      arm64) JDK_URL="https://corretto.aws/downloads/latest/amazon-corretto-27-aarch64-linux-jdk.tar.gz" ;; \
      *) echo "Unsupported arch: ${TARGETARCH}" && exit 1 ;; \
    esac \
    && curl -fsSL "${JDK_URL}" | tar -xz -C /opt \
    && ln -s /opt/amazon-corretto-27* /opt/java

ENV JAVA_HOME=/opt/java
ENV PATH="${JAVA_HOME}/bin:${PATH}"

WORKDIR /app

ADD https://repo1.maven.org/maven2/org/postgresql/postgresql/42.7.7/postgresql-42.7.7.jar /app/postgresql.jar

COPY PgTlsCheck.java .
RUN javac -cp postgresql.jar PgTlsCheck.java

CMD ["java", \
     "-Djavax.net.debug=ssl:handshake", \
     "-cp", ".:postgresql.jar", \
     "PgTlsCheck"]

PgTlsCheck.java

import java.sql.*;
import java.util.Properties;

public class PgTlsCheck {

    public static void main(String[] args) throws Exception {
        String host = System.getenv("PG_HOST");
        String port = System.getenv().getOrDefault("PG_PORT", "5432");
        String user = System.getenv().getOrDefault("PG_USER", "pgadmin");
        String pass = System.getenv("PG_PASSWORD");
        String db   = System.getenv().getOrDefault("PG_DB", "postgres");

        System.out.println("=== Corretto 27 PQ TLS Check (PostgreSQL) ===");
        System.out.println("Target: " + host + ":" + port + "/" + db);
        System.out.println("Java version: " + System.getProperty("java.version"));
        System.out.println("Java vendor:  " + System.getProperty("java.vendor"));
        System.out.println();

        String url = "jdbc:postgresql://" + host + ":" + port + "/" + db;

        Properties props = new Properties();
        props.setProperty("user", user);
        props.setProperty("password", pass);
        props.setProperty("ssl", "true");
        props.setProperty("sslmode", "require");

        try (Connection conn = DriverManager.getConnection(url, props);
             Statement  stmt = conn.createStatement()) {

            System.out.println("Connected successfully!");
            System.out.println();

            System.out.println("--- TLS Session Status ---");
            try (ResultSet rs = stmt.executeQuery(
                    "SELECT ssl, version, cipher, bits FROM pg_stat_ssl WHERE pid = pg_backend_pid()")) {
                if (rs.next()) {
                    System.out.println("ssl:     " + rs.getBoolean("ssl"));
                    System.out.println("version: " + rs.getString("version"));
                    System.out.println("cipher:  " + rs.getString("cipher"));
                    System.out.println("bits:    " + rs.getInt("bits"));
                }
            }

            try (ResultSet rs = stmt.executeQuery("SELECT version()")) {
                if (rs.next()) System.out.println("PostgreSQL: " + rs.getString(1));
            }
        }
    }
}

ビルドと実行(接続元 EC2 上)

# ビルド
docker build -t pg-pq-tls .

# 実行(-Djavax.net.debug=ssl:handshake は Dockerfile の CMD に含む)
docker run --rm \
  -e PG_HOST=pq-tls-pg18.xxxxxxxxxxxx.ap-northeast-1.rds.amazonaws.com \
  -e PG_PASSWORD="$PG_PASSWORD" \
  pg-pq-tls

まとめ

RDS for PostgreSQL でポスト量子鍵交換を利用可能なことを確認できました。

2035年までのポスト量子暗号(PQC)移行を目指すガイドライン対応が求められる場合、ポスト量子鍵交換に対応したバージョンの RDS for PostgreSQL を採用し、パラメータグループの ssl_groups にポスト量子グループを設定してご利用ください。

この記事をシェアする

AWSのお困り事はクラスメソッドへ

関連記事