From ae83cf512706c9120f11de54e9c409a05ad34b7a Mon Sep 17 00:00:00 2001 From: Lawrence Qiu Date: Thu, 30 Jul 2026 03:21:32 +0000 Subject: [PATCH 01/25] docs: add Post-Quantum Cryptography (PQC) User Guide --- docs/post_quantum_cryptography_guide.md | 281 ++++++++++++++++++++++++ 1 file changed, 281 insertions(+) create mode 100644 docs/post_quantum_cryptography_guide.md diff --git a/docs/post_quantum_cryptography_guide.md b/docs/post_quantum_cryptography_guide.md new file mode 100644 index 000000000000..418e62a87486 --- /dev/null +++ b/docs/post_quantum_cryptography_guide.md @@ -0,0 +1,281 @@ +# Post-Quantum Cryptography (PQC) User Guide for Java Client Libraries + +## Overview + +**Post-Quantum Cryptography (PQC)** refers to cryptographic algorithms designed to secure communications against future attacks by quantum computers. Quantum computers utilizing Shor's algorithm threaten traditional public-key algorithms (such as RSA and ECDH key exchange) by making it possible to retroactively decrypt intercepted TLS communications ("store-now, decrypt-later" attacks). + +Google Cloud Java client libraries (via `gax-grpc` and `gax-httpjson`) provide out-of-the-box support for **hybrid PQC key exchange** (combining classical algorithms like `X25519` with post-quantum key encapsulation mechanisms like `ML-KEM-768` / `X25519MLKEM768`). This hybrid approach guarantees that security is at least as strong as traditional TLS 1.3 even if post-quantum algorithms encounter unforeseen implementation flaws, while protecting present-day encrypted traffic against future quantum decryption. + +--- + +## Default Behavior + +PQC support is **enabled by default** for both **gRPC** (`gax-grpc`) and **HTTP/JSON** (REST, `gax-httpjson`) transports in Google Cloud Java client libraries whenever native BoringSSL/Conscrypt libraries are available on the runtime environment. + +### Transport Support Summary + +| Transport | GAX Module | Underlying Transport Library | Native Engine | PQC Activation | +| :--- | :--- | :--- | :--- | :--- | +| **HTTP/JSON** | `gax-httpjson` | Google HTTP Client (`NetHttpTransport`) | Conscrypt (BoringSSL JNI) | Enabled via `google-http-java-client` Conscrypt provider API | +| **gRPC** | `gax-grpc` | gRPC-Java (`grpc-netty-shaded` / Netty) | Netty-tcnative (BoringSSL JNI) or Conscrypt | Built-in via gRPC-Java v1.83.0+ | + +--- + +## Transport Implementation Details + +The underlying TLS implementation and configuration mechanism differs between HTTP/JSON and gRPC. + +### 1. HTTP/JSON Transport (`gax-httpjson` & `google-http-java-client`) + +For REST/HTTP transport, PQC enablement relies on updates introduced in `google-http-java-client`: + +- **`google-http-java-client` API Enhancements**: `NetHttpTransport.Builder` introduced `.setSecurityProvider(Provider)` and `.setSslSocketConfigurator(...)`. This allows higher-level libraries (like GAX) to register a specific Security Provider and customize `SSLSocket` / `SSLEngine` instances created by standard Java `HttpsURLConnection`. +- **GAX Integration (`HttpJsonConscryptUtils`)**: GAX uses these APIs to register **Conscrypt** as the security provider and set a socket configurator (`Conscrypt.setUseEngineSocket(socket, true)`). +- **TLS 1.3 Negotiation**: When HTTPS connections are opened, Conscrypt advertises `X25519MLKEM768` to Google Front End (GFE) endpoints during the TLS 1.3 handshake. + +``` ++-------------------------------------------------------------------+ +| GAPIC HTTP/JSON Client Request | ++-------------------------------------------------------------------+ + | + Is Conscrypt JNI Available on Platform? + | + +----------------+----------------+ + | | + [ YES ] [ NO ] + | | + v v + google-http-client registers Conscrypt Falls back to JDK TLS (JSSE) + Offers X25519MLKEM768 (PQC) Offers Classical TLS (X25519) +``` + +### 2. gRPC Transport (`gax-grpc` & gRPC-Java v1.83.0+) + +For gRPC transport, PQC key exchange is built into **gRPC-Java v1.83.0+**: + +- **BoringSSL under the Hood**: gRPC-Java (`grpc-netty-shaded`) defaults to Netty's `netty-tcnative` (Netty's Tomcat Native JNI wrapper around **BoringSSL**). Like Conscrypt, it uses BoringSSL for C-level cryptographic execution. +- **gRPC-Java v1.83.0+ PQC Support**: Starting in version 1.83.0, `grpc-netty-shaded` has PQC hybrid key exchange (`X25519MLKEM768`) enabled by default for TLS 1.3 connections. +- **ALPN & Channel Pooling**: gRPC-Java advertises HTTP/2 (`h2`) via ALPN while offering `X25519MLKEM768` in the ClientHello. This negotiation operates seamlessly across all channels in GAX's `ChannelPoolSettings`. + +``` ++-------------------------------------------------------------------+ +| GAPIC gRPC Client Request | ++-------------------------------------------------------------------+ + | + gRPC-Java v1.83.0+ Netty Channel Builder + | + Is Netty-tcnative / Conscrypt JNI Available? + | + +----------------+----------------+ + | | + [ YES ] [ NO ] + | | + v v + Netty SSLContext uses BoringSSL/Conscrypt Netty uses Standard JDK JSSE + Offers X25519MLKEM768 (PQC) Offers Classical TLS (X25519) +``` + +--- + +## Conscrypt Capabilities & Supported Algorithms + +Conscrypt provides high-performance TLS and cryptographic operations by wrapping BoringSSL via JNI native libraries. + +> [!NOTE] +> For a full, up-to-date listing of named groups and capabilities supported across Conscrypt versions, refer to the official [Conscrypt Capabilities Documentation](https://github.com/google/conscrypt/blob/2.6.0/CAPABILITIES.md#supported-named-groups). + +### Supported PQC & Hybrid Key Exchange Groups + +Conscrypt supports several post-quantum and hybrid named groups for TLS 1.3 key exchange: + +| Named Group Identifier | Description | Status in Conscrypt | +| :--- | :--- | :--- | +| `X25519MLKEM768` | Primary hybrid group combining X25519 ECDH with NIST FIPS 203 ML-KEM-768. | Recommended / Offered by Default | +| `SecP256r1MLKEM768` | Hybrid group combining NIST P-256 (secp256r1) with ML-KEM-768. | Supported | +| `X25519Kyber768Draft00` | Pre-standardization draft hybrid group combining X25519 with Kyber-768. | Legacy / Supported for backward compatibility | +| `MLKEM1024` | Standalone high-security post-quantum key encapsulation mechanism. | Supported | + +### Supported Classical (Non-PQC) Groups + +For environments or server endpoints where PQC key exchange is disabled or unsupported, Conscrypt falls back to classical named groups: + +- `X25519` (Curve25519 ECDH) +- `SecP256r1` (NIST P-256 ECDH) +- `SecP384r1` (NIST P-384 ECDH) +- `SecP521r1` (NIST P-521 ECDH) + +### What to Do If a Required Algorithm Is Unsupported + +If your application or security policy mandates a specific PQC algorithm variant that Conscrypt does not support (or if you must use a custom security module): +1. Configure a custom Security Provider (such as Bouncy Castle) as described in [Alternatives & How to Configure Them](#alternatives--how-to-configure-them). +2. Explicitly override the transport builder's channel provider or `SSLContext`. + +--- + +## Limitations of Native PQC Engines (Conscrypt & Netty-tcnative) + +Both HTTP/JSON (via Conscrypt) and gRPC (via Netty-tcnative / BoringSSL) rely on C native shared libraries loaded via JNI. Consequently, **both transports share the same platform limitations**: + +1. **JNI Native Binary Dependencies**: + - Conscrypt uses `conscrypt-openjdk-uber`, which extracts `.so`, `.dylib`, or `.dll` native libraries into temporary directories at runtime. + - `grpc-netty-shaded` embeds pre-compiled `netty-tcnative` BoringSSL native libraries into its JAR. + +2. **System & GLIBC Compatibility Constraints**: + - **Linux glibc Versioning**: Native C binaries require compatible C runtime (`glibc`) versions (e.g. `GLIBC_2.35+`). Older Linux enterprise distributions or base images with older `glibc` releases will fail to load native libraries (`UnsatisfiedLinkError`). + - **Restricted / Read-Only Filesystems**: Environments that mount `/tmp` with `noexec`, strict container runtimes, Android/GraalVM native images without JNI support, or security managers blocking C library loading will prevent native PQC initialization. + +3. **Graceful Fallback Behavior**: + When native C libraries fail to load for either transport, the client libraries safely fall back to standard JDK JSSE: + ``` + WARNING: Conscrypt native libraries not available. Falling back to JDK TLS. + java.lang.UnsatisfiedLinkError: ... libc.so.6: version `GLIBC_2.35' not found + ``` + The client will continue operating using classical TLS provided by the JDK. + +--- + +## Alternatives & How to Configure Them + +If you need to disable PQC, force classical key exchange, or use a custom TLS engine, you can configure alternative transport providers for both gRPC and HTTP/JSON. + +### Alternative 1: Forcing Classical (Non-PQC) Key Exchange (HTTP/JSON) + +To explicitly force classical key exchange (such as `X25519` or `SecP256r1`) for HTTP/JSON clients: + +```java +import com.google.api.client.http.javanet.NetHttpTransport; +import com.google.api.gax.httpjson.HttpJsonConscryptUtils; +import com.google.api.gax.httpjson.InstantiatingHttpJsonChannelProvider; +import com.google.cloud.secretmanager.v1.SecretManagerServiceSettings; +import org.conscrypt.Conscrypt; + +// Step 1: Create NetHttpTransport configured with explicit classical named groups +NetHttpTransport transport = + HttpJsonConscryptUtils.configureConscryptSecurityProvider(new NetHttpTransport.Builder()) + .setSslSocketConfigurator( + socket -> { + if (Conscrypt.isConscrypt(socket)) { + try { + // Explicitly offer only classical X25519 (disabling PQC hybrid groups) + Conscrypt.setNamedGroups(socket, new String[] {"X25519"}); + } catch (Exception e) { + // Handle or log socket configuration failure + } + } + }) + .build(); + +// Step 2: Build transport channel provider using custom transport +InstantiatingHttpJsonChannelProvider transportChannelProvider = + SecretManagerServiceSettings.defaultHttpJsonTransportProviderBuilder() + .setHttpTransport(transport) + .build(); + +// Step 3: Instantiate client with settings +SecretManagerServiceSettings settings = + SecretManagerServiceSettings.newHttpJsonBuilder() + .setTransportChannelProvider(transportChannelProvider) + .build(); +``` + +### Alternative 2: Forcing Classical (Non-PQC) Key Exchange (gRPC) + +For gRPC clients, you can configure `InstantiatingGrpcChannelProvider` with custom Netty SSL context options to restrict key exchange groups: + +```java +import com.google.api.gax.grpc.InstantiatingGrpcChannelProvider; +import com.google.cloud.secretmanager.v1.SecretManagerServiceSettings; + +InstantiatingGrpcChannelProvider transportChannelProvider = + SecretManagerServiceSettings.defaultGrpcTransportProviderBuilder() + .setChannelConfigurator( + managedChannelBuilder -> { + // Custom channel configuration to override SSL/TLS settings + }) + .build(); + +SecretManagerServiceSettings settings = + SecretManagerServiceSettings.newBuilder() + .setTransportChannelProvider(transportChannelProvider) + .build(); +``` + +### Alternative 3: Bypassing Conscrypt to Use Standard JDK JSSE (HTTP/JSON) + +If you prefer to bypass Conscrypt completely and use the standard JDK JSSE provider: + +```java +import com.google.api.client.http.javanet.NetHttpTransport; +import com.google.api.gax.httpjson.InstantiatingHttpJsonChannelProvider; +import com.google.cloud.secretmanager.v1.SecretManagerServiceClient; +import com.google.cloud.secretmanager.v1.SecretManagerServiceSettings; + +// Build standard NetHttpTransport without Conscrypt configuration +NetHttpTransport standardTransport = new NetHttpTransport.Builder().build(); + +InstantiatingHttpJsonChannelProvider transportProvider = + SecretManagerServiceSettings.defaultHttpJsonTransportProviderBuilder() + .setHttpTransport(standardTransport) + .build(); + +SecretManagerServiceSettings settings = + SecretManagerServiceSettings.newHttpJsonBuilder() + .setTransportChannelProvider(transportProvider) + .build(); + +try (SecretManagerServiceClient client = SecretManagerServiceClient.create(settings)) { + // Client uses standard JDK JSSE TLS +} +``` + +### Alternative 4: Configuring Custom Security Providers (e.g., Bouncy Castle) + +To use a third-party Security Provider (such as Bouncy Castle) for TLS: + +```java +import com.google.api.client.http.javanet.NetHttpTransport; +import com.google.api.gax.httpjson.InstantiatingHttpJsonChannelProvider; +import java.security.Provider; +import java.security.Security; +import javax.net.ssl.SSLContext; + +// Register custom provider +Provider customProvider = new org.bouncycastle.jce.provider.BouncyCastleProvider(); +Security.addProvider(customProvider); + +// Initialize custom SSLContext +SSLContext sslContext = SSLContext.getInstance("TLS", customProvider); +sslContext.init(null, null, null); + +// Configure transport builder with custom SSLSocketFactory +NetHttpTransport customTransport = + new NetHttpTransport.Builder() + .setSslSocketFactory(sslContext.getSocketFactory()) + .build(); + +InstantiatingHttpJsonChannelProvider transportProvider = + SecretManagerServiceSettings.defaultHttpJsonTransportProviderBuilder() + .setHttpTransport(customTransport) + .build(); +``` + +--- + +## Future Roadmap: JDK 27+ and Native JDK PQC Support + +As quantum-resistant cryptography standards mature, Java is incorporating native PQC support directly into standard OpenJDK distributions. + +> [!IMPORTANT] +> **JDK 27+ Native PQC Support**: +> Starting with JDK 27, standard JDK Security Providers (SunJSSE) will include native support for NIST post-quantum key encapsulation standards (JEP / ML-KEM). + +### What JDK 27+ Means for Java SDK Users + +1. **Zero-Dependency Native PQC**: + On JDK 27 and future Java LTS releases, applications running standard OpenJDK will automatically negotiate PQC key exchange natively out-of-the-box—even without Conscrypt or JNI native dependencies. + +2. **Forward Compatibility**: + The GAX transport layer (`gax-grpc` and `gax-httpjson`) is designed so that when running on JDK 27+: + - If native BoringSSL libraries (Conscrypt / Netty-tcnative) are present, they continue to offer hardware-accelerated PQC key exchange. + - If native libraries are absent or disabled, the JDK's standard JSSE provider natively offers ML-KEM PQC key exchange. + - Applications do not need to make any code or configuration changes when upgrading to JDK 27+. From d588590ff02dedd5a09084b1a504f39527e8a605 Mon Sep 17 00:00:00 2001 From: Lawrence Qiu Date: Thu, 30 Jul 2026 16:53:38 +0000 Subject: [PATCH 02/25] docs: refine PQC user guide for HTTP/JSON transport with verification steps and locally scoped security providers --- docs/post_quantum_cryptography_guide.md | 258 ++++++++++++------------ 1 file changed, 131 insertions(+), 127 deletions(-) diff --git a/docs/post_quantum_cryptography_guide.md b/docs/post_quantum_cryptography_guide.md index 418e62a87486..3c6404806d0c 100644 --- a/docs/post_quantum_cryptography_guide.md +++ b/docs/post_quantum_cryptography_guide.md @@ -1,151 +1,167 @@ -# Post-Quantum Cryptography (PQC) User Guide for Java Client Libraries +# Post-Quantum Cryptography (PQC) User Guide for HTTP/JSON Java Client Libraries -## Overview +## 1. The Quantum Threat & Why PQC is Critical -**Post-Quantum Cryptography (PQC)** refers to cryptographic algorithms designed to secure communications against future attacks by quantum computers. Quantum computers utilizing Shor's algorithm threaten traditional public-key algorithms (such as RSA and ECDH key exchange) by making it possible to retroactively decrypt intercepted TLS communications ("store-now, decrypt-later" attacks). +### The Problem: Store-Now, Decrypt-Later (SNDL) Attacks +Traditional Transport Layer Security (TLS) relies on classical asymmetric public-key cryptography—such as RSA, Elliptic Curve Diffie-Hellman (`ECDH`), and `X25519`—to establish secure encrypted connections. While these classical algorithms are computationally secure against present-day classical computers, they are vulnerable to **Shor's algorithm** running on a cryptographically relevant quantum computer (CRQC). -Google Cloud Java client libraries (via `gax-grpc` and `gax-httpjson`) provide out-of-the-box support for **hybrid PQC key exchange** (combining classical algorithms like `X25519` with post-quantum key encapsulation mechanisms like `ML-KEM-768` / `X25519MLKEM768`). This hybrid approach guarantees that security is at least as strong as traditional TLS 1.3 even if post-quantum algorithms encounter unforeseen implementation flaws, while protecting present-day encrypted traffic against future quantum decryption. +An adversary does not need to wait for a quantum computer to be built before attacking classical encryption: +- **Harvest Now, Decrypt Later**: Threat actors can intercept and store encrypted TLS network traffic today. +- **Future Decryption**: Once a sufficiently powerful quantum computer becomes operational, adversaries will be able to retroactively break the classical Diffie-Hellman key exchange and decrypt long-lived confidential data collected years earlier. + +### The Consequence of Not Using PQC +Without Post-Quantum Cryptography (PQC), any sensitive data transmitted across networks today—including authentication credentials, financial records, proprietary algorithms, and customer data—remains vulnerable to retroactive decryption in the future. + +### The Solution: Hybrid PQC Key Exchange +To mitigate this threat immediately without sacrificing present-day security, Google Cloud HTTP/JSON Java client libraries support **Hybrid PQC Key Exchange**. +- A hybrid key exchange combines a classical ECDH algorithm (such as `X25519`) with a NIST-standardized Post-Quantum Key Encapsulation Mechanism (KEM), such as **ML-KEM-768** (FIPS 203), negotiated as `X25519MLKEM768`. +- This ensures that your communications remain at least as secure as standard classical TLS 1.3 against present-day attacks, while simultaneously protecting encrypted sessions against future quantum decryption. --- -## Default Behavior +## 2. Overview & Default Behavior in `gax-httpjson` -PQC support is **enabled by default** for both **gRPC** (`gax-grpc`) and **HTTP/JSON** (REST, `gax-httpjson`) transports in Google Cloud Java client libraries whenever native BoringSSL/Conscrypt libraries are available on the runtime environment. +PQC support is **enabled by default** for **HTTP/JSON** (REST) transport in Google Cloud Java client libraries (`gax-httpjson`) whenever native Conscrypt / BoringSSL libraries are supported on the runtime environment. + +> [!NOTE] +> This guide currently focuses on **HTTP/JSON (`gax-httpjson`)** client libraries. Support for gRPC (`gax-grpc`) is under active development and will be detailed in an upcoming release. ### Transport Support Summary -| Transport | GAX Module | Underlying Transport Library | Native Engine | PQC Activation | +| Transport | GAX Module | Underlying HTTP Client | Cryptographic Engine | PQC Activation | | :--- | :--- | :--- | :--- | :--- | -| **HTTP/JSON** | `gax-httpjson` | Google HTTP Client (`NetHttpTransport`) | Conscrypt (BoringSSL JNI) | Enabled via `google-http-java-client` Conscrypt provider API | -| **gRPC** | `gax-grpc` | gRPC-Java (`grpc-netty-shaded` / Netty) | Netty-tcnative (BoringSSL JNI) or Conscrypt | Built-in via gRPC-Java v1.83.0+ | +| **HTTP/JSON** | `gax-httpjson` | Google HTTP Client (`NetHttpTransport`) | Conscrypt (BoringSSL JNI) | **Enabled by Default** via `google-http-java-client` security provider API | --- -## Transport Implementation Details +## 3. How to Verify That You Are Using PQC -The underlying TLS implementation and configuration mechanism differs between HTTP/JSON and gRPC. +You can verify that your HTTP/JSON client library is actively negotiating Post-Quantum Cryptography through operational logs, debug logging, or network traffic analysis. -### 1. HTTP/JSON Transport (`gax-httpjson` & `google-http-java-client`) - -For REST/HTTP transport, PQC enablement relies on updates introduced in `google-http-java-client`: - -- **`google-http-java-client` API Enhancements**: `NetHttpTransport.Builder` introduced `.setSecurityProvider(Provider)` and `.setSslSocketConfigurator(...)`. This allows higher-level libraries (like GAX) to register a specific Security Provider and customize `SSLSocket` / `SSLEngine` instances created by standard Java `HttpsURLConnection`. -- **GAX Integration (`HttpJsonConscryptUtils`)**: GAX uses these APIs to register **Conscrypt** as the security provider and set a socket configurator (`Conscrypt.setUseEngineSocket(socket, true)`). -- **TLS 1.3 Negotiation**: When HTTPS connections are opened, Conscrypt advertises `X25519MLKEM768` to Google Front End (GFE) endpoints during the TLS 1.3 handshake. +### 1. Check Operational Log Messages +When Conscrypt initializes successfully and configures PQC named groups, **no warning logs are emitted**. +If your environment cannot load native Conscrypt libraries or cannot configure PQC groups, the library emits a concise, one-line warning at `Level.WARNING` and safely falls back to standard JDK TLS: ``` -+-------------------------------------------------------------------+ -| GAPIC HTTP/JSON Client Request | -+-------------------------------------------------------------------+ - | - Is Conscrypt JNI Available on Platform? - | - +----------------+----------------+ - | | - [ YES ] [ NO ] - | | - v v - google-http-client registers Conscrypt Falls back to JDK TLS (JSSE) - Offers X25519MLKEM768 (PQC) Offers Classical TLS (X25519) +WARNING: Conscrypt native libraries not available. Falling back to JDK TLS. ``` +If you **do not see this warning message** in your application logs, Conscrypt has successfully initialized and enabled PQC key exchange. + +### 2. Enable Debug Logging (`Level.FINE`) +To inspect the exact initialization status and any underlying native library loader exceptions, enable debug logging (`Level.FINE`) for `com.google.api.gax.httpjson.HttpJsonConscryptUtils`: + +- In `logging.properties`: + ```properties + com.google.api.gax.httpjson.HttpJsonConscryptUtils.level = FINE + ``` +- If an error occurs during initialization, the full exception stacktrace (`UnsatisfiedLinkError`, `LinkageError`, etc.) will appear only at `FINE` level: + ``` + FINE: Conscrypt initialization failed with exception: java.lang.UnsatisfiedLinkError: ... + ``` -### 2. gRPC Transport (`gax-grpc` & gRPC-Java v1.83.0+) +### 3. Packet & Handshake Inspection +During a TLS 1.3 handshake with Google Front End (GFE) services, you can verify PQC negotiation using network analysis tools (such as Wireshark or OpenSSL `s_client`): +- **ClientHello**: Inspect the TLS `supported_groups` extension (Extension 10). When PQC is active, `X25519MLKEM768` (Group ID `0x4543` / `17731` or standardized IANA PQC identifier) is advertised in the ClientHello. +- **ServerHello**: The GFE endpoint selects `X25519MLKEM768` in the `key_share` extension, confirming that hybrid post-quantum key agreement was established for the connection. -For gRPC transport, PQC key exchange is built into **gRPC-Java v1.83.0+**: +--- + +## 4. HTTP/JSON Transport Implementation Details (`gax-httpjson` & `google-http-java-client`) -- **BoringSSL under the Hood**: gRPC-Java (`grpc-netty-shaded`) defaults to Netty's `netty-tcnative` (Netty's Tomcat Native JNI wrapper around **BoringSSL**). Like Conscrypt, it uses BoringSSL for C-level cryptographic execution. -- **gRPC-Java v1.83.0+ PQC Support**: Starting in version 1.83.0, `grpc-netty-shaded` has PQC hybrid key exchange (`X25519MLKEM768`) enabled by default for TLS 1.3 connections. -- **ALPN & Channel Pooling**: gRPC-Java advertises HTTP/2 (`h2`) via ALPN while offering `X25519MLKEM768` in the ClientHello. This negotiation operates seamlessly across all channels in GAX's `ChannelPoolSettings`. +PQC enablement for REST/HTTP transport relies on architecture enhancements in `google-http-java-client` and `gax-httpjson`: + +1. **`NetHttpTransport.Builder` API Enhancements**: + - `NetHttpTransport.Builder` provides `.setSecurityProvider(Provider)` and `.setSslSocketConfigurator(SslSocketConfigurator)`. + - This allows GAX to inject an explicit cryptographic `Provider` and configure raw `SSLSocket` instances created by standard Java `HttpsURLConnection`. +2. **GAX Conscrypt Registration (`HttpJsonConscryptUtils`)**: + - `InstantiatingHttpJsonChannelProvider` automatically invokes `HttpJsonConscryptUtils.configureConscryptSecurityProvider(builder)`. + - This registers Conscrypt as the socket provider and attaches a socket configurator that enables BoringSSL engine sockets (`Conscrypt.setUseEngineSocket(socket, true)`) and prefers hybrid PQC groups (`Conscrypt.setNamedGroups(socket, new String[] {"X25519MLKEM768", ...})`). +3. **TLS 1.3 Handshake Negotiation**: + - When HTTP connections are established, Conscrypt advertises `X25519MLKEM768` to Google Cloud endpoints, establishing a quantum-resistant TLS 1.3 channel. ``` +-------------------------------------------------------------------+ -| GAPIC gRPC Client Request | +| GAPIC HTTP/JSON Client Request | +-------------------------------------------------------------------+ | - gRPC-Java v1.83.0+ Netty Channel Builder - | - Is Netty-tcnative / Conscrypt JNI Available? + Is Conscrypt JNI Available on Platform? | +----------------+----------------+ | | [ YES ] [ NO ] | | v v - Netty SSLContext uses BoringSSL/Conscrypt Netty uses Standard JDK JSSE - Offers X25519MLKEM768 (PQC) Offers Classical TLS (X25519) + google-http-client uses Conscrypt Falls back to JDK JSSE + Offers X25519MLKEM768 (PQC Hybrid) Offers Classical X25519 ``` --- -## Conscrypt Capabilities & Supported Algorithms +## 5. Conscrypt Capabilities & Supported Algorithms Conscrypt provides high-performance TLS and cryptographic operations by wrapping BoringSSL via JNI native libraries. > [!NOTE] -> For a full, up-to-date listing of named groups and capabilities supported across Conscrypt versions, refer to the official [Conscrypt Capabilities Documentation](https://github.com/google/conscrypt/blob/2.6.0/CAPABILITIES.md#supported-named-groups). +> For a full listing of named groups and capabilities supported across Conscrypt versions, refer to the official [Conscrypt Capabilities Documentation](https://github.com/google/conscrypt/blob/2.6.0/CAPABILITIES.md#supported-named-groups). ### Supported PQC & Hybrid Key Exchange Groups -Conscrypt supports several post-quantum and hybrid named groups for TLS 1.3 key exchange: - | Named Group Identifier | Description | Status in Conscrypt | | :--- | :--- | :--- | -| `X25519MLKEM768` | Primary hybrid group combining X25519 ECDH with NIST FIPS 203 ML-KEM-768. | Recommended / Offered by Default | -| `SecP256r1MLKEM768` | Hybrid group combining NIST P-256 (secp256r1) with ML-KEM-768. | Supported | -| `X25519Kyber768Draft00` | Pre-standardization draft hybrid group combining X25519 with Kyber-768. | Legacy / Supported for backward compatibility | -| `MLKEM1024` | Standalone high-security post-quantum key encapsulation mechanism. | Supported | +| **`X25519MLKEM768`** | Primary hybrid group combining X25519 ECDH with NIST FIPS 203 ML-KEM-768. | Recommended / Offered by Default | +| **`SecP256r1MLKEM768`** | Hybrid group combining NIST P-256 (`secp256r1`) with ML-KEM-768. | Supported | +| **`X25519Kyber768Draft00`** | Pre-standardization draft hybrid group combining X25519 with Kyber-768. | Legacy / Backward compatible | +| **`MLKEM1024`** | Standalone high-security post-quantum key encapsulation mechanism. | Supported | ### Supported Classical (Non-PQC) Groups -For environments or server endpoints where PQC key exchange is disabled or unsupported, Conscrypt falls back to classical named groups: - +For environments or endpoints where PQC key exchange is disabled or unsupported, Conscrypt falls back to standard classical named groups: - `X25519` (Curve25519 ECDH) - `SecP256r1` (NIST P-256 ECDH) - `SecP384r1` (NIST P-384 ECDH) - `SecP521r1` (NIST P-521 ECDH) -### What to Do If a Required Algorithm Is Unsupported +--- -If your application or security policy mandates a specific PQC algorithm variant that Conscrypt does not support (or if you must use a custom security module): -1. Configure a custom Security Provider (such as Bouncy Castle) as described in [Alternatives & How to Configure Them](#alternatives--how-to-configure-them). -2. Explicitly override the transport builder's channel provider or `SSLContext`. +## 6. Platform Compatibility & Native Library Limitations ---- +Because Conscrypt relies on C native shared libraries (`conscrypt-openjdk-uber`) loaded via Java Native Interface (JNI), PQC support depends on OS platform compatibility: + +1. **System & GLIBC Compatibility Constraints**: + - **Linux glibc Versioning**: Conscrypt native C binaries require compatible C runtime (`glibc`) versions (such as `GLIBC_2.35+`). Older Linux distributions or lightweight images (such as Alpine Linux using `musl` libc) will fail to load native libraries (`UnsatisfiedLinkError`). + - **Restricted Filesystems**: Operating systems that mount `/tmp` with `noexec`, strict container security profiles, or environments blocking JNI library extraction will prevent Conscrypt from initializing. -## Limitations of Native PQC Engines (Conscrypt & Netty-tcnative) +2. **Graceful Fallback Behavior**: + - Whenever native library loading fails, `gax-httpjson` catches the error, logs a concise warning at `Level.WARNING`, and safely falls back to standard JDK JSSE: + ``` + WARNING: Conscrypt native libraries not available. Falling back to JDK TLS. + ``` + - Your application will continue running normally using classical TLS provided by the JDK. -Both HTTP/JSON (via Conscrypt) and gRPC (via Netty-tcnative / BoringSSL) rely on C native shared libraries loaded via JNI. Consequently, **both transports share the same platform limitations**: +--- -1. **JNI Native Binary Dependencies**: - - Conscrypt uses `conscrypt-openjdk-uber`, which extracts `.so`, `.dylib`, or `.dll` native libraries into temporary directories at runtime. - - `grpc-netty-shaded` embeds pre-compiled `netty-tcnative` BoringSSL native libraries into its JAR. +## 7. Mutual TLS (mTLS) Support with PQC -2. **System & GLIBC Compatibility Constraints**: - - **Linux glibc Versioning**: Native C binaries require compatible C runtime (`glibc`) versions (e.g. `GLIBC_2.35+`). Older Linux enterprise distributions or base images with older `glibc` releases will fail to load native libraries (`UnsatisfiedLinkError`). - - **Restricted / Read-Only Filesystems**: Environments that mount `/tmp` with `noexec`, strict container runtimes, Android/GraalVM native images without JNI support, or security managers blocking C library loading will prevent native PQC initialization. +Google Cloud HTTP/JSON client libraries support **Mutual TLS (mTLS)** client certificate authentication alongside PQC hybrid key exchange. -3. **Graceful Fallback Behavior**: - When native C libraries fail to load for either transport, the client libraries safely fall back to standard JDK JSSE: - ``` - WARNING: Conscrypt native libraries not available. Falling back to JDK TLS. - java.lang.UnsatisfiedLinkError: ... libc.so.6: version `GLIBC_2.35' not found - ``` - The client will continue operating using classical TLS provided by the JDK. +- When mTLS is enabled (via `GOOGLE_API_USE_CLIENT_CERTIFICATE="true"` in the system environment or via an explicit `MtlsProvider`), `InstantiatingHttpJsonChannelProvider` configures client certificate keystores and server trust stores. +- The trust manager factory is automatically initialized using the PKIX trust manager (`TrustManagerFactory.getInstance("PKIX", conscryptProvider)`), ensuring seamless compatibility with Conscrypt's TLS 1.3 engine and PQC named groups. --- -## Alternatives & How to Configure Them +## 8. Custom & Alternative Configurations -If you need to disable PQC, force classical key exchange, or use a custom TLS engine, you can configure alternative transport providers for both gRPC and HTTP/JSON. +If you need to disable PQC, force classical key exchange, bypass Conscrypt, or use a third-party security provider, you can customize the transport provider. -### Alternative 1: Forcing Classical (Non-PQC) Key Exchange (HTTP/JSON) +### Alternative 1: Forcing Classical (Non-PQC) Key Exchange -To explicitly force classical key exchange (such as `X25519` or `SecP256r1`) for HTTP/JSON clients: +To explicitly restrict key exchange to classical `X25519` (disabling post-quantum hybrid groups): ```java import com.google.api.client.http.javanet.NetHttpTransport; import com.google.api.gax.httpjson.HttpJsonConscryptUtils; import com.google.api.gax.httpjson.InstantiatingHttpJsonChannelProvider; +import com.google.cloud.secretmanager.v1.SecretManagerServiceClient; import com.google.cloud.secretmanager.v1.SecretManagerServiceSettings; import org.conscrypt.Conscrypt; @@ -159,13 +175,13 @@ NetHttpTransport transport = // Explicitly offer only classical X25519 (disabling PQC hybrid groups) Conscrypt.setNamedGroups(socket, new String[] {"X25519"}); } catch (Exception e) { - // Handle or log socket configuration failure + // Ignore or log socket configuration failure } } }) .build(); -// Step 2: Build transport channel provider using custom transport +// Step 2: Build transport channel provider using the custom transport InstantiatingHttpJsonChannelProvider transportChannelProvider = SecretManagerServiceSettings.defaultHttpJsonTransportProviderBuilder() .setHttpTransport(transport) @@ -176,33 +192,15 @@ SecretManagerServiceSettings settings = SecretManagerServiceSettings.newHttpJsonBuilder() .setTransportChannelProvider(transportChannelProvider) .build(); -``` - -### Alternative 2: Forcing Classical (Non-PQC) Key Exchange (gRPC) - -For gRPC clients, you can configure `InstantiatingGrpcChannelProvider` with custom Netty SSL context options to restrict key exchange groups: - -```java -import com.google.api.gax.grpc.InstantiatingGrpcChannelProvider; -import com.google.cloud.secretmanager.v1.SecretManagerServiceSettings; -InstantiatingGrpcChannelProvider transportChannelProvider = - SecretManagerServiceSettings.defaultGrpcTransportProviderBuilder() - .setChannelConfigurator( - managedChannelBuilder -> { - // Custom channel configuration to override SSL/TLS settings - }) - .build(); - -SecretManagerServiceSettings settings = - SecretManagerServiceSettings.newBuilder() - .setTransportChannelProvider(transportChannelProvider) - .build(); +try (SecretManagerServiceClient client = SecretManagerServiceClient.create(settings)) { + // Client communicates using classical X25519 TLS 1.3 +} ``` -### Alternative 3: Bypassing Conscrypt to Use Standard JDK JSSE (HTTP/JSON) +### Alternative 2: Bypassing Conscrypt to Use Standard JDK JSSE -If you prefer to bypass Conscrypt completely and use the standard JDK JSSE provider: +To bypass Conscrypt completely and use the standard JDK JSSE TLS provider: ```java import com.google.api.client.http.javanet.NetHttpTransport; @@ -210,7 +208,7 @@ import com.google.api.gax.httpjson.InstantiatingHttpJsonChannelProvider; import com.google.cloud.secretmanager.v1.SecretManagerServiceClient; import com.google.cloud.secretmanager.v1.SecretManagerServiceSettings; -// Build standard NetHttpTransport without Conscrypt configuration +// Build a standard NetHttpTransport without GAX Conscrypt configuration NetHttpTransport standardTransport = new NetHttpTransport.Builder().build(); InstantiatingHttpJsonChannelProvider transportProvider = @@ -224,30 +222,35 @@ SecretManagerServiceSettings settings = .build(); try (SecretManagerServiceClient client = SecretManagerServiceClient.create(settings)) { - // Client uses standard JDK JSSE TLS + // Client communicates using standard JDK JSSE TLS } ``` -### Alternative 4: Configuring Custom Security Providers (e.g., Bouncy Castle) +### Alternative 3: Configuring Custom Security Providers (Locally Scoped to `NetHttpTransport`) -To use a third-party Security Provider (such as Bouncy Castle) for TLS: +If your application requires a custom cryptographic provider (such as Bouncy Castle), you can configure it **locally on the specific `NetHttpTransport` instance without modifying the global JVM `Security` provider table**: ```java import com.google.api.client.http.javanet.NetHttpTransport; import com.google.api.gax.httpjson.InstantiatingHttpJsonChannelProvider; +import com.google.cloud.secretmanager.v1.SecretManagerServiceClient; +import com.google.cloud.secretmanager.v1.SecretManagerServiceSettings; +import java.security.KeyStore; import java.security.Provider; -import java.security.Security; import javax.net.ssl.SSLContext; +import javax.net.ssl.TrustManagerFactory; -// Register custom provider +// Step 1: Instantiate custom security provider (without calling Security.addProvider globally) Provider customProvider = new org.bouncycastle.jce.provider.BouncyCastleProvider(); -Security.addProvider(customProvider); -// Initialize custom SSLContext +// Step 2: Initialize TrustManagerFactory and SSLContext locally using customProvider +TrustManagerFactory tmf = TrustManagerFactory.getInstance("PKIX", customProvider); +tmf.init((KeyStore) null); // Loads standard JDK cacerts trust store + SSLContext sslContext = SSLContext.getInstance("TLS", customProvider); -sslContext.init(null, null, null); +sslContext.init(null, tmf.getTrustManagers(), null); -// Configure transport builder with custom SSLSocketFactory +// Step 3: Configure NetHttpTransport to use the locally scoped SSLSocketFactory NetHttpTransport customTransport = new NetHttpTransport.Builder() .setSslSocketFactory(sslContext.getSocketFactory()) @@ -257,25 +260,26 @@ InstantiatingHttpJsonChannelProvider transportProvider = SecretManagerServiceSettings.defaultHttpJsonTransportProviderBuilder() .setHttpTransport(customTransport) .build(); -``` - ---- -## Future Roadmap: JDK 27+ and Native JDK PQC Support +SecretManagerServiceSettings settings = + SecretManagerServiceSettings.newHttpJsonBuilder() + .setTransportChannelProvider(transportProvider) + .build(); -As quantum-resistant cryptography standards mature, Java is incorporating native PQC support directly into standard OpenJDK distributions. +try (SecretManagerServiceClient client = SecretManagerServiceClient.create(settings)) { + // Client communicates using Bouncy Castle TLS scoped strictly to this transport +} +``` -> [!IMPORTANT] -> **JDK 27+ Native PQC Support**: -> Starting with JDK 27, standard JDK Security Providers (SunJSSE) will include native support for NIST post-quantum key encapsulation standards (JEP / ML-KEM). +--- -### What JDK 27+ Means for Java SDK Users +## 9. Future Roadmap -1. **Zero-Dependency Native PQC**: - On JDK 27 and future Java LTS releases, applications running standard OpenJDK will automatically negotiate PQC key exchange natively out-of-the-box—even without Conscrypt or JNI native dependencies. +### gRPC Client Library Support +Out-of-the-box PQC support for gRPC client libraries (`gax-grpc`) is under active development and will be detailed in an upcoming release. -2. **Forward Compatibility**: - The GAX transport layer (`gax-grpc` and `gax-httpjson`) is designed so that when running on JDK 27+: - - If native BoringSSL libraries (Conscrypt / Netty-tcnative) are present, they continue to offer hardware-accelerated PQC key exchange. - - If native libraries are absent or disabled, the JDK's standard JSSE provider natively offers ML-KEM PQC key exchange. - - Applications do not need to make any code or configuration changes when upgrading to JDK 27+. +### JDK 27+ Native JDK PQC Support +As quantum-resistant cryptography standards mature, OpenJDK is incorporating native PQC support directly into standard Java releases: +- Starting with **JDK 27**, standard JDK Security Providers (`SunJSSE`) will include native support for NIST post-quantum key encapsulation standards (JEP / ML-KEM). +- When running on JDK 27+, Java applications will automatically negotiate ML-KEM PQC key exchange out-of-the-box—without requiring Conscrypt or JNI native dependencies. +- No code or configuration changes will be required in Google Cloud Java client libraries when upgrading to JDK 27+. From 12cd1a6bd16127000e90384ada22208ccc10e2b6 Mon Sep 17 00:00:00 2001 From: Lawrence Qiu Date: Thu, 30 Jul 2026 16:58:15 +0000 Subject: [PATCH 03/25] docs: remove mTLS/gRPC references, add default algorithms and fallback flow, and format JDK 27 as addendum --- docs/post_quantum_cryptography_guide.md | 65 ++++++++++++++----------- 1 file changed, 37 insertions(+), 28 deletions(-) diff --git a/docs/post_quantum_cryptography_guide.md b/docs/post_quantum_cryptography_guide.md index 3c6404806d0c..4c3b36db468b 100644 --- a/docs/post_quantum_cryptography_guide.md +++ b/docs/post_quantum_cryptography_guide.md @@ -23,9 +23,6 @@ To mitigate this threat immediately without sacrificing present-day security, Go PQC support is **enabled by default** for **HTTP/JSON** (REST) transport in Google Cloud Java client libraries (`gax-httpjson`) whenever native Conscrypt / BoringSSL libraries are supported on the runtime environment. -> [!NOTE] -> This guide currently focuses on **HTTP/JSON (`gax-httpjson`)** client libraries. Support for gRPC (`gax-grpc`) is under active development and will be detailed in an upcoming release. - ### Transport Support Summary | Transport | GAX Module | Underlying HTTP Client | Cryptographic Engine | PQC Activation | @@ -75,9 +72,30 @@ PQC enablement for REST/HTTP transport relies on architecture enhancements in `g - This allows GAX to inject an explicit cryptographic `Provider` and configure raw `SSLSocket` instances created by standard Java `HttpsURLConnection`. 2. **GAX Conscrypt Registration (`HttpJsonConscryptUtils`)**: - `InstantiatingHttpJsonChannelProvider` automatically invokes `HttpJsonConscryptUtils.configureConscryptSecurityProvider(builder)`. - - This registers Conscrypt as the socket provider and attaches a socket configurator that enables BoringSSL engine sockets (`Conscrypt.setUseEngineSocket(socket, true)`) and prefers hybrid PQC groups (`Conscrypt.setNamedGroups(socket, new String[] {"X25519MLKEM768", ...})`). -3. **TLS 1.3 Handshake Negotiation**: - - When HTTP connections are established, Conscrypt advertises `X25519MLKEM768` to Google Cloud endpoints, establishing a quantum-resistant TLS 1.3 channel. + - This registers Conscrypt as the socket provider and attaches a socket configurator that enables BoringSSL engine sockets (`Conscrypt.setUseEngineSocket(socket, true)`). + +### Default Algorithms & Multi-Algorithm Fallback Mechanism + +To maximize compatibility across diverse server endpoints and connect to as many algorithms as possible, `gax-httpjson` configures Conscrypt to advertise a comprehensive ordered list of **post-quantum hybrid groups, standalone PQC groups, and standard classical ECDH groups** by default: + +- **PQC / Hybrid Groups Offered by Default**: + - `X25519MLKEM768` + - `SecP256r1MLKEM768` + - `X25519Kyber768Draft00` + - `MLKEM1024` +- **Classical ECDH Groups Offered by Default**: + - `X25519` + - `SecP256r1` + - `SecP384r1` + - `SecP521r1` + +#### Two-Tier Fallback Architecture for Maximum Interoperability +1. **TLS 1.3 Handshake Negotiation (Algorithm Fallback)**: + - When a TLS 1.3 handshake begins, the client includes all default PQC and classical groups in its `supported_groups` ClientHello extension. + - **PQC-Enabled Endpoints**: If the server endpoint supports PQC (such as Google Cloud Front End endpoints), it selects `X25519MLKEM768` (or another mutually supported hybrid group), establishing an authenticated post-quantum session. + - **Non-PQC Endpoints**: If the server endpoint does not support post-quantum algorithms, it ignores the unknown PQC group identifiers and gracefully selects the highest-preference classical group (such as `X25519` or `SecP256r1`) without dropping the connection. +2. **Runtime Platform Fallback (Provider Fallback)**: + - If the runtime platform itself cannot load native Conscrypt libraries, `gax-httpjson` safely catches the error, logs a concise warning, and falls back to standard JDK JSSE (`SunJSSE`), ensuring network connectivity is never broken. ``` +-------------------------------------------------------------------+ @@ -92,7 +110,11 @@ PQC enablement for REST/HTTP transport relies on architecture enhancements in `g | | v v google-http-client uses Conscrypt Falls back to JDK JSSE - Offers X25519MLKEM768 (PQC Hybrid) Offers Classical X25519 + Offers PQC Hybrid + Classical Groups Offers Standard JDK Classical Groups + - Negotiates X25519MLKEM768 if server - Negotiates Classical X25519 / + supports PQC SecP256r1 via JDK TLS + - Automatically falls back to classical + X25519 if server lacks PQC ``` --- @@ -109,9 +131,9 @@ Conscrypt provides high-performance TLS and cryptographic operations by wrapping | Named Group Identifier | Description | Status in Conscrypt | | :--- | :--- | :--- | | **`X25519MLKEM768`** | Primary hybrid group combining X25519 ECDH with NIST FIPS 203 ML-KEM-768. | Recommended / Offered by Default | -| **`SecP256r1MLKEM768`** | Hybrid group combining NIST P-256 (`secp256r1`) with ML-KEM-768. | Supported | -| **`X25519Kyber768Draft00`** | Pre-standardization draft hybrid group combining X25519 with Kyber-768. | Legacy / Backward compatible | -| **`MLKEM1024`** | Standalone high-security post-quantum key encapsulation mechanism. | Supported | +| **`SecP256r1MLKEM768`** | Hybrid group combining NIST P-256 (`secp256r1`) with ML-KEM-768. | Supported / Offered by Default | +| **`X25519Kyber768Draft00`** | Pre-standardization draft hybrid group combining X25519 with Kyber-768. | Legacy / Offered for backward compatibility | +| **`MLKEM1024`** | Standalone high-security post-quantum key encapsulation mechanism. | Supported / Offered by Default | ### Supported Classical (Non-PQC) Groups @@ -140,16 +162,7 @@ Because Conscrypt relies on C native shared libraries (`conscrypt-openjdk-uber`) --- -## 7. Mutual TLS (mTLS) Support with PQC - -Google Cloud HTTP/JSON client libraries support **Mutual TLS (mTLS)** client certificate authentication alongside PQC hybrid key exchange. - -- When mTLS is enabled (via `GOOGLE_API_USE_CLIENT_CERTIFICATE="true"` in the system environment or via an explicit `MtlsProvider`), `InstantiatingHttpJsonChannelProvider` configures client certificate keystores and server trust stores. -- The trust manager factory is automatically initialized using the PKIX trust manager (`TrustManagerFactory.getInstance("PKIX", conscryptProvider)`), ensuring seamless compatibility with Conscrypt's TLS 1.3 engine and PQC named groups. - ---- - -## 8. Custom & Alternative Configurations +## 7. Custom & Alternative Configurations If you need to disable PQC, force classical key exchange, bypass Conscrypt, or use a third-party security provider, you can customize the transport provider. @@ -273,13 +286,9 @@ try (SecretManagerServiceClient client = SecretManagerServiceClient.create(setti --- -## 9. Future Roadmap - -### gRPC Client Library Support -Out-of-the-box PQC support for gRPC client libraries (`gax-grpc`) is under active development and will be detailed in an upcoming release. +## 8. Addendum: JDK 27+ and Native OpenJDK PQC Support -### JDK 27+ Native JDK PQC Support As quantum-resistant cryptography standards mature, OpenJDK is incorporating native PQC support directly into standard Java releases: -- Starting with **JDK 27**, standard JDK Security Providers (`SunJSSE`) will include native support for NIST post-quantum key encapsulation standards (JEP / ML-KEM). -- When running on JDK 27+, Java applications will automatically negotiate ML-KEM PQC key exchange out-of-the-box—without requiring Conscrypt or JNI native dependencies. -- No code or configuration changes will be required in Google Cloud Java client libraries when upgrading to JDK 27+. +- Starting with **JDK 27**, standard JDK Security Providers (`SunJSSE`) include native support for NIST post-quantum key encapsulation standards (JEP / ML-KEM). +- When running on JDK 27 or later, Java applications automatically negotiate ML-KEM PQC key exchange out-of-the-box—without requiring Conscrypt or JNI native dependencies. +- No code or configuration changes are required in Google Cloud Java client libraries when running on JDK 27+. From 613008854a256c2b20a06a0f256310a9287912fe Mon Sep 17 00:00:00 2001 From: Lawrence Qiu Date: Thu, 30 Jul 2026 17:24:15 +0000 Subject: [PATCH 04/25] docs: refine HTTP/JSON PQC guide with exact versions, concise intro, and custom provider builder examples --- docs/post_quantum_cryptography_guide.md | 133 +++++++++--------------- 1 file changed, 50 insertions(+), 83 deletions(-) diff --git a/docs/post_quantum_cryptography_guide.md b/docs/post_quantum_cryptography_guide.md index 4c3b36db468b..66e63f9be25e 100644 --- a/docs/post_quantum_cryptography_guide.md +++ b/docs/post_quantum_cryptography_guide.md @@ -2,20 +2,11 @@ ## 1. The Quantum Threat & Why PQC is Critical -### The Problem: Store-Now, Decrypt-Later (SNDL) Attacks -Traditional Transport Layer Security (TLS) relies on classical asymmetric public-key cryptography—such as RSA, Elliptic Curve Diffie-Hellman (`ECDH`), and `X25519`—to establish secure encrypted connections. While these classical algorithms are computationally secure against present-day classical computers, they are vulnerable to **Shor's algorithm** running on a cryptographically relevant quantum computer (CRQC). +Traditional TLS public-key encryption (such as RSA and ECDH) is vulnerable to future decryption by quantum computers. -An adversary does not need to wait for a quantum computer to be built before attacking classical encryption: -- **Harvest Now, Decrypt Later**: Threat actors can intercept and store encrypted TLS network traffic today. -- **Future Decryption**: Once a sufficiently powerful quantum computer becomes operational, adversaries will be able to retroactively break the classical Diffie-Hellman key exchange and decrypt long-lived confidential data collected years earlier. - -### The Consequence of Not Using PQC -Without Post-Quantum Cryptography (PQC), any sensitive data transmitted across networks today—including authentication credentials, financial records, proprietary algorithms, and customer data—remains vulnerable to retroactive decryption in the future. - -### The Solution: Hybrid PQC Key Exchange -To mitigate this threat immediately without sacrificing present-day security, Google Cloud HTTP/JSON Java client libraries support **Hybrid PQC Key Exchange**. -- A hybrid key exchange combines a classical ECDH algorithm (such as `X25519`) with a NIST-standardized Post-Quantum Key Encapsulation Mechanism (KEM), such as **ML-KEM-768** (FIPS 203), negotiated as `X25519MLKEM768`. -- This ensures that your communications remain at least as secure as standard classical TLS 1.3 against present-day attacks, while simultaneously protecting encrypted sessions against future quantum decryption. +- **The Risk ("Store-Now, Decrypt-Later")**: Adversaries can intercept and store encrypted network traffic today with the intent to decrypt it once cryptographically relevant quantum computers become available. +- **The Consequence**: Without Post-Quantum Cryptography (PQC), sensitive data transmitted today—such as credentials, financial records, and customer data—is at risk of retroactive decryption in the future. +- **The Solution (Hybrid PQC)**: Google Cloud HTTP/JSON Java client libraries support **Hybrid PQC Key Exchange** (such as `X25519MLKEM768`), combining a classical ECDH algorithm (like `X25519`) with a NIST-standardized Post-Quantum Key Encapsulation Mechanism (like `ML-KEM-768`, FIPS 203). This protects encrypted traffic against both present-day and future quantum threats without sacrificing existing security. --- @@ -31,9 +22,9 @@ PQC support is **enabled by default** for **HTTP/JSON** (REST) transport in Goog --- -## 3. How to Verify That You Are Using PQC +## 3. How to Verify That You Are Using PQC in Google Cloud Java Client Libraries -You can verify that your HTTP/JSON client library is actively negotiating Post-Quantum Cryptography through operational logs, debug logging, or network traffic analysis. +You can verify that your Google Cloud HTTP/JSON Java client library is actively negotiating Post-Quantum Cryptography through operational logs, debug logging, or network traffic analysis. ### 1. Check Operational Log Messages When Conscrypt initializes successfully and configures PQC named groups, **no warning logs are emitted**. @@ -57,45 +48,34 @@ To inspect the exact initialization status and any underlying native library loa ``` ### 3. Packet & Handshake Inspection -During a TLS 1.3 handshake with Google Front End (GFE) services, you can verify PQC negotiation using network analysis tools (such as Wireshark or OpenSSL `s_client`): +During a TLS 1.3 handshake with Google Front End (GFE) services, you can verify PQC negotiation by inspecting the handshake packets: - **ClientHello**: Inspect the TLS `supported_groups` extension (Extension 10). When PQC is active, `X25519MLKEM768` (Group ID `0x4543` / `17731` or standardized IANA PQC identifier) is advertised in the ClientHello. - **ServerHello**: The GFE endpoint selects `X25519MLKEM768` in the `key_share` extension, confirming that hybrid post-quantum key agreement was established for the connection. --- -## 4. HTTP/JSON Transport Implementation Details (`gax-httpjson` & `google-http-java-client`) +## 4. Architecture & Minimum Required Versions -PQC enablement for REST/HTTP transport relies on architecture enhancements in `google-http-java-client` and `gax-httpjson`: +PQC enablement for HTTP/JSON transport requires compatible versions of `gax-httpjson` and `google-http-client`: -1. **`NetHttpTransport.Builder` API Enhancements**: - - `NetHttpTransport.Builder` provides `.setSecurityProvider(Provider)` and `.setSslSocketConfigurator(SslSocketConfigurator)`. - - This allows GAX to inject an explicit cryptographic `Provider` and configure raw `SSLSocket` instances created by standard Java `HttpsURLConnection`. -2. **GAX Conscrypt Registration (`HttpJsonConscryptUtils`)**: - - `InstantiatingHttpJsonChannelProvider` automatically invokes `HttpJsonConscryptUtils.configureConscryptSecurityProvider(builder)`. - - This registers Conscrypt as the socket provider and attaches a socket configurator that enables BoringSSL engine sockets (`Conscrypt.setUseEngineSocket(socket, true)`). +> [!TIP] +> **Recommended BOM**: +> We recommend importing Google Cloud Java libraries using **`libraries-bom` version `26.86.0+`**, which automatically manages compatible dependency versions across all Google Cloud client libraries, GAX, and the Google HTTP Client. -### Default Algorithms & Multi-Algorithm Fallback Mechanism +### Minimum Required Versions + +| Library | Minimum Required Version | Role | +| :--- | :--- | :--- | +| **`gax-httpjson`** | `2.83.0+` | Automatically registers Conscrypt as the TLS security provider and configures PQC named groups. | +| **`google-http-client`** | `2.2.0+` | Provides security provider registration and socket configurators on `NetHttpTransport.Builder`. | -To maximize compatibility across diverse server endpoints and connect to as many algorithms as possible, `gax-httpjson` configures Conscrypt to advertise a comprehensive ordered list of **post-quantum hybrid groups, standalone PQC groups, and standard classical ECDH groups** by default: +### How GAX and Google Cloud Servers Work Together -- **PQC / Hybrid Groups Offered by Default**: - - `X25519MLKEM768` - - `SecP256r1MLKEM768` - - `X25519Kyber768Draft00` - - `MLKEM1024` -- **Classical ECDH Groups Offered by Default**: - - `X25519` - - `SecP256r1` - - `SecP384r1` - - `SecP521r1` +When you construct a Google Cloud HTTP/JSON service client, `gax-httpjson` automatically registers Conscrypt as the underlying cryptographic provider on the Google HTTP Client (`NetHttpTransport`). -#### Two-Tier Fallback Architecture for Maximum Interoperability -1. **TLS 1.3 Handshake Negotiation (Algorithm Fallback)**: - - When a TLS 1.3 handshake begins, the client includes all default PQC and classical groups in its `supported_groups` ClientHello extension. - - **PQC-Enabled Endpoints**: If the server endpoint supports PQC (such as Google Cloud Front End endpoints), it selects `X25519MLKEM768` (or another mutually supported hybrid group), establishing an authenticated post-quantum session. - - **Non-PQC Endpoints**: If the server endpoint does not support post-quantum algorithms, it ignores the unknown PQC group identifiers and gracefully selects the highest-preference classical group (such as `X25519` or `SecP256r1`) without dropping the connection. -2. **Runtime Platform Fallback (Provider Fallback)**: - - If the runtime platform itself cannot load native Conscrypt libraries, `gax-httpjson` safely catches the error, logs a concise warning, and falls back to standard JDK JSSE (`SunJSSE`), ensuring network connectivity is never broken. +- **Negotiation with Google Cloud Servers**: During the TLS 1.3 handshake, `gax-httpjson` advertises Post-Quantum Cryptography named groups (`X25519MLKEM768`, etc.) in preference order alongside classical TLS groups. When connecting to Google Cloud Front End (GFE) endpoints, the server evaluates the client's list from top to bottom and **selects the first compatible algorithm from the list that it also supports**—in this case, `X25519MLKEM768` (#1 preference), establishing an authenticated post-quantum session. +- **Transparent Endpoint Compatibility**: When connecting to endpoints that do not yet support PQC, the server skips the unknown post-quantum identifiers at the top of the list and selects **the first compatible algorithm from the client's list that it recognizes** (such as classical `X25519`), transparently negotiating standard TLS without dropping the connection. +- **Platform Runtime Fallback**: If the runtime environment cannot load native Conscrypt libraries, `gax-httpjson` catches the error, logs a concise warning, and falls back to standard JDK JSSE (`SunJSSE`), ensuring network connectivity is never broken. ``` +-------------------------------------------------------------------+ @@ -111,37 +91,29 @@ To maximize compatibility across diverse server endpoints and connect to as many v v google-http-client uses Conscrypt Falls back to JDK JSSE Offers PQC Hybrid + Classical Groups Offers Standard JDK Classical Groups - - Negotiates X25519MLKEM768 if server - Negotiates Classical X25519 / - supports PQC SecP256r1 via JDK TLS - - Automatically falls back to classical - X25519 if server lacks PQC + - Server selects 1st compatible group - Server negotiates Classical + - Negotiates X25519MLKEM768 on - Negotiates Classical X25519 / + Google Cloud Front End (GFE) secp256r1 via JDK TLS + - Automatically falls back to X25519 + on older non-PQC servers ``` --- -## 5. Conscrypt Capabilities & Supported Algorithms +## 5. Supported Key Exchange Groups -Conscrypt provides high-performance TLS and cryptographic operations by wrapping BoringSSL via JNI native libraries. +Google Cloud HTTP/JSON client libraries configure Conscrypt to advertise the following named groups in preference order: -> [!NOTE] -> For a full listing of named groups and capabilities supported across Conscrypt versions, refer to the official [Conscrypt Capabilities Documentation](https://github.com/google/conscrypt/blob/2.6.0/CAPABILITIES.md#supported-named-groups). - -### Supported PQC & Hybrid Key Exchange Groups - -| Named Group Identifier | Description | Status in Conscrypt | -| :--- | :--- | :--- | -| **`X25519MLKEM768`** | Primary hybrid group combining X25519 ECDH with NIST FIPS 203 ML-KEM-768. | Recommended / Offered by Default | -| **`SecP256r1MLKEM768`** | Hybrid group combining NIST P-256 (`secp256r1`) with ML-KEM-768. | Supported / Offered by Default | -| **`X25519Kyber768Draft00`** | Pre-standardization draft hybrid group combining X25519 with Kyber-768. | Legacy / Offered for backward compatibility | -| **`MLKEM1024`** | Standalone high-security post-quantum key encapsulation mechanism. | Supported / Offered by Default | +1. `X25519MLKEM768` +2. `SecP256r1MLKEM768` +3. `MLKEM1024` +4. `MLKEM768` +5. `X25519Kyber768Draft00` *(deprecated draft group kept for backward compatibility)* +6. `X25519` +7. `secp256r1` +8. `secp384r1` -### Supported Classical (Non-PQC) Groups - -For environments or endpoints where PQC key exchange is disabled or unsupported, Conscrypt falls back to standard classical named groups: -- `X25519` (Curve25519 ECDH) -- `SecP256r1` (NIST P-256 ECDH) -- `SecP384r1` (NIST P-384 ECDH) -- `SecP521r1` (NIST P-521 ECDH) +For additional details on Conscrypt's cryptographic algorithms and capabilities, refer to the official [Conscrypt CAPABILITIES.md](https://github.com/google/conscrypt/blob/2.6.0/CAPABILITIES.md#supported-named-groups). --- @@ -239,36 +211,31 @@ try (SecretManagerServiceClient client = SecretManagerServiceClient.create(setti } ``` -### Alternative 3: Configuring Custom Security Providers (Locally Scoped to `NetHttpTransport`) +### Alternative 3: Configuring Custom Security Providers -If your application requires a custom cryptographic provider (such as Bouncy Castle), you can configure it **locally on the specific `NetHttpTransport` instance without modifying the global JVM `Security` provider table**: +If your application requires a custom cryptographic provider (such as Bouncy Castle), you can configure it on a specific `NetHttpTransport` instance using `NetHttpTransport.Builder.setSecurityProvider(...)` and `.setSslSocketConfigurator(...)`: ```java import com.google.api.client.http.javanet.NetHttpTransport; import com.google.api.gax.httpjson.InstantiatingHttpJsonChannelProvider; import com.google.cloud.secretmanager.v1.SecretManagerServiceClient; import com.google.cloud.secretmanager.v1.SecretManagerServiceSettings; -import java.security.KeyStore; import java.security.Provider; -import javax.net.ssl.SSLContext; -import javax.net.ssl.TrustManagerFactory; -// Step 1: Instantiate custom security provider (without calling Security.addProvider globally) +// Step 1: Instantiate custom security provider Provider customProvider = new org.bouncycastle.jce.provider.BouncyCastleProvider(); -// Step 2: Initialize TrustManagerFactory and SSLContext locally using customProvider -TrustManagerFactory tmf = TrustManagerFactory.getInstance("PKIX", customProvider); -tmf.init((KeyStore) null); // Loads standard JDK cacerts trust store - -SSLContext sslContext = SSLContext.getInstance("TLS", customProvider); -sslContext.init(null, tmf.getTrustManagers(), null); - -// Step 3: Configure NetHttpTransport to use the locally scoped SSLSocketFactory +// Step 2: Configure NetHttpTransport with custom security provider and SSLSocketConfigurator NetHttpTransport customTransport = new NetHttpTransport.Builder() - .setSslSocketFactory(sslContext.getSocketFactory()) + .setSecurityProvider(customProvider) + .setSslSocketConfigurator( + socket -> { + // Configure custom SSLSocket options (e.g., cipher suites, protocols, or named groups) + }) .build(); +// Step 3: Build transport provider and service client InstantiatingHttpJsonChannelProvider transportProvider = SecretManagerServiceSettings.defaultHttpJsonTransportProviderBuilder() .setHttpTransport(customTransport) @@ -280,7 +247,7 @@ SecretManagerServiceSettings settings = .build(); try (SecretManagerServiceClient client = SecretManagerServiceClient.create(settings)) { - // Client communicates using Bouncy Castle TLS scoped strictly to this transport + // Client communicates using custom security provider scoped strictly to this transport } ``` From ea4e04e2bc35c96004605102cc0adeb9f9169dbc Mon Sep 17 00:00:00 2001 From: Lawrence Qiu Date: Thu, 30 Jul 2026 17:46:35 +0000 Subject: [PATCH 05/25] docs: reorganize HTTP/JSON PQC guide with versions first and clarify JDK 27 addendum scope --- docs/post_quantum_cryptography_guide.md | 115 +++++++++++------------- 1 file changed, 51 insertions(+), 64 deletions(-) diff --git a/docs/post_quantum_cryptography_guide.md b/docs/post_quantum_cryptography_guide.md index 66e63f9be25e..7f607e683cc1 100644 --- a/docs/post_quantum_cryptography_guide.md +++ b/docs/post_quantum_cryptography_guide.md @@ -10,72 +10,39 @@ Traditional TLS public-key encryption (such as RSA and ECDH) is vulnerable to fu --- -## 2. Overview & Default Behavior in `gax-httpjson` +## 2. HTTP/JSON (REST) Client Library Support -PQC support is **enabled by default** for **HTTP/JSON** (REST) transport in Google Cloud Java client libraries (`gax-httpjson`) whenever native Conscrypt / BoringSSL libraries are supported on the runtime environment. +Post-Quantum Cryptography is **enabled by default** for **HTTP/JSON** (REST) transport in Google Cloud Java client libraries (`gax-httpjson`) whenever native Conscrypt / BoringSSL libraries are supported on the runtime environment. -### Transport Support Summary +### 2.1 Minimum Required Versions -| Transport | GAX Module | Underlying HTTP Client | Cryptographic Engine | PQC Activation | -| :--- | :--- | :--- | :--- | :--- | -| **HTTP/JSON** | `gax-httpjson` | Google HTTP Client (`NetHttpTransport`) | Conscrypt (BoringSSL JNI) | **Enabled by Default** via `google-http-java-client` security provider API | - ---- - -## 3. How to Verify That You Are Using PQC in Google Cloud Java Client Libraries - -You can verify that your Google Cloud HTTP/JSON Java client library is actively negotiating Post-Quantum Cryptography through operational logs, debug logging, or network traffic analysis. - -### 1. Check Operational Log Messages -When Conscrypt initializes successfully and configures PQC named groups, **no warning logs are emitted**. - -If your environment cannot load native Conscrypt libraries or cannot configure PQC groups, the library emits a concise, one-line warning at `Level.WARNING` and safely falls back to standard JDK TLS: -``` -WARNING: Conscrypt native libraries not available. Falling back to JDK TLS. -``` -If you **do not see this warning message** in your application logs, Conscrypt has successfully initialized and enabled PQC key exchange. - -### 2. Enable Debug Logging (`Level.FINE`) -To inspect the exact initialization status and any underlying native library loader exceptions, enable debug logging (`Level.FINE`) for `com.google.api.gax.httpjson.HttpJsonConscryptUtils`: - -- In `logging.properties`: - ```properties - com.google.api.gax.httpjson.HttpJsonConscryptUtils.level = FINE - ``` -- If an error occurs during initialization, the full exception stacktrace (`UnsatisfiedLinkError`, `LinkageError`, etc.) will appear only at `FINE` level: - ``` - FINE: Conscrypt initialization failed with exception: java.lang.UnsatisfiedLinkError: ... - ``` - -### 3. Packet & Handshake Inspection -During a TLS 1.3 handshake with Google Front End (GFE) services, you can verify PQC negotiation by inspecting the handshake packets: -- **ClientHello**: Inspect the TLS `supported_groups` extension (Extension 10). When PQC is active, `X25519MLKEM768` (Group ID `0x4543` / `17731` or standardized IANA PQC identifier) is advertised in the ClientHello. -- **ServerHello**: The GFE endpoint selects `X25519MLKEM768` in the `key_share` extension, confirming that hybrid post-quantum key agreement was established for the connection. - ---- - -## 4. Architecture & Minimum Required Versions - -PQC enablement for HTTP/JSON transport requires compatible versions of `gax-httpjson` and `google-http-client`: +PQC enablement for HTTP/JSON transport requires compatible versions of `conscrypt-openjdk-uber`, `gax-httpjson`, and `google-http-client`: > [!TIP] > **Recommended BOM**: > We recommend importing Google Cloud Java libraries using **`libraries-bom` version `26.86.0+`**, which automatically manages compatible dependency versions across all Google Cloud client libraries, GAX, and the Google HTTP Client. -### Minimum Required Versions - | Library | Minimum Required Version | Role | | :--- | :--- | :--- | +| **`conscrypt-openjdk-uber`** | `2.6.0+` | Provides BoringSSL native C engine and TLS 1.3 PQC hybrid named groups. | | **`gax-httpjson`** | `2.83.0+` | Automatically registers Conscrypt as the TLS security provider and configures PQC named groups. | | **`google-http-client`** | `2.2.0+` | Provides security provider registration and socket configurators on `NetHttpTransport.Builder`. | -### How GAX and Google Cloud Servers Work Together +### 2.2 Why Conscrypt? -When you construct a Google Cloud HTTP/JSON service client, `gax-httpjson` automatically registers Conscrypt as the underlying cryptographic provider on the Google HTTP Client (`NetHttpTransport`). +Standard Java Development Kits (JDK 8, 11, 17, and 21) do not natively support Post-Quantum Cryptography in their built-in TLS providers (`SunJSSE`). While native ML-KEM support is planned for **JDK 27+**, requiring all users to upgrade to JDK 27 is not feasible for most production environments. -- **Negotiation with Google Cloud Servers**: During the TLS 1.3 handshake, `gax-httpjson` advertises Post-Quantum Cryptography named groups (`X25519MLKEM768`, etc.) in preference order alongside classical TLS groups. When connecting to Google Cloud Front End (GFE) endpoints, the server evaluates the client's list from top to bottom and **selects the first compatible algorithm from the list that it also supports**—in this case, `X25519MLKEM768` (#1 preference), establishing an authenticated post-quantum session. -- **Transparent Endpoint Compatibility**: When connecting to endpoints that do not yet support PQC, the server skips the unknown post-quantum identifiers at the top of the list and selects **the first compatible algorithm from the client's list that it recognizes** (such as classical `X25519`), transparently negotiating standard TLS without dropping the connection. -- **Platform Runtime Fallback**: If the runtime environment cannot load native Conscrypt libraries, `gax-httpjson` catches the error, logs a concise warning, and falls back to standard JDK JSSE (`SunJSSE`), ensuring network connectivity is never broken. +We chose **Conscrypt** (`conscrypt-openjdk-uber`) because: +1. **Maximum Java & OS Compatibility**: Conscrypt wraps Google's BoringSSL cryptographic engine via JNI, enabling quantum-resistant TLS 1.3 handshakes across existing Java LTS runtimes (Java 8, 11, 17, 21, and 25). +2. **Zero Runtime Configuration Required**: By bundling Conscrypt as an optional dependency, `gax-httpjson` delivers high-performance PQC out-of-the-box without requiring users to replace their JVM or upgrade their JDK. + +### 2.3 How HTTP/JSON Clients and Google Cloud Servers Work Together + +When you construct a Google Cloud HTTP/JSON service client, `gax-httpjson` registers Conscrypt on the Google HTTP Client (`NetHttpTransport`) to advertise PQC and classical groups in preference order: + +- **PQC-Enabled Endpoints (GFE)**: During the TLS 1.3 handshake, Google Front End servers select `X25519MLKEM768` (#1 preference), establishing a quantum-resistant session. +- **Non-PQC Endpoints**: Endpoints that do not support PQC ignore unknown post-quantum identifiers and select the first compatible classical algorithm (such as `X25519`). +- **Platform Runtime Fallback**: If Conscrypt native libraries cannot load on the OS, the client logs a concise warning and falls back to standard JDK JSSE (`SunJSSE`). ``` +-------------------------------------------------------------------+ @@ -98,9 +65,7 @@ When you construct a Google Cloud HTTP/JSON service client, `gax-httpjson` autom on older non-PQC servers ``` ---- - -## 5. Supported Key Exchange Groups +### 2.4 Supported Key Exchange Groups Google Cloud HTTP/JSON client libraries configure Conscrypt to advertise the following named groups in preference order: @@ -115,9 +80,7 @@ Google Cloud HTTP/JSON client libraries configure Conscrypt to advertise the fol For additional details on Conscrypt's cryptographic algorithms and capabilities, refer to the official [Conscrypt CAPABILITIES.md](https://github.com/google/conscrypt/blob/2.6.0/CAPABILITIES.md#supported-named-groups). ---- - -## 6. Platform Compatibility & Native Library Limitations +### 2.5 Platform Compatibility & Native Library Limitations Because Conscrypt relies on C native shared libraries (`conscrypt-openjdk-uber`) loaded via Java Native Interface (JNI), PQC support depends on OS platform compatibility: @@ -132,13 +95,36 @@ Because Conscrypt relies on C native shared libraries (`conscrypt-openjdk-uber`) ``` - Your application will continue running normally using classical TLS provided by the JDK. ---- +### 2.6 Verifying PQC in HTTP/JSON Client Libraries + +You can verify that your Google Cloud HTTP/JSON Java client library is actively negotiating Post-Quantum Cryptography through operational logs or debug logging. Note that the log messages and logger categories below apply specifically to HTTP/JSON (REST) client libraries. + +#### 1. Check Operational Log Messages +When Conscrypt initializes successfully and configures PQC named groups, **no warning logs are emitted**. + +If your environment cannot load native Conscrypt libraries or cannot configure PQC groups, the library emits a concise, one-line warning at `Level.WARNING` and safely falls back to standard JDK TLS: +``` +WARNING: Conscrypt native libraries not available. Falling back to JDK TLS. +``` +If you **do not see this warning message** in your application logs, Conscrypt has successfully initialized and enabled PQC key exchange. + +#### 2. Enable Debug Logging (`Level.FINE`) +To inspect the exact initialization status and any underlying native library loader exceptions, enable debug logging (`Level.FINE`) for `com.google.api.gax.httpjson.HttpJsonConscryptUtils`: + +- In `logging.properties`: + ```properties + com.google.api.gax.httpjson.HttpJsonConscryptUtils.level = FINE + ``` +- If an error occurs during initialization, the full exception stacktrace (`UnsatisfiedLinkError`, `LinkageError`, etc.) will appear only at `FINE` level: + ``` + FINE: Conscrypt initialization failed with exception: java.lang.UnsatisfiedLinkError: ... + ``` -## 7. Custom & Alternative Configurations +### 2.7 Custom & Alternative Configurations If you need to disable PQC, force classical key exchange, bypass Conscrypt, or use a third-party security provider, you can customize the transport provider. -### Alternative 1: Forcing Classical (Non-PQC) Key Exchange +#### Alternative 1: Forcing Classical (Non-PQC) Key Exchange To explicitly restrict key exchange to classical `X25519` (disabling post-quantum hybrid groups): @@ -183,7 +169,7 @@ try (SecretManagerServiceClient client = SecretManagerServiceClient.create(setti } ``` -### Alternative 2: Bypassing Conscrypt to Use Standard JDK JSSE +#### Alternative 2: Bypassing Conscrypt to Use Standard JDK JSSE To bypass Conscrypt completely and use the standard JDK JSSE TLS provider: @@ -211,7 +197,7 @@ try (SecretManagerServiceClient client = SecretManagerServiceClient.create(setti } ``` -### Alternative 3: Configuring Custom Security Providers +#### Alternative 3: Configuring Custom Security Providers If your application requires a custom cryptographic provider (such as Bouncy Castle), you can configure it on a specific `NetHttpTransport` instance using `NetHttpTransport.Builder.setSecurityProvider(...)` and `.setSslSocketConfigurator(...)`: @@ -253,9 +239,10 @@ try (SecretManagerServiceClient client = SecretManagerServiceClient.create(setti --- -## 8. Addendum: JDK 27+ and Native OpenJDK PQC Support +## 3. Addendum: JDK 27+ and Native OpenJDK PQC Support As quantum-resistant cryptography standards mature, OpenJDK is incorporating native PQC support directly into standard Java releases: - Starting with **JDK 27**, standard JDK Security Providers (`SunJSSE`) include native support for NIST post-quantum key encapsulation standards (JEP / ML-KEM). -- When running on JDK 27 or later, Java applications automatically negotiate ML-KEM PQC key exchange out-of-the-box—without requiring Conscrypt or JNI native dependencies. +- **Google Cloud Java Client Libraries**: Google Cloud Java client SDKs use Conscrypt by default whenever it is available on the platform (delivering hardware-accelerated BoringSSL performance across all Java releases). +- **Your Own Applications**: For your own Java applications or non-Conscrypt HTTPS connections running on JDK 27 or later, standard OpenJDK Security Providers automatically negotiate ML-KEM PQC key exchange out-of-the-box—even without Conscrypt or JNI native dependencies. - No code or configuration changes are required in Google Cloud Java client libraries when running on JDK 27+. From 8b5351776f13cc0d92d7ad1f5b054d6273eb9ff3 Mon Sep 17 00:00:00 2001 From: Lawrence Qiu Date: Thu, 30 Jul 2026 20:28:00 +0000 Subject: [PATCH 06/25] docs: update PQC guide with debug-level logging and prominent WARNING callout on user responsibility --- docs/post_quantum_cryptography_guide.md | 48 ++++++++++++------------- 1 file changed, 22 insertions(+), 26 deletions(-) diff --git a/docs/post_quantum_cryptography_guide.md b/docs/post_quantum_cryptography_guide.md index 7f607e683cc1..2c045378cffd 100644 --- a/docs/post_quantum_cryptography_guide.md +++ b/docs/post_quantum_cryptography_guide.md @@ -12,7 +12,11 @@ Traditional TLS public-key encryption (such as RSA and ECDH) is vulnerable to fu ## 2. HTTP/JSON (REST) Client Library Support -Post-Quantum Cryptography is **enabled by default** for **HTTP/JSON** (REST) transport in Google Cloud Java client libraries (`gax-httpjson`) whenever native Conscrypt / BoringSSL libraries are supported on the runtime environment. +Google Cloud Java client libraries (`gax-httpjson`) use **Conscrypt by default** to achieve Post-Quantum Cryptography (PQC) for **HTTP/JSON** (REST) transport whenever native BoringSSL libraries are supported on the runtime environment. + +> [!WARNING] +> **User Responsibility for Conscrypt Compatibility**: +> It is the user's responsibility to ensure that their runtime environment supports Conscrypt native libraries if they want to use the default PQC configuration. Otherwise, users can opt to use alternative configurations (see **Section 2.7**). If Conscrypt cannot be initialized, the client library will silently fall back to standard JDK JSSE (`SunJSSE`), which on Java 8–20 has no Post-Quantum Cryptography support. See **Section 2.5 (Known Conscrypt Compatibility Issues)** for more information. ### 2.1 Minimum Required Versions @@ -30,19 +34,19 @@ PQC enablement for HTTP/JSON transport requires compatible versions of `conscryp ### 2.2 Why Conscrypt? -Standard Java Development Kits (JDK 8, 11, 17, and 21) do not natively support Post-Quantum Cryptography in their built-in TLS providers (`SunJSSE`). While native ML-KEM support is planned for **JDK 27+**, requiring all users to upgrade to JDK 27 is not feasible for most production environments. +Standard Java Development Kits (Java 8–20) do not natively support Post-Quantum Cryptography in their built-in TLS providers (`SunJSSE`). While native ML-KEM support is planned for **JDK 27+**, requiring all users to upgrade to JDK 27 is not feasible for most production environments. -We chose **Conscrypt** (`conscrypt-openjdk-uber`) because: -1. **Maximum Java & OS Compatibility**: Conscrypt wraps Google's BoringSSL cryptographic engine via JNI, enabling quantum-resistant TLS 1.3 handshakes across existing Java LTS runtimes (Java 8, 11, 17, 21, and 25). +**Conscrypt** (`conscrypt-openjdk-uber`) is the default `SecurityProvider` for Google Cloud Java client libraries because: +1. **Maximum Java & OS Compatibility**: Conscrypt wraps Google's BoringSSL cryptographic engine via JNI, enabling quantum-resistant TLS 1.3 handshakes across existing Java runtimes (**Java 8+**). 2. **Zero Runtime Configuration Required**: By bundling Conscrypt as an optional dependency, `gax-httpjson` delivers high-performance PQC out-of-the-box without requiring users to replace their JVM or upgrade their JDK. ### 2.3 How HTTP/JSON Clients and Google Cloud Servers Work Together When you construct a Google Cloud HTTP/JSON service client, `gax-httpjson` registers Conscrypt on the Google HTTP Client (`NetHttpTransport`) to advertise PQC and classical groups in preference order: -- **PQC-Enabled Endpoints (GFE)**: During the TLS 1.3 handshake, Google Front End servers select `X25519MLKEM768` (#1 preference), establishing a quantum-resistant session. +- **PQC-Enabled Google Cloud Endpoints**: During the TLS 1.3 handshake, Google Cloud servers select `X25519MLKEM768` (#1 preference), establishing a quantum-resistant session. - **Non-PQC Endpoints**: Endpoints that do not support PQC ignore unknown post-quantum identifiers and select the first compatible classical algorithm (such as `X25519`). -- **Platform Runtime Fallback**: If Conscrypt native libraries cannot load on the OS, the client logs a concise warning and falls back to standard JDK JSSE (`SunJSSE`). +- **Platform Runtime Fallback**: If Conscrypt native libraries cannot load on the OS, the client logs at debug level (`FINE`) and falls back to standard JDK JSSE (`SunJSSE`) without emitting operational warnings. ``` +-------------------------------------------------------------------+ @@ -59,8 +63,8 @@ When you construct a Google Cloud HTTP/JSON service client, `gax-httpjson` regis google-http-client uses Conscrypt Falls back to JDK JSSE Offers PQC Hybrid + Classical Groups Offers Standard JDK Classical Groups - Server selects 1st compatible group - Server negotiates Classical - - Negotiates X25519MLKEM768 on - Negotiates Classical X25519 / - Google Cloud Front End (GFE) secp256r1 via JDK TLS + - Negotiates X25519MLKEM768 on X25519 / secp256r1 via JDK TLS + Google Cloud Endpoints - Automatically falls back to X25519 on older non-PQC servers ``` @@ -80,45 +84,37 @@ Google Cloud HTTP/JSON client libraries configure Conscrypt to advertise the fol For additional details on Conscrypt's cryptographic algorithms and capabilities, refer to the official [Conscrypt CAPABILITIES.md](https://github.com/google/conscrypt/blob/2.6.0/CAPABILITIES.md#supported-named-groups). -### 2.5 Platform Compatibility & Native Library Limitations +### 2.5 Known Conscrypt Compatibility Issues -Because Conscrypt relies on C native shared libraries (`conscrypt-openjdk-uber`) loaded via Java Native Interface (JNI), PQC support depends on OS platform compatibility: +Because Conscrypt relies on C native shared libraries (`conscrypt-openjdk-uber`) loaded via Java Native Interface (JNI), PQC support depends on OS platform compatibility. Note that the constraints below represent known common issues and are **not an exhaustive list** of Conscrypt platform requirements: 1. **System & GLIBC Compatibility Constraints**: - **Linux glibc Versioning**: Conscrypt native C binaries require compatible C runtime (`glibc`) versions (such as `GLIBC_2.35+`). Older Linux distributions or lightweight images (such as Alpine Linux using `musl` libc) will fail to load native libraries (`UnsatisfiedLinkError`). - **Restricted Filesystems**: Operating systems that mount `/tmp` with `noexec`, strict container security profiles, or environments blocking JNI library extraction will prevent Conscrypt from initializing. 2. **Graceful Fallback Behavior**: - - Whenever native library loading fails, `gax-httpjson` catches the error, logs a concise warning at `Level.WARNING`, and safely falls back to standard JDK JSSE: + - Whenever native library loading fails, `gax-httpjson` catches the error, logs at **`Level.FINE` (debug level)**, and safely falls back to standard JDK JSSE (`SunJSSE`): ``` - WARNING: Conscrypt native libraries not available. Falling back to JDK TLS. + FINE: Conscrypt native libraries not available. Falling back to JDK TLS. ``` - - Your application will continue running normally using classical TLS provided by the JDK. + - Your application will continue running normally using classical TLS provided by the JDK without emitting warnings in standard operational logs. ### 2.6 Verifying PQC in HTTP/JSON Client Libraries -You can verify that your Google Cloud HTTP/JSON Java client library is actively negotiating Post-Quantum Cryptography through operational logs or debug logging. Note that the log messages and logger categories below apply specifically to HTTP/JSON (REST) client libraries. - -#### 1. Check Operational Log Messages -When Conscrypt initializes successfully and configures PQC named groups, **no warning logs are emitted**. - -If your environment cannot load native Conscrypt libraries or cannot configure PQC groups, the library emits a concise, one-line warning at `Level.WARNING` and safely falls back to standard JDK TLS: -``` -WARNING: Conscrypt native libraries not available. Falling back to JDK TLS. -``` -If you **do not see this warning message** in your application logs, Conscrypt has successfully initialized and enabled PQC key exchange. +You can verify that your Google Cloud HTTP/JSON Java client library is actively negotiating Post-Quantum Cryptography through debug logging. Note that the log messages and logger categories below apply specifically to HTTP/JSON (REST) client libraries. -#### 2. Enable Debug Logging (`Level.FINE`) -To inspect the exact initialization status and any underlying native library loader exceptions, enable debug logging (`Level.FINE`) for `com.google.api.gax.httpjson.HttpJsonConscryptUtils`: +To inspect whether Conscrypt successfully initialized or why it fell back to JDK TLS, enable debug logging (`Level.FINE`) for `com.google.api.gax.httpjson.HttpJsonConscryptUtils`: - In `logging.properties`: ```properties com.google.api.gax.httpjson.HttpJsonConscryptUtils.level = FINE ``` -- If an error occurs during initialization, the full exception stacktrace (`UnsatisfiedLinkError`, `LinkageError`, etc.) will appear only at `FINE` level: +- When Conscrypt is unavailable or fails to initialize, it logs at `Level.FINE`: ``` + FINE: Conscrypt native library unavailable. Falling back to default JDK TLS. FINE: Conscrypt initialization failed with exception: java.lang.UnsatisfiedLinkError: ... ``` +- When Conscrypt initializes successfully, no fallback messages appear in the `FINE` logs. ### 2.7 Custom & Alternative Configurations From 44706619383bf19b69007c86f9039582706ebbda Mon Sep 17 00:00:00 2001 From: Lawrence Qiu Date: Wed, 2 Sep 2026 17:50:30 +0000 Subject: [PATCH 07/25] docs: revamp Post-Quantum Cryptography guide for HTTP/JSON transport - Frame PQC concepts with beginner-friendly explanations and the two-lock hybrid analogy. - Clarify transport scope: focus exclusively on HTTP/JSON transport and note gRPC coverage in a future PR. - Document handshake size overhead (~1-2KB) and negligible runtime API latency impact due to connection pooling. - Detail deployment compatibility matrix covering glibc Linux, Alpine/musl fallback, and hardened noexec /tmp filesystems. - Add prominent warning on silent fallback tradeoff between high availability and strict regulatory compliance. - Provide step-by-step verification instructions using GAX debug logs and JVM -Djavax.net.debug=ssl:handshake output. - Present modular, non-prescriptive configuration choices (default Conscrypt, classical-only X25519, pure JDK JSSE, dependency exclusion, and custom Bouncy Castle provider). - Add future outlook on OpenJDK native ML-KEM support in JDK 27+. --- docs/post_quantum_cryptography_guide.md | 390 +++++++++++++++++------- 1 file changed, 282 insertions(+), 108 deletions(-) diff --git a/docs/post_quantum_cryptography_guide.md b/docs/post_quantum_cryptography_guide.md index 2c045378cffd..e8f9d52d77ca 100644 --- a/docs/post_quantum_cryptography_guide.md +++ b/docs/post_quantum_cryptography_guide.md @@ -1,128 +1,271 @@ -# Post-Quantum Cryptography (PQC) User Guide for HTTP/JSON Java Client Libraries +# Post-Quantum Cryptography (PQC) User Guide for HTTP/JSON (REST) Java Client Libraries -## 1. The Quantum Threat & Why PQC is Critical +## 1. Executive Summary & Core Concepts -Traditional TLS public-key encryption (such as RSA and ECDH) is vulnerable to future decryption by quantum computers. +### 1.1 What is Post-Quantum Cryptography (PQC)? +Traditional Transport Layer Security (TLS) public-key cryptography—such as RSA and Elliptic Curve Diffie-Hellman (ECDH)—relies on mathematical problems (integer factorization and discrete logarithms) that are practically impossible for classical computers to solve in a reasonable timeframe. -- **The Risk ("Store-Now, Decrypt-Later")**: Adversaries can intercept and store encrypted network traffic today with the intent to decrypt it once cryptographically relevant quantum computers become available. -- **The Consequence**: Without Post-Quantum Cryptography (PQC), sensitive data transmitted today—such as credentials, financial records, and customer data—is at risk of retroactive decryption in the future. -- **The Solution (Hybrid PQC)**: Google Cloud HTTP/JSON Java client libraries support **Hybrid PQC Key Exchange** (such as `X25519MLKEM768`), combining a classical ECDH algorithm (like `X25519`) with a NIST-standardized Post-Quantum Key Encapsulation Mechanism (like `ML-KEM-768`, FIPS 203). This protects encrypted traffic against both present-day and future quantum threats without sacrificing existing security. +However, sufficiently large, cryptographically relevant quantum computers (CRQCs) will be capable of breaking these mathematical foundations using Shor's algorithm. **Post-Quantum Cryptography (PQC)** refers to a new class of cryptographic algorithms designed to run on classical hardware while remaining mathematically secure against attacks from both classical and quantum computers. + +### 1.2 The Threat: "Store-Now, Decrypt-Later" (SNDL) +You might wonder why post-quantum security matters today if large-scale quantum computers do not yet exist. The primary threat is **Store-Now, Decrypt-Later (SNDL)**: +- **The Attack**: Adversaries can intercept and archive encrypted network communications traversing the public internet today. +- **The Consequence**: Even if attackers cannot read your ciphertext now, they can store the encrypted traffic indefinitely and decrypt it in the future once quantum computers become available. +- **The Impact**: Any data with a long secrecy lifecycle—such as customer records, credentials, intellectual property, health information, and financial transactions—is vulnerable to retroactive exposure unless protected before transmission. + +### 1.3 The Solution: Hybrid Key Exchange +Rather than completely replacing proven classical algorithms with brand-new post-quantum mechanisms, Google Cloud and standards bodies (NIST) utilize **Hybrid Key Exchange** (specifically `X25519MLKEM768`): + +> [!TIP] +> **The Two-Lock Analogy**: +> Think of hybrid key exchange like securing a door with **two distinct locks**: +> 1. A battle-tested **classical lock** (`X25519` elliptic curve). +> 2. A quantum-resistant **post-quantum lock** (`ML-KEM-768`, NIST FIPS 203). +> +> To decrypt the session, an attacker must break **both** locks simultaneously: +> - If an unforeseen mathematical weakness is ever discovered in the post-quantum algorithm, the classical algorithm still maintains security. +> - If a quantum computer breaks the classical algorithm, the post-quantum algorithm still maintains security. + +### 1.4 What Changes vs. What Stays the Same? +For software engineers and application developers, adopting PQC in Google Cloud Java client libraries requires no changes to business logic: +- **What stays exactly the same**: + - Your application source code and business logic. + - How you construct and call API clients (e.g., `SecretManagerServiceClient`, `StorageClient`). + - Authentication tokens, Service Account keys, and OAuth2 credentials. + - Request and response JSON payloads. +- **What changes**: + - Only the initial **TLS 1.3 cryptographic handshake** (Layer 4/6) performed when the client opens an HTTPS connection to Google Cloud endpoints (`*.googleapis.com`). --- -## 2. HTTP/JSON (REST) Client Library Support +## 2. Transport Scope: HTTP/JSON (REST) vs. gRPC -Google Cloud Java client libraries (`gax-httpjson`) use **Conscrypt by default** to achieve Post-Quantum Cryptography (PQC) for **HTTP/JSON** (REST) transport whenever native BoringSSL libraries are supported on the runtime environment. +Google Cloud Java client libraries support two underlying transport mechanisms: **gRPC** (HTTP/2 with Protobuf) and **HTTP/JSON** (REST with JSON): +- Most Google Cloud Java clients use **gRPC by default** (e.g., Cloud Bigtable, Cloud Spanner, Cloud Pub/Sub). +- Clients use **HTTP/JSON** when explicitly configured (e.g., via `ClientSettings.newHttpJsonBuilder()`), when interacting with HTTP-only services (e.g., Google Cloud Compute Engine, Cloud Storage JSON API), or in corporate networks where firewalls restrict non-standard HTTP/2 gRPC traffic. -> [!WARNING] -> **User Responsibility for Conscrypt Compatibility**: -> It is the user's responsibility to ensure that their runtime environment supports Conscrypt native libraries if they want to use the default PQC configuration. Otherwise, users can opt to use alternative configurations (see **Section 2.7**). If Conscrypt cannot be initialized, the client library will silently fall back to standard JDK JSSE (`SunJSSE`), which on Java 8–20 has no Post-Quantum Cryptography support. See **Section 2.5 (Known Conscrypt Compatibility Issues)** for more information. +> [!NOTE] +> **Scope of This Guide**: +> This guide focuses exclusively on **HTTP/JSON (REST)** transport (`gax-httpjson` and `google-http-client`). gRPC transport manages its TLS lifecycle independently via `grpc-netty-shaded` and will be covered in a subsequent guide. + +--- -### 2.1 Minimum Required Versions +## 3. HTTP/JSON Transport Architecture & Defaults +### 3.1 Minimum Required Versions PQC enablement for HTTP/JSON transport requires compatible versions of `conscrypt-openjdk-uber`, `gax-httpjson`, and `google-http-client`: -> [!TIP] -> **Recommended BOM**: -> We recommend importing Google Cloud Java libraries using **`libraries-bom` version `26.86.0+`**, which automatically manages compatible dependency versions across all Google Cloud client libraries, GAX, and the Google HTTP Client. - -| Library | Minimum Required Version | Role | +| Library | Minimum Version | Role | | :--- | :--- | :--- | -| **`conscrypt-openjdk-uber`** | `2.6.0+` | Provides BoringSSL native C engine and TLS 1.3 PQC hybrid named groups. | -| **`gax-httpjson`** | `2.83.0+` | Automatically registers Conscrypt as the TLS security provider and configures PQC named groups. | -| **`google-http-client`** | `2.2.0+` | Provides security provider registration and socket configurators on `NetHttpTransport.Builder`. | +| **`libraries-bom`** | `26.86.0+` | **Recommended**. Central BOM managing compatible versions across all Google Cloud client libraries. | +| **`gax-httpjson`** | `2.83.0+` | Automatically configures Conscrypt as the TLS security provider and sets PQC named groups. | +| **`google-http-client`** | `2.2.0+` | Provides transport-level security provider registration on `NetHttpTransport.Builder`. | +| **`conscrypt-openjdk-uber`** | `2.6.0+` *(2.6.2+ recommended)* | Provides Google's BoringSSL native C engine and TLS 1.3 PQC hybrid named groups. | + +### 3.2 Why Conscrypt? +Built-in Java Development Kits (Java 8 through Java 20) do not support Post-Quantum Cryptography in their default Java Secure Socket Extension provider (`SunJSSE`). While native ML-KEM support is in development for future Java releases (**JDK 27+** via JEP 496), requiring all production enterprise workloads to immediately upgrade to bleeding-edge JDK versions is impractical. + +To bridge this gap, Google Cloud Java client libraries use **Conscrypt** (`conscrypt-openjdk-uber`) as the default security provider for HTTP/JSON transport: +1. **Immediate PQC Availability Across Java 8+**: Conscrypt embeds Google's open-source BoringSSL cryptographic engine via Java Native Interface (JNI). This enables quantum-resistant TLS 1.3 handshakes on existing production runtimes (Java 8, 11, 17, and 21). +2. **Zero Code Changes**: When `gax-httpjson` detects compatible Conscrypt libraries on the classpath, it automatically configures the HTTPS transport without requiring manual SSLContext setup. +3. **High Performance**: BoringSSL contains hardware-accelerated assembly optimizations for modern CPU architectures (x86_64 and ARM64). + +### 3.3 How Client and Google Cloud Endpoints Negotiate PQC +When a Google Cloud HTTP/JSON client initiates a connection, it advertises supported key exchange groups to the server in strict preference order: + +1. `X25519MLKEM768` *(#1 Preference: Hybrid Post-Quantum Key Exchange)* +2. `SecP256r1MLKEM768` *(Hybrid Post-Quantum Key Exchange with NIST P-256)* +3. `MLKEM1024` *(Pure Post-Quantum Key Exchange)* +4. `MLKEM768` *(Pure Post-Quantum Key Exchange)* +5. `X25519Kyber768Draft00` *(Deprecated draft group retained for backward compatibility)* +6. `X25519` *(Classical ECDH)* +7. `secp256r1` *(Classical ECDH)* +8. `secp384r1` *(Classical ECDH)* + +#### Handshake Negotiation Flow: +- **PQC-Enabled Google Cloud Endpoints**: Google Cloud frontends recognize `X25519MLKEM768` as their preferred group. The client and server agree on this hybrid algorithm, establishing a quantum-resistant TLS 1.3 session. +- **Non-PQC Endpoints / Middleboxes**: If a server or intermediate network proxy does not yet support post-quantum cryptography, it ignores the unrecognized post-quantum identifiers and selects the first mutually supported classical group (e.g., `X25519`). +- **Graceful Client Fallback**: If Conscrypt native libraries cannot load on the client host, the client seamlessly falls back to standard JDK JSSE (`SunJSSE`), negotiating classical TLS 1.3. -### 2.2 Why Conscrypt? +``` ++-------------------------------------------------------------------------------+ +| GAPIC HTTP/JSON Client Request | ++-------------------------------------------------------------------------------+ + | + Is Conscrypt JNI Available on This Platform? + | + +-------------------+-------------------+ + | | + [ YES ] [ NO ] + | | + v v + google-http-client uses Conscrypt Falls back to JDK JSSE + Offers Hybrid PQC + Classical Groups Offers Standard JDK Classical Groups + - Google Cloud negotiates X25519MLKEM768 - Negotiates classical X25519 + - Non-PQC endpoints fall back to X25519 via standard JDK SunJSSE +``` -Standard Java Development Kits (Java 8–20) do not natively support Post-Quantum Cryptography in their built-in TLS providers (`SunJSSE`). While native ML-KEM support is planned for **JDK 27+**, requiring all users to upgrade to JDK 27 is not feasible for most production environments. +### 3.4 Performance, Network, & Handshake Characteristics +Understanding the real-world performance implications helps teams make informed deployment decisions: +- **TLS Handshake Size Overhead**: + - Classical `X25519` public keys are very compact: **32 bytes**. + - `ML-KEM-768` public keys are **1,184 bytes**, and ciphertexts are **1,088 bytes**. + - Consequently, the TLS `ClientHello` and `ServerHello` messages increase by approximately **1 to 2 kilobytes**. +- **Connection Pooling & API Latency**: + - Google Cloud Java client libraries maintain persistent HTTP connection pools (`Keep-Alive`). + - The TLS handshake occurs **only once** when a pooled connection is established. + - Subsequent API requests reuse existing open connections without repeating the TLS handshake. Therefore, the runtime latency impact on everyday API requests is **negligible**. +- **CPU Computation**: + - Modern CPUs execute ML-KEM key generation and encapsulation in under 50 microseconds. In benchmark testing, CPU utilization differences between classical and hybrid handshakes are within normal margin of error. -**Conscrypt** (`conscrypt-openjdk-uber`) is the default `SecurityProvider` for Google Cloud Java client libraries because: -1. **Maximum Java & OS Compatibility**: Conscrypt wraps Google's BoringSSL cryptographic engine via JNI, enabling quantum-resistant TLS 1.3 handshakes across existing Java runtimes (**Java 8+**). -2. **Zero Runtime Configuration Required**: By bundling Conscrypt as an optional dependency, `gax-httpjson` delivers high-performance PQC out-of-the-box without requiring users to replace their JVM or upgrade their JDK. +--- -### 2.3 How HTTP/JSON Clients and Google Cloud Servers Work Together +## 4. Deployment Environments & Platform Compatibility -When you construct a Google Cloud HTTP/JSON service client, `gax-httpjson` registers Conscrypt on the Google HTTP Client (`NetHttpTransport`) to advertise PQC and classical groups in preference order: +Because Conscrypt relies on C native shared libraries (`.so`, `.dylib`, or `.dll`) loaded via JNI, platform compatibility depends on the host operating system and container environment. -- **PQC-Enabled Google Cloud Endpoints**: During the TLS 1.3 handshake, Google Cloud servers select `X25519MLKEM768` (#1 preference), establishing a quantum-resistant session. -- **Non-PQC Endpoints**: Endpoints that do not support PQC ignore unknown post-quantum identifiers and select the first compatible classical algorithm (such as `X25519`). -- **Platform Runtime Fallback**: If Conscrypt native libraries cannot load on the OS, the client logs at debug level (`FINE`) and falls back to standard JDK JSSE (`SunJSSE`) without emitting operational warnings. +### 4.1 Compatibility Matrix +| Environment / OS | Status | Notes | +| :--- | :--- | :--- | +| **Standard Linux (Ubuntu, Debian, RHEL, CentOS)** | **Fully Supported** | Requires `glibc` 2.17+ (Conscrypt 2.6.2+) or `glibc` 2.35+ (Conscrypt 2.6.0). | +| **Google Cloud Managed (Cloud Run, GKE, App Engine)** | **Fully Supported** | Default base container environments use compatible `glibc` runtimes. | +| **macOS (Apple Silicon M-series & Intel)** | **Fully Supported** | Native `osx-aarch_64` and `osx-x86_64` binaries bundled in `conscrypt-openjdk-uber`. | +| **Windows (x86_64)** | **Fully Supported** | Native `windows-x86_64` binary bundled in `conscrypt-openjdk-uber`. | +| **Alpine Linux / Musl libc Containers** | **Fallback to Classical** | Conscrypt native binaries are compiled for `glibc`. On Alpine (`musl`), native loading fails with `UnsatisfiedLinkError` and gracefully falls back to JDK TLS. | +| **Containers with `noexec /tmp`** | **Requires Configuration** | By default, JNI extracts libraries to `/tmp`. If `/tmp` is mounted `noexec`, specify `-Dorg.conscrypt.native.workdir`. | + +### 4.2 Handling Alpine Linux (`musl` libc) +If your container images are based on Alpine Linux (e.g., `eclipse-temurin:17-alpine` or `openjdk:11-alpine`), Conscrypt cannot load its native C library because Alpine uses `musl` libc instead of `glibc`. + +**Your Options on Alpine**: +1. **Accept Classical TLS Fallback (No Action)**: The client library will safely fall back to standard JDK JSSE and negotiate classical TLS 1.3 (`X25519`). Your application will function normally without errors. +2. **Switch to a Glibc-Based Base Image (Recommended for PQC)**: If quantum resistance is required in containerized environments, switch to a minimal `glibc`-based base image such as: + - Debian Slim (e.g., `eclipse-temurin:17-jre-jammy` or `eclipse-temurin:21-jre-noble`) + - Distroless Java (e.g., `gcr.io/distroless/java17-debian12`) + - Chainguard JRE with glibc + +### 4.3 Handling Hardened Filesystems & `noexec /tmp` +In hardened Kubernetes pods or security-conscious Docker containers, `/tmp` may be mounted with the `noexec` flag or the entire root filesystem may be marked read-only. + +When Conscrypt starts, the JVM extracts its bundled native `.so` file to a temporary directory. If that directory does not allow execution: +```text +java.lang.UnsatisfiedLinkError: /tmp/libconscrypt_openjdk_jni...: failed to map segment from shared object: Operation not permitted ``` -+-------------------------------------------------------------------+ -| GAPIC HTTP/JSON Client Request | -+-------------------------------------------------------------------+ - | - Is Conscrypt JNI Available on Platform? - | - +----------------+----------------+ - | | - [ YES ] [ NO ] - | | - v v - google-http-client uses Conscrypt Falls back to JDK JSSE - Offers PQC Hybrid + Classical Groups Offers Standard JDK Classical Groups - - Server selects 1st compatible group - Server negotiates Classical - - Negotiates X25519MLKEM768 on X25519 / secp256r1 via JDK TLS - Google Cloud Endpoints - - Automatically falls back to X25519 - on older non-PQC servers +**Solution**: Provide an alternative directory that has write and execute permissions using the JVM system property: +```bash +java -Dorg.conscrypt.native.workdir=/var/run/app/tmp -jar my-application.jar ``` -### 2.4 Supported Key Exchange Groups +### 4.4 Classpath Isolation & Version Skew Warning +If your project uses multiple dependencies that transitively pull in different versions of Conscrypt (e.g., older versions like `2.5.2` alongside `2.6.2`), a JNI ABI mismatch can occur during JVM classloading. Always ensure your build tool (Maven/Gradle) resolves `conscrypt-openjdk-uber` to version `2.6.0+` (or `2.6.2+`) consistently. -Google Cloud HTTP/JSON client libraries configure Conscrypt to advertise the following named groups in preference order: +--- -1. `X25519MLKEM768` -2. `SecP256r1MLKEM768` -3. `MLKEM1024` -4. `MLKEM768` -5. `X25519Kyber768Draft00` *(deprecated draft group kept for backward compatibility)* -6. `X25519` -7. `secp256r1` -8. `secp384r1` +## 5. Important Warning: Availability vs. Strict Compliance -For additional details on Conscrypt's cryptographic algorithms and capabilities, refer to the official [Conscrypt CAPABILITIES.md](https://github.com/google/conscrypt/blob/2.6.0/CAPABILITIES.md#supported-named-groups). +Google Cloud Java client libraries follow a deliberate architectural principle: **prefer service availability over hard failures**. -### 2.5 Known Conscrypt Compatibility Issues +### 5.1 The Silent Fallback Behavior +If Conscrypt native libraries fail to initialize—due to an unsupported operating system, missing `glibc`, permission issues, or file extraction limits—`gax-httpjson` catches the exception and logs a message at **`Level.FINE` (debug level)**: +```text +FINE: Conscrypt native libraries not available. Falling back to JDK TLS. +``` +The client then proceeds to establish standard classical TLS using the host JVM's built-in `SunJSSE` provider. -Because Conscrypt relies on C native shared libraries (`conscrypt-openjdk-uber`) loaded via Java Native Interface (JNI), PQC support depends on OS platform compatibility. Note that the constraints below represent known common issues and are **not an exhaustive list** of Conscrypt platform requirements: +**Why does it behave this way?** +To protect production workloads. A customer updating dependencies or migrating container images should not experience broken API calls or catastrophic application outages simply because a native optimization library could not load on their environment. -1. **System & GLIBC Compatibility Constraints**: - - **Linux glibc Versioning**: Conscrypt native C binaries require compatible C runtime (`glibc`) versions (such as `GLIBC_2.35+`). Older Linux distributions or lightweight images (such as Alpine Linux using `musl` libc) will fail to load native libraries (`UnsatisfiedLinkError`). - - **Restricted Filesystems**: Operating systems that mount `/tmp` with `noexec`, strict container security profiles, or environments blocking JNI library extraction will prevent Conscrypt from initializing. +### 5.2 The Compliance Warning +> [!WARNING] +> **Active Verification is Required for Regulatory Mandates**: +> If your organization operates under strict compliance, governmental, or corporate security mandates requiring Post-Quantum Cryptography today, **you cannot rely solely on the default configuration without verification**. +> +> Because fallback to classical TLS is silent and non-breaking by design, an unexpected environment change (such as switching to an Alpine-based Docker container or changing filesystem mount permissions) could downgrade your connections from hybrid PQC to classical TLS **without throwing exceptions or failing requests**. +> +> If PQC is a mandatory requirement for your workload, you must implement automated verification in your CI/CD pipelines or startup health checks (see **Section 6**). -2. **Graceful Fallback Behavior**: - - Whenever native library loading fails, `gax-httpjson` catches the error, logs at **`Level.FINE` (debug level)**, and safely falls back to standard JDK JSSE (`SunJSSE`): - ``` - FINE: Conscrypt native libraries not available. Falling back to JDK TLS. - ``` - - Your application will continue running normally using classical TLS provided by the JDK without emitting warnings in standard operational logs. +--- -### 2.6 Verifying PQC in HTTP/JSON Client Libraries +## 6. How to Verify PQC Negotiation -You can verify that your Google Cloud HTTP/JSON Java client library is actively negotiating Post-Quantum Cryptography through debug logging. Note that the log messages and logger categories below apply specifically to HTTP/JSON (REST) client libraries. +To confirm whether your application is actively negotiating post-quantum hybrid key exchange, use one or more of the following verification methods. -To inspect whether Conscrypt successfully initialized or why it fell back to JDK TLS, enable debug logging (`Level.FINE`) for `com.google.api.gax.httpjson.HttpJsonConscryptUtils`: +### Method 1: GAX Internal Initialization Logging +Inspect whether `gax-httpjson` successfully loaded Conscrypt or fell back to JDK TLS by enabling debug logging on `HttpJsonConscryptUtils`. -- In `logging.properties`: - ```properties - com.google.api.gax.httpjson.HttpJsonConscryptUtils.level = FINE - ``` -- When Conscrypt is unavailable or fails to initialize, it logs at `Level.FINE`: - ``` +In your `logging.properties` file: +```properties +com.google.api.gax.httpjson.HttpJsonConscryptUtils.level = FINE +java.util.logging.ConsoleHandler.level = FINE +``` + +Or programmatically at application startup: +```java +import java.util.logging.Level; +import java.util.logging.Logger; + +Logger.getLogger("com.google.api.gax.httpjson.HttpJsonConscryptUtils").setLevel(Level.FINE); +``` + +- **When Conscrypt initializes successfully**: No fallback messages appear in the log. +- **When fallback occurs**: You will observe: + ```text FINE: Conscrypt native library unavailable. Falling back to default JDK TLS. FINE: Conscrypt initialization failed with exception: java.lang.UnsatisfiedLinkError: ... ``` -- When Conscrypt initializes successfully, no fallback messages appear in the `FINE` logs. -### 2.7 Custom & Alternative Configurations +### Method 2: JVM TLS Handshake Tracing (`-Djavax.net.debug`) +To inspect the actual cryptographic parameters negotiated during the TLS 1.3 handshake with Google Cloud servers, start your Java application with the standard JSSE debug flag: + +```bash +java -Djavax.net.debug=ssl:handshake -jar my-application.jar +``` + +Look for the following entries in standard error during the initial HTTPS connection: + +1. **ClientHello (Groups Offered)**: + Verify that your client advertises post-quantum hybrid named groups: + ```text + Extension supported_groups (10): [ + NamedGroup: X25519MLKEM768 (0x11ec), + NamedGroup: SecP256r1MLKEM768 (0x11ed), + NamedGroup: x25519 (0x001d), + NamedGroup: secp256r1 (0x0017) + ] + ``` + +2. **ServerHello (Negotiated Algorithm)**: + Verify that the Google Cloud endpoint selects `X25519MLKEM768`: + ```text + ServerHello: + Version: TLSv1.3 + Cipher Suite: TLS_AES_128_GCM_SHA256 + Extension key_share (51): [ + NamedGroup: X25519MLKEM768 (0x11ec) + ] + ``` +If the negotiated group displays `X25519MLKEM768` (or `0x11ec`), your connection is fully protected with hybrid Post-Quantum Cryptography. -If you need to disable PQC, force classical key exchange, bypass Conscrypt, or use a third-party security provider, you can customize the transport provider. +--- + +## 7. Alternative Configurations & Custom Providers + +Google Cloud client libraries are designed to be flexible. You are not locked into Conscrypt; you can configure classical-only key exchange, standard JDK TLS, or custom security providers. + +### Option A: Default Out-of-the-Box (Conscrypt Automatic PQC) +No code required. If you import `libraries-bom:26.86.0+` on a compatible platform, PQC is enabled automatically: +```java +// Standard client construction automatically leverages Conscrypt PQC +try (SecretManagerServiceClient client = SecretManagerServiceClient.create()) { + // Transport negotiates X25519MLKEM768 +} +``` -#### Alternative 1: Forcing Classical (Non-PQC) Key Exchange +--- -To explicitly restrict key exchange to classical `X25519` (disabling post-quantum hybrid groups): +### Option B: Forcing Classical-Only Key Exchange (Disabling PQC) +If you need to use Conscrypt for high-performance TLS but want to explicitly disable post-quantum hybrid groups (for example, to isolate a network middlebox issue or benchmark legacy performance): ```java import com.google.api.client.http.javanet.NetHttpTransport; @@ -132,29 +275,29 @@ import com.google.cloud.secretmanager.v1.SecretManagerServiceClient; import com.google.cloud.secretmanager.v1.SecretManagerServiceSettings; import org.conscrypt.Conscrypt; -// Step 1: Create NetHttpTransport configured with explicit classical named groups -NetHttpTransport transport = +// 1. Build a NetHttpTransport with Conscrypt restricted to classical X25519 +NetHttpTransport classicalTransport = HttpJsonConscryptUtils.configureConscryptSecurityProvider(new NetHttpTransport.Builder()) .setSslSocketConfigurator( socket -> { if (Conscrypt.isConscrypt(socket)) { try { - // Explicitly offer only classical X25519 (disabling PQC hybrid groups) + // Restrict offered groups exclusively to classical X25519 Conscrypt.setNamedGroups(socket, new String[] {"X25519"}); } catch (Exception e) { - // Ignore or log socket configuration failure + // Fallback or log if needed } } }) .build(); -// Step 2: Build transport channel provider using the custom transport +// 2. Configure the transport channel provider InstantiatingHttpJsonChannelProvider transportChannelProvider = SecretManagerServiceSettings.defaultHttpJsonTransportProviderBuilder() - .setHttpTransport(transport) + .setHttpTransport(classicalTransport) .build(); -// Step 3: Instantiate client with settings +// 3. Instantiate the service client SecretManagerServiceSettings settings = SecretManagerServiceSettings.newHttpJsonBuilder() .setTransportChannelProvider(transportChannelProvider) @@ -165,9 +308,10 @@ try (SecretManagerServiceClient client = SecretManagerServiceClient.create(setti } ``` -#### Alternative 2: Bypassing Conscrypt to Use Standard JDK JSSE +--- -To bypass Conscrypt completely and use the standard JDK JSSE TLS provider: +### Option C: Bypassing Conscrypt to Use Standard JDK JSSE +If your deployment environment prohibits native JNI libraries or you prefer using the JVM's built-in cryptographic engine (`SunJSSE`): ```java import com.google.api.client.http.javanet.NetHttpTransport; @@ -175,14 +319,16 @@ import com.google.api.gax.httpjson.InstantiatingHttpJsonChannelProvider; import com.google.cloud.secretmanager.v1.SecretManagerServiceClient; import com.google.cloud.secretmanager.v1.SecretManagerServiceSettings; -// Build a standard NetHttpTransport without GAX Conscrypt configuration +// 1. Build a standard NetHttpTransport without Conscrypt configuration NetHttpTransport standardTransport = new NetHttpTransport.Builder().build(); +// 2. Attach the standard transport to the channel provider InstantiatingHttpJsonChannelProvider transportProvider = SecretManagerServiceSettings.defaultHttpJsonTransportProviderBuilder() .setHttpTransport(standardTransport) .build(); +// 3. Create settings and instantiate client SecretManagerServiceSettings settings = SecretManagerServiceSettings.newHttpJsonBuilder() .setTransportChannelProvider(transportProvider) @@ -193,9 +339,37 @@ try (SecretManagerServiceClient client = SecretManagerServiceClient.create(setti } ``` -#### Alternative 3: Configuring Custom Security Providers +--- + +### Option D: Completely Excluding Conscrypt via Maven or Gradle +If you want to ensure that Conscrypt is never pulled onto your classpath (and never loaded by any client in your application), exclude it in your build configuration: + +**Maven (`pom.xml`)**: +```xml + + com.google.cloud + google-cloud-secretmanager + + + org.conscrypt + conscrypt-openjdk-uber + + + +``` + +**Gradle (`build.gradle`)**: +```groovy +configurations.all { + exclude group: 'org.conscrypt', module: 'conscrypt-openjdk-uber' +} +``` +When Conscrypt is not present on the classpath, `gax-httpjson` detects its absence and automatically uses standard JDK JSSE. + +--- -If your application requires a custom cryptographic provider (such as Bouncy Castle), you can configure it on a specific `NetHttpTransport` instance using `NetHttpTransport.Builder.setSecurityProvider(...)` and `.setSslSocketConfigurator(...)`: +### Option E: Configuring a Third-Party Security Provider (e.g., Bouncy Castle) +If your enterprise utilizes an alternative cryptographic provider (such as Bouncy Castle FIPS), configure it directly on the `NetHttpTransport.Builder`: ```java import com.google.api.client.http.javanet.NetHttpTransport; @@ -203,21 +377,22 @@ import com.google.api.gax.httpjson.InstantiatingHttpJsonChannelProvider; import com.google.cloud.secretmanager.v1.SecretManagerServiceClient; import com.google.cloud.secretmanager.v1.SecretManagerServiceSettings; import java.security.Provider; +import java.security.Security; -// Step 1: Instantiate custom security provider -Provider customProvider = new org.bouncycastle.jce.provider.BouncyCastleProvider(); +// 1. Instantiate or lookup custom security provider +Provider customProvider = Security.getProvider("BC"); // e.g., BouncyCastleProvider -// Step 2: Configure NetHttpTransport with custom security provider and SSLSocketConfigurator +// 2. Configure NetHttpTransport with the custom provider NetHttpTransport customTransport = new NetHttpTransport.Builder() .setSecurityProvider(customProvider) .setSslSocketConfigurator( socket -> { - // Configure custom SSLSocket options (e.g., cipher suites, protocols, or named groups) + // Apply custom socket settings (cipher suites, protocols, named groups) }) .build(); -// Step 3: Build transport provider and service client +// 3. Attach custom transport to client settings InstantiatingHttpJsonChannelProvider transportProvider = SecretManagerServiceSettings.defaultHttpJsonTransportProviderBuilder() .setHttpTransport(customTransport) @@ -229,16 +404,15 @@ SecretManagerServiceSettings settings = .build(); try (SecretManagerServiceClient client = SecretManagerServiceClient.create(settings)) { - // Client communicates using custom security provider scoped strictly to this transport + // Client communicates using custom security provider } ``` --- -## 3. Addendum: JDK 27+ and Native OpenJDK PQC Support +## 8. Future Outlook: Native OpenJDK PQC Support (JDK 27+) -As quantum-resistant cryptography standards mature, OpenJDK is incorporating native PQC support directly into standard Java releases: -- Starting with **JDK 27**, standard JDK Security Providers (`SunJSSE`) include native support for NIST post-quantum key encapsulation standards (JEP / ML-KEM). -- **Google Cloud Java Client Libraries**: Google Cloud Java client SDKs use Conscrypt by default whenever it is available on the platform (delivering hardware-accelerated BoringSSL performance across all Java releases). -- **Your Own Applications**: For your own Java applications or non-Conscrypt HTTPS connections running on JDK 27 or later, standard OpenJDK Security Providers automatically negotiate ML-KEM PQC key exchange out-of-the-box—even without Conscrypt or JNI native dependencies. -- No code or configuration changes are required in Google Cloud Java client libraries when running on JDK 27+. +The cryptographic landscape is continually advancing. The OpenJDK community is integrating standardized post-quantum algorithms directly into the Java platform: +- **JEP 496 (ML-KEM)**: Introduces native implementations of NIST FIPS 203 (Module-Lattice-Based Key-Encapsulation Mechanism) into OpenJDK's standard security providers (`SunJSSE` and `SunJCE`), targeted for **JDK 27+**. +- **What this means for Google Cloud Java**: Once JDK 27 becomes standard in production environments, Java applications will be capable of negotiating hybrid and pure post-quantum TLS natively without requiring JNI shared libraries or third-party dependencies like Conscrypt. +- **Future-Proofing**: As native JDK capabilities mature, Google Cloud Java client libraries will adapt to take advantage of built-in JVM providers, preserving a seamless, zero-maintenance security upgrade path for all users. From f1d2cd68d023562b34b3191742865c5cd0bc3073 Mon Sep 17 00:00:00 2001 From: Lawrence Qiu Date: Wed, 2 Sep 2026 18:03:15 +0000 Subject: [PATCH 08/25] docs: address review comments on PQC user guide - Add Wikipedia link to Shor's algorithm. - Remove conversational introductory phrasing in threat section. - Frame hybrid key exchange as an example rather than a standard. - Remove redundant audience phrasing and generalize endpoint references. - Remove gRPC transport scope section to keep guide focused on HTTP/JSON. - Add OpenJDK link to JEP 496. - Align default named groups list with DEFAULT_CONSCRYPT_NAMED_GROUPS in gax-httpjson. - Clarify fallback to configured security provider (defaulting to standard JDK JSSE). - Moderate latency assertions and encourage user benchmarking. - Remove unsubstantiated CPU benchmark assertions. - Neutralize Alpine Linux options and suggest alternative security providers like Bouncy Castle. - Clean up custom configuration options to only include actionable alternative setups. --- docs/post_quantum_cryptography_guide.md | 155 ++++++++---------------- 1 file changed, 49 insertions(+), 106 deletions(-) diff --git a/docs/post_quantum_cryptography_guide.md b/docs/post_quantum_cryptography_guide.md index e8f9d52d77ca..0fffda27d8b5 100644 --- a/docs/post_quantum_cryptography_guide.md +++ b/docs/post_quantum_cryptography_guide.md @@ -5,16 +5,16 @@ ### 1.1 What is Post-Quantum Cryptography (PQC)? Traditional Transport Layer Security (TLS) public-key cryptography—such as RSA and Elliptic Curve Diffie-Hellman (ECDH)—relies on mathematical problems (integer factorization and discrete logarithms) that are practically impossible for classical computers to solve in a reasonable timeframe. -However, sufficiently large, cryptographically relevant quantum computers (CRQCs) will be capable of breaking these mathematical foundations using Shor's algorithm. **Post-Quantum Cryptography (PQC)** refers to a new class of cryptographic algorithms designed to run on classical hardware while remaining mathematically secure against attacks from both classical and quantum computers. +However, sufficiently large, cryptographically relevant quantum computers (CRQCs) will be capable of breaking these mathematical foundations using [Shor's algorithm](https://en.wikipedia.org/wiki/Shor%27s_algorithm). **Post-Quantum Cryptography (PQC)** refers to a new class of cryptographic algorithms designed to run on classical hardware while remaining mathematically secure against attacks from both classical and quantum computers. ### 1.2 The Threat: "Store-Now, Decrypt-Later" (SNDL) -You might wonder why post-quantum security matters today if large-scale quantum computers do not yet exist. The primary threat is **Store-Now, Decrypt-Later (SNDL)**: +The primary threat addressed by PQC today is **Store-Now, Decrypt-Later (SNDL)**: - **The Attack**: Adversaries can intercept and archive encrypted network communications traversing the public internet today. -- **The Consequence**: Even if attackers cannot read your ciphertext now, they can store the encrypted traffic indefinitely and decrypt it in the future once quantum computers become available. +- **The Consequence**: Even if attackers cannot read ciphertext now, they can store the encrypted traffic indefinitely and decrypt it in the future once quantum computers become available. - **The Impact**: Any data with a long secrecy lifecycle—such as customer records, credentials, intellectual property, health information, and financial transactions—is vulnerable to retroactive exposure unless protected before transmission. ### 1.3 The Solution: Hybrid Key Exchange -Rather than completely replacing proven classical algorithms with brand-new post-quantum mechanisms, Google Cloud and standards bodies (NIST) utilize **Hybrid Key Exchange** (specifically `X25519MLKEM768`): +Rather than completely replacing proven classical algorithms with brand-new post-quantum mechanisms, client libraries can utilize **Hybrid Key Exchange** (e.g., combining classical ECDH with post-quantum algorithms such as `X25519MLKEM768`): > [!TIP] > **The Two-Lock Analogy**: @@ -27,32 +27,20 @@ Rather than completely replacing proven classical algorithms with brand-new post > - If a quantum computer breaks the classical algorithm, the post-quantum algorithm still maintains security. ### 1.4 What Changes vs. What Stays the Same? -For software engineers and application developers, adopting PQC in Google Cloud Java client libraries requires no changes to business logic: +Adopting PQC in Google Cloud Java client libraries requires no changes to business logic: - **What stays exactly the same**: - Your application source code and business logic. - How you construct and call API clients (e.g., `SecretManagerServiceClient`, `StorageClient`). - Authentication tokens, Service Account keys, and OAuth2 credentials. - Request and response JSON payloads. - **What changes**: - - Only the initial **TLS 1.3 cryptographic handshake** (Layer 4/6) performed when the client opens an HTTPS connection to Google Cloud endpoints (`*.googleapis.com`). + - Only the initial **TLS 1.3 cryptographic handshake** (Layer 4/6) performed when the client opens an HTTPS connection to Google Cloud service endpoints. --- -## 2. Transport Scope: HTTP/JSON (REST) vs. gRPC +## 2. HTTP/JSON Transport Architecture & Defaults -Google Cloud Java client libraries support two underlying transport mechanisms: **gRPC** (HTTP/2 with Protobuf) and **HTTP/JSON** (REST with JSON): -- Most Google Cloud Java clients use **gRPC by default** (e.g., Cloud Bigtable, Cloud Spanner, Cloud Pub/Sub). -- Clients use **HTTP/JSON** when explicitly configured (e.g., via `ClientSettings.newHttpJsonBuilder()`), when interacting with HTTP-only services (e.g., Google Cloud Compute Engine, Cloud Storage JSON API), or in corporate networks where firewalls restrict non-standard HTTP/2 gRPC traffic. - -> [!NOTE] -> **Scope of This Guide**: -> This guide focuses exclusively on **HTTP/JSON (REST)** transport (`gax-httpjson` and `google-http-client`). gRPC transport manages its TLS lifecycle independently via `grpc-netty-shaded` and will be covered in a subsequent guide. - ---- - -## 3. HTTP/JSON Transport Architecture & Defaults - -### 3.1 Minimum Required Versions +### 2.1 Minimum Required Versions PQC enablement for HTTP/JSON transport requires compatible versions of `conscrypt-openjdk-uber`, `gax-httpjson`, and `google-http-client`: | Library | Minimum Version | Role | @@ -62,30 +50,27 @@ PQC enablement for HTTP/JSON transport requires compatible versions of `conscryp | **`google-http-client`** | `2.2.0+` | Provides transport-level security provider registration on `NetHttpTransport.Builder`. | | **`conscrypt-openjdk-uber`** | `2.6.0+` *(2.6.2+ recommended)* | Provides Google's BoringSSL native C engine and TLS 1.3 PQC hybrid named groups. | -### 3.2 Why Conscrypt? -Built-in Java Development Kits (Java 8 through Java 20) do not support Post-Quantum Cryptography in their default Java Secure Socket Extension provider (`SunJSSE`). While native ML-KEM support is in development for future Java releases (**JDK 27+** via JEP 496), requiring all production enterprise workloads to immediately upgrade to bleeding-edge JDK versions is impractical. +### 2.2 Why Conscrypt? +Built-in Java Development Kits (Java 8 through Java 20) do not support Post-Quantum Cryptography in their default Java Secure Socket Extension provider (`SunJSSE`). While native ML-KEM support is in development for future Java releases (**JDK 27+** via [JEP 496](https://openjdk.org/jeps/496)), requiring all production enterprise workloads to immediately upgrade to bleeding-edge JDK versions is impractical. To bridge this gap, Google Cloud Java client libraries use **Conscrypt** (`conscrypt-openjdk-uber`) as the default security provider for HTTP/JSON transport: 1. **Immediate PQC Availability Across Java 8+**: Conscrypt embeds Google's open-source BoringSSL cryptographic engine via Java Native Interface (JNI). This enables quantum-resistant TLS 1.3 handshakes on existing production runtimes (Java 8, 11, 17, and 21). 2. **Zero Code Changes**: When `gax-httpjson` detects compatible Conscrypt libraries on the classpath, it automatically configures the HTTPS transport without requiring manual SSLContext setup. 3. **High Performance**: BoringSSL contains hardware-accelerated assembly optimizations for modern CPU architectures (x86_64 and ARM64). -### 3.3 How Client and Google Cloud Endpoints Negotiate PQC +### 2.3 How Client and Google Cloud Endpoints Negotiate PQC When a Google Cloud HTTP/JSON client initiates a connection, it advertises supported key exchange groups to the server in strict preference order: -1. `X25519MLKEM768` *(#1 Preference: Hybrid Post-Quantum Key Exchange)* -2. `SecP256r1MLKEM768` *(Hybrid Post-Quantum Key Exchange with NIST P-256)* -3. `MLKEM1024` *(Pure Post-Quantum Key Exchange)* -4. `MLKEM768` *(Pure Post-Quantum Key Exchange)* -5. `X25519Kyber768Draft00` *(Deprecated draft group retained for backward compatibility)* -6. `X25519` *(Classical ECDH)* -7. `secp256r1` *(Classical ECDH)* -8. `secp384r1` *(Classical ECDH)* +1. `X25519MLKEM768` *(Hybrid Post-Quantum Key Exchange)* +2. `MLKEM1024` *(Pure Post-Quantum Key Exchange)* +3. `X25519` *(Classical ECDH)* +4. `secp256r1` *(Classical ECDH)* +5. `secp384r1` *(Classical ECDH)* #### Handshake Negotiation Flow: - **PQC-Enabled Google Cloud Endpoints**: Google Cloud frontends recognize `X25519MLKEM768` as their preferred group. The client and server agree on this hybrid algorithm, establishing a quantum-resistant TLS 1.3 session. -- **Non-PQC Endpoints / Middleboxes**: If a server or intermediate network proxy does not yet support post-quantum cryptography, it ignores the unrecognized post-quantum identifiers and selects the first mutually supported classical group (e.g., `X25519`). -- **Graceful Client Fallback**: If Conscrypt native libraries cannot load on the client host, the client seamlessly falls back to standard JDK JSSE (`SunJSSE`), negotiating classical TLS 1.3. +- **Non-PQC Endpoints / Middleboxes**: If a server or intermediate network proxy does not support post-quantum cryptography, it ignores the unrecognized post-quantum identifiers and selects the first mutually supported classical group (e.g., `X25519`). +- **Graceful Client Fallback**: If Conscrypt native libraries cannot load on the client host, the client seamlessly falls back to the environment's configured security provider (which defaults to standard JDK JSSE / `SunJSSE`), negotiating classical TLS 1.3. ``` +-------------------------------------------------------------------------------+ @@ -99,13 +84,13 @@ When a Google Cloud HTTP/JSON client initiates a connection, it advertises suppo [ YES ] [ NO ] | | v v - google-http-client uses Conscrypt Falls back to JDK JSSE - Offers Hybrid PQC + Classical Groups Offers Standard JDK Classical Groups + google-http-client uses Conscrypt Falls back to configured + Offers Hybrid PQC + Classical Groups security provider (JDK JSSE) - Google Cloud negotiates X25519MLKEM768 - Negotiates classical X25519 - Non-PQC endpoints fall back to X25519 via standard JDK SunJSSE ``` -### 3.4 Performance, Network, & Handshake Characteristics +### 2.4 Performance & Network Considerations Understanding the real-world performance implications helps teams make informed deployment decisions: - **TLS Handshake Size Overhead**: - Classical `X25519` public keys are very compact: **32 bytes**. @@ -114,17 +99,15 @@ Understanding the real-world performance implications helps teams make informed - **Connection Pooling & API Latency**: - Google Cloud Java client libraries maintain persistent HTTP connection pools (`Keep-Alive`). - The TLS handshake occurs **only once** when a pooled connection is established. - - Subsequent API requests reuse existing open connections without repeating the TLS handshake. Therefore, the runtime latency impact on everyday API requests is **negligible**. -- **CPU Computation**: - - Modern CPUs execute ML-KEM key generation and encapsulation in under 50 microseconds. In benchmark testing, CPU utilization differences between classical and hybrid handshakes are within normal margin of error. + - Subsequent API requests reuse existing open connections without repeating the TLS handshake. While the runtime latency impact should feel negligible in most environments, you should benchmark and evaluate whether this holds true for your specific application's latency and connection churn profile. --- -## 4. Deployment Environments & Platform Compatibility +## 3. Deployment Environments & Platform Compatibility Because Conscrypt relies on C native shared libraries (`.so`, `.dylib`, or `.dll`) loaded via JNI, platform compatibility depends on the host operating system and container environment. -### 4.1 Compatibility Matrix +### 3.1 Compatibility Matrix | Environment / OS | Status | Notes | | :--- | :--- | :--- | @@ -132,20 +115,18 @@ Because Conscrypt relies on C native shared libraries (`.so`, `.dylib`, or `.dll | **Google Cloud Managed (Cloud Run, GKE, App Engine)** | **Fully Supported** | Default base container environments use compatible `glibc` runtimes. | | **macOS (Apple Silicon M-series & Intel)** | **Fully Supported** | Native `osx-aarch_64` and `osx-x86_64` binaries bundled in `conscrypt-openjdk-uber`. | | **Windows (x86_64)** | **Fully Supported** | Native `windows-x86_64` binary bundled in `conscrypt-openjdk-uber`. | -| **Alpine Linux / Musl libc Containers** | **Fallback to Classical** | Conscrypt native binaries are compiled for `glibc`. On Alpine (`musl`), native loading fails with `UnsatisfiedLinkError` and gracefully falls back to JDK TLS. | +| **Alpine Linux / Musl libc Containers** | **Fallback to Classical** | Conscrypt native binaries are compiled for `glibc`. On Alpine (`musl`), native loading fails with `UnsatisfiedLinkError` and gracefully falls back to the configured security provider (default JDK TLS). | | **Containers with `noexec /tmp`** | **Requires Configuration** | By default, JNI extracts libraries to `/tmp`. If `/tmp` is mounted `noexec`, specify `-Dorg.conscrypt.native.workdir`. | -### 4.2 Handling Alpine Linux (`musl` libc) +### 3.2 Handling Alpine Linux (`musl` libc) If your container images are based on Alpine Linux (e.g., `eclipse-temurin:17-alpine` or `openjdk:11-alpine`), Conscrypt cannot load its native C library because Alpine uses `musl` libc instead of `glibc`. **Your Options on Alpine**: -1. **Accept Classical TLS Fallback (No Action)**: The client library will safely fall back to standard JDK JSSE and negotiate classical TLS 1.3 (`X25519`). Your application will function normally without errors. -2. **Switch to a Glibc-Based Base Image (Recommended for PQC)**: If quantum resistance is required in containerized environments, switch to a minimal `glibc`-based base image such as: - - Debian Slim (e.g., `eclipse-temurin:17-jre-jammy` or `eclipse-temurin:21-jre-noble`) - - Distroless Java (e.g., `gcr.io/distroless/java17-debian12`) - - Chainguard JRE with glibc +1. **Accept Classical TLS Fallback**: The client library will safely fall back to the configured security provider (by default standard JDK JSSE) and negotiate classical TLS 1.3 (`X25519`). Your application will function normally without errors. +2. **Use a Glibc-Based Container Image**: If quantum resistance via Conscrypt is desired, use a base container image that provides `glibc`. +3. **Configure an Alternative Security Provider**: Use an alternative security provider that supports your environment (such as Bouncy Castle; see **Section 6**). -### 4.3 Handling Hardened Filesystems & `noexec /tmp` +### 3.3 Handling Hardened Filesystems & `noexec /tmp` In hardened Kubernetes pods or security-conscious Docker containers, `/tmp` may be mounted with the `noexec` flag or the entire root filesystem may be marked read-only. When Conscrypt starts, the JVM extracts its bundled native `.so` file to a temporary directory. If that directory does not allow execution: @@ -157,42 +138,42 @@ java.lang.UnsatisfiedLinkError: /tmp/libconscrypt_openjdk_jni...: failed to map java -Dorg.conscrypt.native.workdir=/var/run/app/tmp -jar my-application.jar ``` -### 4.4 Classpath Isolation & Version Skew Warning +### 3.4 Classpath Isolation & Version Skew Warning If your project uses multiple dependencies that transitively pull in different versions of Conscrypt (e.g., older versions like `2.5.2` alongside `2.6.2`), a JNI ABI mismatch can occur during JVM classloading. Always ensure your build tool (Maven/Gradle) resolves `conscrypt-openjdk-uber` to version `2.6.0+` (or `2.6.2+`) consistently. --- -## 5. Important Warning: Availability vs. Strict Compliance +## 4. Important Warning: Availability vs. Strict Compliance Google Cloud Java client libraries follow a deliberate architectural principle: **prefer service availability over hard failures**. -### 5.1 The Silent Fallback Behavior +### 4.1 The Silent Fallback Behavior If Conscrypt native libraries fail to initialize—due to an unsupported operating system, missing `glibc`, permission issues, or file extraction limits—`gax-httpjson` catches the exception and logs a message at **`Level.FINE` (debug level)**: ```text FINE: Conscrypt native libraries not available. Falling back to JDK TLS. ``` -The client then proceeds to establish standard classical TLS using the host JVM's built-in `SunJSSE` provider. +The client then proceeds to establish standard classical TLS using the host JVM's configured security provider (by default `SunJSSE`). **Why does it behave this way?** To protect production workloads. A customer updating dependencies or migrating container images should not experience broken API calls or catastrophic application outages simply because a native optimization library could not load on their environment. -### 5.2 The Compliance Warning +### 4.2 The Compliance Warning > [!WARNING] > **Active Verification is Required for Regulatory Mandates**: > If your organization operates under strict compliance, governmental, or corporate security mandates requiring Post-Quantum Cryptography today, **you cannot rely solely on the default configuration without verification**. > > Because fallback to classical TLS is silent and non-breaking by design, an unexpected environment change (such as switching to an Alpine-based Docker container or changing filesystem mount permissions) could downgrade your connections from hybrid PQC to classical TLS **without throwing exceptions or failing requests**. > -> If PQC is a mandatory requirement for your workload, you must implement automated verification in your CI/CD pipelines or startup health checks (see **Section 6**). +> If PQC is a mandatory requirement for your workload, you must implement automated verification in your CI/CD pipelines or startup health checks (see **Section 5**). --- -## 6. How to Verify PQC Negotiation +## 5. How to Verify PQC Negotiation To confirm whether your application is actively negotiating post-quantum hybrid key exchange, use one or more of the following verification methods. -### Method 1: GAX Internal Initialization Logging -Inspect whether `gax-httpjson` successfully loaded Conscrypt or fell back to JDK TLS by enabling debug logging on `HttpJsonConscryptUtils`. +### 5.1 Method 1: GAX Internal Initialization Logging +Inspect whether `gax-httpjson` successfully loaded Conscrypt or fell back to the default security provider by enabling debug logging on `HttpJsonConscryptUtils`. In your `logging.properties` file: ```properties @@ -215,7 +196,7 @@ Logger.getLogger("com.google.api.gax.httpjson.HttpJsonConscryptUtils").setLevel( FINE: Conscrypt initialization failed with exception: java.lang.UnsatisfiedLinkError: ... ``` -### Method 2: JVM TLS Handshake Tracing (`-Djavax.net.debug`) +### 5.2 Method 2: JVM TLS Handshake Tracing (`-Djavax.net.debug`) To inspect the actual cryptographic parameters negotiated during the TLS 1.3 handshake with Google Cloud servers, start your Java application with the standard JSSE debug flag: ```bash @@ -229,7 +210,7 @@ Look for the following entries in standard error during the initial HTTPS connec ```text Extension supported_groups (10): [ NamedGroup: X25519MLKEM768 (0x11ec), - NamedGroup: SecP256r1MLKEM768 (0x11ed), + NamedGroup: MLKEM1024 (0x0202), NamedGroup: x25519 (0x001d), NamedGroup: secp256r1 (0x0017) ] @@ -249,22 +230,11 @@ If the negotiated group displays `X25519MLKEM768` (or `0x11ec`), your connection --- -## 7. Alternative Configurations & Custom Providers - -Google Cloud client libraries are designed to be flexible. You are not locked into Conscrypt; you can configure classical-only key exchange, standard JDK TLS, or custom security providers. - -### Option A: Default Out-of-the-Box (Conscrypt Automatic PQC) -No code required. If you import `libraries-bom:26.86.0+` on a compatible platform, PQC is enabled automatically: -```java -// Standard client construction automatically leverages Conscrypt PQC -try (SecretManagerServiceClient client = SecretManagerServiceClient.create()) { - // Transport negotiates X25519MLKEM768 -} -``` +## 6. Custom & Alternative Configurations ---- +By default, client libraries automatically use Conscrypt when available on compatible platforms without requiring custom code. If you need to customize transport behavior or security providers, you can configure the transport directly: -### Option B: Forcing Classical-Only Key Exchange (Disabling PQC) +### Option 1: Forcing Classical-Only Key Exchange (Disabling PQC) If you need to use Conscrypt for high-performance TLS but want to explicitly disable post-quantum hybrid groups (for example, to isolate a network middlebox issue or benchmark legacy performance): ```java @@ -310,7 +280,7 @@ try (SecretManagerServiceClient client = SecretManagerServiceClient.create(setti --- -### Option C: Bypassing Conscrypt to Use Standard JDK JSSE +### Option 2: Bypassing Conscrypt to Use Standard JDK JSSE If your deployment environment prohibits native JNI libraries or you prefer using the JVM's built-in cryptographic engine (`SunJSSE`): ```java @@ -341,35 +311,8 @@ try (SecretManagerServiceClient client = SecretManagerServiceClient.create(setti --- -### Option D: Completely Excluding Conscrypt via Maven or Gradle -If you want to ensure that Conscrypt is never pulled onto your classpath (and never loaded by any client in your application), exclude it in your build configuration: - -**Maven (`pom.xml`)**: -```xml - - com.google.cloud - google-cloud-secretmanager - - - org.conscrypt - conscrypt-openjdk-uber - - - -``` - -**Gradle (`build.gradle`)**: -```groovy -configurations.all { - exclude group: 'org.conscrypt', module: 'conscrypt-openjdk-uber' -} -``` -When Conscrypt is not present on the classpath, `gax-httpjson` detects its absence and automatically uses standard JDK JSSE. - ---- - -### Option E: Configuring a Third-Party Security Provider (e.g., Bouncy Castle) -If your enterprise utilizes an alternative cryptographic provider (such as Bouncy Castle FIPS), configure it directly on the `NetHttpTransport.Builder`: +### Option 3: Configuring a Third-Party Security Provider (e.g., Bouncy Castle) +If your enterprise utilizes an alternative cryptographic provider (such as Bouncy Castle), configure it directly on the `NetHttpTransport.Builder`: ```java import com.google.api.client.http.javanet.NetHttpTransport; @@ -410,9 +353,9 @@ try (SecretManagerServiceClient client = SecretManagerServiceClient.create(setti --- -## 8. Future Outlook: Native OpenJDK PQC Support (JDK 27+) +## 7. Future Outlook: Native OpenJDK PQC Support (JDK 27+) The cryptographic landscape is continually advancing. The OpenJDK community is integrating standardized post-quantum algorithms directly into the Java platform: -- **JEP 496 (ML-KEM)**: Introduces native implementations of NIST FIPS 203 (Module-Lattice-Based Key-Encapsulation Mechanism) into OpenJDK's standard security providers (`SunJSSE` and `SunJCE`), targeted for **JDK 27+**. +- **[JEP 496](https://openjdk.org/jeps/496) (ML-KEM)**: Introduces native implementations of NIST FIPS 203 (Module-Lattice-Based Key-Encapsulation Mechanism) into OpenJDK's standard security providers (`SunJSSE` and `SunJCE`), targeted for **JDK 27+**. - **What this means for Google Cloud Java**: Once JDK 27 becomes standard in production environments, Java applications will be capable of negotiating hybrid and pure post-quantum TLS natively without requiring JNI shared libraries or third-party dependencies like Conscrypt. - **Future-Proofing**: As native JDK capabilities mature, Google Cloud Java client libraries will adapt to take advantage of built-in JVM providers, preserving a seamless, zero-maintenance security upgrade path for all users. From 5d562670d63382381f1169a2562c79a0749523fe Mon Sep 17 00:00:00 2001 From: Lawrence Qiu Date: Wed, 2 Sep 2026 18:14:38 +0000 Subject: [PATCH 09/25] docs: address additional review feedback on PQC user guide --- docs/post_quantum_cryptography_guide.md | 25 ++++++++++++++++++------- 1 file changed, 18 insertions(+), 7 deletions(-) diff --git a/docs/post_quantum_cryptography_guide.md b/docs/post_quantum_cryptography_guide.md index 0fffda27d8b5..e9add6578f72 100644 --- a/docs/post_quantum_cryptography_guide.md +++ b/docs/post_quantum_cryptography_guide.md @@ -34,7 +34,7 @@ Adopting PQC in Google Cloud Java client libraries requires no changes to busine - Authentication tokens, Service Account keys, and OAuth2 credentials. - Request and response JSON payloads. - **What changes**: - - Only the initial **TLS 1.3 cryptographic handshake** (Layer 4/6) performed when the client opens an HTTPS connection to Google Cloud service endpoints. + - Only the initial **TLS 1.3 cryptographic handshake** (Layer 4/6) performed when the client opens an HTTPS connection to Google Cloud service endpoints. By default, this under-the-hood improvement is completely seamless and requires **zero application code changes**. --- @@ -51,14 +51,20 @@ PQC enablement for HTTP/JSON transport requires compatible versions of `conscryp | **`conscrypt-openjdk-uber`** | `2.6.0+` *(2.6.2+ recommended)* | Provides Google's BoringSSL native C engine and TLS 1.3 PQC hybrid named groups. | ### 2.2 Why Conscrypt? -Built-in Java Development Kits (Java 8 through Java 20) do not support Post-Quantum Cryptography in their default Java Secure Socket Extension provider (`SunJSSE`). While native ML-KEM support is in development for future Java releases (**JDK 27+** via [JEP 496](https://openjdk.org/jeps/496)), requiring all production enterprise workloads to immediately upgrade to bleeding-edge JDK versions is impractical. +Built-in Java Development Kits (Java 8 through Java 26) do not support Post-Quantum Cryptography in their default Java Secure Socket Extension provider (`SunJSSE`). While native ML-KEM support is in development for future Java releases (**JDK 27+** via [JEP 496](https://openjdk.org/jeps/496)), requiring all production enterprise workloads to immediately upgrade to bleeding-edge JDK versions is impractical. To bridge this gap, Google Cloud Java client libraries use **Conscrypt** (`conscrypt-openjdk-uber`) as the default security provider for HTTP/JSON transport: 1. **Immediate PQC Availability Across Java 8+**: Conscrypt embeds Google's open-source BoringSSL cryptographic engine via Java Native Interface (JNI). This enables quantum-resistant TLS 1.3 handshakes on existing production runtimes (Java 8, 11, 17, and 21). 2. **Zero Code Changes**: When `gax-httpjson` detects compatible Conscrypt libraries on the classpath, it automatically configures the HTTPS transport without requiring manual SSLContext setup. 3. **High Performance**: BoringSSL contains hardware-accelerated assembly optimizations for modern CPU architectures (x86_64 and ARM64). -### 2.3 How Client and Google Cloud Endpoints Negotiate PQC +### 2.3 Scoped Security Provider (No Global JVM Impact) +A deliberate architectural decision in Google Cloud Java client libraries is that **Conscrypt is scoped strictly to Google Cloud Java SDK requests**: + +- `gax-httpjson` configures the Conscrypt `Provider` instance directly on the client's internal `NetHttpTransport.Builder` rather than installing it into the global JVM security registry (`java.security.Security.addProvider(...)`). +- As a result, enabling Conscrypt for Google Cloud calls **does not alter the TLS behavior, cipher suites, or security providers of any other HTTP clients or libraries** in your application (e.g., Apache HttpClient, Spring WebClient, OkHttp, or direct `HttpsURLConnection` calls). Your existing JVM-wide cryptographic configurations remain completely undisturbed. + +### 2.4 How Client and Google Cloud Endpoints Negotiate PQC When a Google Cloud HTTP/JSON client initiates a connection, it advertises supported key exchange groups to the server in strict preference order: 1. `X25519MLKEM768` *(Hybrid Post-Quantum Key Exchange)* @@ -67,6 +73,10 @@ When a Google Cloud HTTP/JSON client initiates a connection, it advertises suppo 4. `secp256r1` *(Classical ECDH)* 5. `secp384r1` *(Classical ECDH)* +> [!NOTE] +> **Algorithm Selection**: +> These named groups are selected because they are supported by Conscrypt (see [Conscrypt CAPABILITIES.md](https://github.com/google/conscrypt/blob/2.6.2/CAPABILITIES.md) and `HttpJsonConscryptUtils.DEFAULT_CONSCRYPT_NAMED_GROUPS`). If your application requires a cryptographic algorithm or named group not in this list, you can configure an alternative `SecurityProvider` (e.g., Bouncy Castle; see **Section 6, Option 3**). + #### Handshake Negotiation Flow: - **PQC-Enabled Google Cloud Endpoints**: Google Cloud frontends recognize `X25519MLKEM768` as their preferred group. The client and server agree on this hybrid algorithm, establishing a quantum-resistant TLS 1.3 session. - **Non-PQC Endpoints / Middleboxes**: If a server or intermediate network proxy does not support post-quantum cryptography, it ignores the unrecognized post-quantum identifiers and selects the first mutually supported classical group (e.g., `X25519`). @@ -90,7 +100,7 @@ When a Google Cloud HTTP/JSON client initiates a connection, it advertises suppo - Non-PQC endpoints fall back to X25519 via standard JDK SunJSSE ``` -### 2.4 Performance & Network Considerations +### 2.5 Performance & Network Considerations Understanding the real-world performance implications helps teams make informed deployment decisions: - **TLS Handshake Size Overhead**: - Classical `X25519` public keys are very compact: **32 bytes**. @@ -111,20 +121,21 @@ Because Conscrypt relies on C native shared libraries (`.so`, `.dylib`, or `.dll | Environment / OS | Status | Notes | | :--- | :--- | :--- | -| **Standard Linux (Ubuntu, Debian, RHEL, CentOS)** | **Fully Supported** | Requires `glibc` 2.17+ (Conscrypt 2.6.2+) or `glibc` 2.35+ (Conscrypt 2.6.0). | +| **Standard Linux (e.g., Ubuntu, Debian, RHEL, CentOS — non-exhaustive)** | **Fully Supported** | Requires `glibc` 2.17+ (Conscrypt 2.6.2+) or `glibc` 2.35+ (Conscrypt 2.6.0). | | **Google Cloud Managed (Cloud Run, GKE, App Engine)** | **Fully Supported** | Default base container environments use compatible `glibc` runtimes. | | **macOS (Apple Silicon M-series & Intel)** | **Fully Supported** | Native `osx-aarch_64` and `osx-x86_64` binaries bundled in `conscrypt-openjdk-uber`. | | **Windows (x86_64)** | **Fully Supported** | Native `windows-x86_64` binary bundled in `conscrypt-openjdk-uber`. | +| **GraalVM Native Image** | **Supported** | Supported when including appropriate reachability metadata and configuration for Conscrypt JNI libraries. | | **Alpine Linux / Musl libc Containers** | **Fallback to Classical** | Conscrypt native binaries are compiled for `glibc`. On Alpine (`musl`), native loading fails with `UnsatisfiedLinkError` and gracefully falls back to the configured security provider (default JDK TLS). | | **Containers with `noexec /tmp`** | **Requires Configuration** | By default, JNI extracts libraries to `/tmp`. If `/tmp` is mounted `noexec`, specify `-Dorg.conscrypt.native.workdir`. | ### 3.2 Handling Alpine Linux (`musl` libc) If your container images are based on Alpine Linux (e.g., `eclipse-temurin:17-alpine` or `openjdk:11-alpine`), Conscrypt cannot load its native C library because Alpine uses `musl` libc instead of `glibc`. -**Your Options on Alpine**: +**Some Possible Options on Alpine**: 1. **Accept Classical TLS Fallback**: The client library will safely fall back to the configured security provider (by default standard JDK JSSE) and negotiate classical TLS 1.3 (`X25519`). Your application will function normally without errors. 2. **Use a Glibc-Based Container Image**: If quantum resistance via Conscrypt is desired, use a base container image that provides `glibc`. -3. **Configure an Alternative Security Provider**: Use an alternative security provider that supports your environment (such as Bouncy Castle; see **Section 6**). +3. **Configure an Alternative Security Provider**: Use an alternative security provider that supports your environment (such as Bouncy Castle; see **Section 6, Option 3**). ### 3.3 Handling Hardened Filesystems & `noexec /tmp` In hardened Kubernetes pods or security-conscious Docker containers, `/tmp` may be mounted with the `noexec` flag or the entire root filesystem may be marked read-only. From 4615c3e62ac26f5de8b97ba5d621f839e0ea23cb Mon Sep 17 00:00:00 2001 From: Lawrence Qiu Date: Wed, 2 Sep 2026 18:25:48 +0000 Subject: [PATCH 10/25] docs: refine PQC user guide based on review comments --- docs/post_quantum_cryptography_guide.md | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/docs/post_quantum_cryptography_guide.md b/docs/post_quantum_cryptography_guide.md index e9add6578f72..4443bc61ed3b 100644 --- a/docs/post_quantum_cryptography_guide.md +++ b/docs/post_quantum_cryptography_guide.md @@ -13,7 +13,7 @@ The primary threat addressed by PQC today is **Store-Now, Decrypt-Later (SNDL)** - **The Consequence**: Even if attackers cannot read ciphertext now, they can store the encrypted traffic indefinitely and decrypt it in the future once quantum computers become available. - **The Impact**: Any data with a long secrecy lifecycle—such as customer records, credentials, intellectual property, health information, and financial transactions—is vulnerable to retroactive exposure unless protected before transmission. -### 1.3 The Solution: Hybrid Key Exchange +### 1.3 Addressing the Threat: Hybrid Key Exchange Rather than completely replacing proven classical algorithms with brand-new post-quantum mechanisms, client libraries can utilize **Hybrid Key Exchange** (e.g., combining classical ECDH with post-quantum algorithms such as `X25519MLKEM768`): > [!TIP] @@ -59,13 +59,13 @@ To bridge this gap, Google Cloud Java client libraries use **Conscrypt** (`consc 3. **High Performance**: BoringSSL contains hardware-accelerated assembly optimizations for modern CPU architectures (x86_64 and ARM64). ### 2.3 Scoped Security Provider (No Global JVM Impact) -A deliberate architectural decision in Google Cloud Java client libraries is that **Conscrypt is scoped strictly to Google Cloud Java SDK requests**: +The Google Cloud Java SDK scopes Conscrypt strictly to Google Cloud Java SDK requests: - `gax-httpjson` configures the Conscrypt `Provider` instance directly on the client's internal `NetHttpTransport.Builder` rather than installing it into the global JVM security registry (`java.security.Security.addProvider(...)`). - As a result, enabling Conscrypt for Google Cloud calls **does not alter the TLS behavior, cipher suites, or security providers of any other HTTP clients or libraries** in your application (e.g., Apache HttpClient, Spring WebClient, OkHttp, or direct `HttpsURLConnection` calls). Your existing JVM-wide cryptographic configurations remain completely undisturbed. ### 2.4 How Client and Google Cloud Endpoints Negotiate PQC -When a Google Cloud HTTP/JSON client initiates a connection, it advertises supported key exchange groups to the server in strict preference order: +When a Google Cloud HTTP/JSON client initiates a connection, it advertises supported key exchange groups to the server in preference order. During the TLS 1.3 handshake, the first mutually supported algorithm that both the client and server agree upon is selected and used for the session: 1. `X25519MLKEM768` *(Hybrid Post-Quantum Key Exchange)* 2. `MLKEM1024` *(Pure Post-Quantum Key Exchange)* @@ -81,6 +81,7 @@ When a Google Cloud HTTP/JSON client initiates a connection, it advertises suppo - **PQC-Enabled Google Cloud Endpoints**: Google Cloud frontends recognize `X25519MLKEM768` as their preferred group. The client and server agree on this hybrid algorithm, establishing a quantum-resistant TLS 1.3 session. - **Non-PQC Endpoints / Middleboxes**: If a server or intermediate network proxy does not support post-quantum cryptography, it ignores the unrecognized post-quantum identifiers and selects the first mutually supported classical group (e.g., `X25519`). - **Graceful Client Fallback**: If Conscrypt native libraries cannot load on the client host, the client seamlessly falls back to the environment's configured security provider (which defaults to standard JDK JSSE / `SunJSSE`), negotiating classical TLS 1.3. + - **Impact of Fallback**: Fallback is completely safe and non-breaking for application availability. Your API calls will continue to execute successfully without throwing errors or dropping traffic. The connection remains fully encrypted using industry-standard classical cryptography (such as `X25519` via standard JDK TLS); it simply does not include quantum-resistant hybrid key exchange for that session. ``` +-------------------------------------------------------------------------------+ @@ -106,10 +107,10 @@ Understanding the real-world performance implications helps teams make informed - Classical `X25519` public keys are very compact: **32 bytes**. - `ML-KEM-768` public keys are **1,184 bytes**, and ciphertexts are **1,088 bytes**. - Consequently, the TLS `ClientHello` and `ServerHello` messages increase by approximately **1 to 2 kilobytes**. -- **Connection Pooling & API Latency**: - - Google Cloud Java client libraries maintain persistent HTTP connection pools (`Keep-Alive`). - - The TLS handshake occurs **only once** when a pooled connection is established. - - Subsequent API requests reuse existing open connections without repeating the TLS handshake. While the runtime latency impact should feel negligible in most environments, you should benchmark and evaluate whether this holds true for your specific application's latency and connection churn profile. +- **Persistent HTTP Connections (`Keep-Alive`) & API Latency**: + - The underlying HTTP transport (`NetHttpTransport` backed by Java's `HttpURLConnection`) supports standard HTTP persistent connections (`Keep-Alive`). + - When connections are reused from Java's connection cache, the TLS handshake occurs **only once** when establishing the connection. + - Subsequent API requests routed through that active connection reuse the existing TLS session without repeating the handshake. The latency impact of the larger handshake therefore primarily applies to new connection establishment rather than every individual API call. (Note that applications experiencing high connection churn or making infrequent calls outside the keep-alive window will perform new handshakes more often.) --- @@ -127,7 +128,6 @@ Because Conscrypt relies on C native shared libraries (`.so`, `.dylib`, or `.dll | **Windows (x86_64)** | **Fully Supported** | Native `windows-x86_64` binary bundled in `conscrypt-openjdk-uber`. | | **GraalVM Native Image** | **Supported** | Supported when including appropriate reachability metadata and configuration for Conscrypt JNI libraries. | | **Alpine Linux / Musl libc Containers** | **Fallback to Classical** | Conscrypt native binaries are compiled for `glibc`. On Alpine (`musl`), native loading fails with `UnsatisfiedLinkError` and gracefully falls back to the configured security provider (default JDK TLS). | -| **Containers with `noexec /tmp`** | **Requires Configuration** | By default, JNI extracts libraries to `/tmp`. If `/tmp` is mounted `noexec`, specify `-Dorg.conscrypt.native.workdir`. | ### 3.2 Handling Alpine Linux (`musl` libc) If your container images are based on Alpine Linux (e.g., `eclipse-temurin:17-alpine` or `openjdk:11-alpine`), Conscrypt cannot load its native C library because Alpine uses `musl` libc instead of `glibc`. @@ -144,7 +144,7 @@ When Conscrypt starts, the JVM extracts its bundled native `.so` file to a tempo ```text java.lang.UnsatisfiedLinkError: /tmp/libconscrypt_openjdk_jni...: failed to map segment from shared object: Operation not permitted ``` -**Solution**: Provide an alternative directory that has write and execute permissions using the JVM system property: +**Possible Solution**: Depending on your container configuration and security constraints, one possible solution is to provide an alternative directory that has write and execute permissions using the JVM system property: ```bash java -Dorg.conscrypt.native.workdir=/var/run/app/tmp -jar my-application.jar ``` @@ -168,6 +168,11 @@ The client then proceeds to establish standard classical TLS using the host JVM' **Why does it behave this way?** To protect production workloads. A customer updating dependencies or migrating container images should not experience broken API calls or catastrophic application outages simply because a native optimization library could not load on their environment. +**What fallback means for your application**: +- **Application Availability**: Requests continue to succeed normally. No exceptions or errors are raised to application code. +- **Security Baseline**: Traffic remains fully encrypted with classical TLS 1.3 (e.g., ECDHE with AES-GCM), maintaining the standard security posture that Java applications use today. +- **What is absent**: The connection will not be protected against future post-quantum decryption (SNDL). + ### 4.2 The Compliance Warning > [!WARNING] > **Active Verification is Required for Regulatory Mandates**: From 7a238369f77cf06a2c45a66cc72e870d5bc4fbbc Mon Sep 17 00:00:00 2001 From: Lawrence Qiu Date: Wed, 2 Sep 2026 18:31:08 +0000 Subject: [PATCH 11/25] docs: address review comments on PQC user guide --- docs/post_quantum_cryptography_guide.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/docs/post_quantum_cryptography_guide.md b/docs/post_quantum_cryptography_guide.md index 4443bc61ed3b..348c0ec48705 100644 --- a/docs/post_quantum_cryptography_guide.md +++ b/docs/post_quantum_cryptography_guide.md @@ -54,7 +54,7 @@ PQC enablement for HTTP/JSON transport requires compatible versions of `conscryp Built-in Java Development Kits (Java 8 through Java 26) do not support Post-Quantum Cryptography in their default Java Secure Socket Extension provider (`SunJSSE`). While native ML-KEM support is in development for future Java releases (**JDK 27+** via [JEP 496](https://openjdk.org/jeps/496)), requiring all production enterprise workloads to immediately upgrade to bleeding-edge JDK versions is impractical. To bridge this gap, Google Cloud Java client libraries use **Conscrypt** (`conscrypt-openjdk-uber`) as the default security provider for HTTP/JSON transport: -1. **Immediate PQC Availability Across Java 8+**: Conscrypt embeds Google's open-source BoringSSL cryptographic engine via Java Native Interface (JNI). This enables quantum-resistant TLS 1.3 handshakes on existing production runtimes (Java 8, 11, 17, and 21). +1. **Immediate PQC Availability Across Java 8+**: Conscrypt embeds Google's open-source BoringSSL cryptographic engine via Java Native Interface (JNI). This enables quantum-resistant TLS 1.3 handshakes on existing production runtimes (Java 8, 11, 17, 21, and 25). 2. **Zero Code Changes**: When `gax-httpjson` detects compatible Conscrypt libraries on the classpath, it automatically configures the HTTPS transport without requiring manual SSLContext setup. 3. **High Performance**: BoringSSL contains hardware-accelerated assembly optimizations for modern CPU architectures (x86_64 and ARM64). @@ -102,7 +102,7 @@ When a Google Cloud HTTP/JSON client initiates a connection, it advertises suppo ``` ### 2.5 Performance & Network Considerations -Understanding the real-world performance implications helps teams make informed deployment decisions: +Note the following performance and network considerations: - **TLS Handshake Size Overhead**: - Classical `X25519` public keys are very compact: **32 bytes**. - `ML-KEM-768` public keys are **1,184 bytes**, and ciphertexts are **1,088 bytes**. @@ -152,6 +152,8 @@ java -Dorg.conscrypt.native.workdir=/var/run/app/tmp -jar my-application.jar ### 3.4 Classpath Isolation & Version Skew Warning If your project uses multiple dependencies that transitively pull in different versions of Conscrypt (e.g., older versions like `2.5.2` alongside `2.6.2`), a JNI ABI mismatch can occur during JVM classloading. Always ensure your build tool (Maven/Gradle) resolves `conscrypt-openjdk-uber` to version `2.6.0+` (or `2.6.2+`) consistently. +One possible solution for this is to use Google Cloud's `libraries-bom` (version `26.86.0+`) to manage dependency versions, ensuring a consistent and compatible Conscrypt runtime across all Google Cloud client libraries. + --- ## 4. Important Warning: Availability vs. Strict Compliance From 30597ab83029b5a73229608dced80d6ffd7aaba7 Mon Sep 17 00:00:00 2001 From: Lawrence Qiu Date: Wed, 2 Sep 2026 18:38:43 +0000 Subject: [PATCH 12/25] docs: add gRPC transport architecture and verification to PQC guide --- docs/post_quantum_cryptography_guide.md | 304 +++++++++++++++++++----- 1 file changed, 245 insertions(+), 59 deletions(-) diff --git a/docs/post_quantum_cryptography_guide.md b/docs/post_quantum_cryptography_guide.md index 348c0ec48705..b04f293f8267 100644 --- a/docs/post_quantum_cryptography_guide.md +++ b/docs/post_quantum_cryptography_guide.md @@ -1,4 +1,4 @@ -# Post-Quantum Cryptography (PQC) User Guide for HTTP/JSON (REST) Java Client Libraries +# Post-Quantum Cryptography (PQC) User Guide for Google Cloud Java Client Libraries ## 1. Executive Summary & Core Concepts @@ -27,14 +27,14 @@ Rather than completely replacing proven classical algorithms with brand-new post > - If a quantum computer breaks the classical algorithm, the post-quantum algorithm still maintains security. ### 1.4 What Changes vs. What Stays the Same? -Adopting PQC in Google Cloud Java client libraries requires no changes to business logic: +Adopting PQC in Google Cloud Java client libraries requires no changes to application business logic across both **gRPC** and **HTTP/JSON** transports: - **What stays exactly the same**: - Your application source code and business logic. - How you construct and call API clients (e.g., `SecretManagerServiceClient`, `StorageClient`). - Authentication tokens, Service Account keys, and OAuth2 credentials. - - Request and response JSON payloads. + - Request and response message payloads (Protobuf or JSON). - **What changes**: - - Only the initial **TLS 1.3 cryptographic handshake** (Layer 4/6) performed when the client opens an HTTPS connection to Google Cloud service endpoints. By default, this under-the-hood improvement is completely seamless and requires **zero application code changes**. + - Only the initial **TLS 1.3 cryptographic handshake** (Layer 4/6) performed when the client establishes a secure connection to Google Cloud service endpoints. By default, this under-the-hood improvement is completely seamless and requires **zero application code changes**. --- @@ -64,7 +64,7 @@ The Google Cloud Java SDK scopes Conscrypt strictly to Google Cloud Java SDK req - `gax-httpjson` configures the Conscrypt `Provider` instance directly on the client's internal `NetHttpTransport.Builder` rather than installing it into the global JVM security registry (`java.security.Security.addProvider(...)`). - As a result, enabling Conscrypt for Google Cloud calls **does not alter the TLS behavior, cipher suites, or security providers of any other HTTP clients or libraries** in your application (e.g., Apache HttpClient, Spring WebClient, OkHttp, or direct `HttpsURLConnection` calls). Your existing JVM-wide cryptographic configurations remain completely undisturbed. -### 2.4 How Client and Google Cloud Endpoints Negotiate PQC +### 2.4 How HTTP/JSON Clients Negotiate PQC When a Google Cloud HTTP/JSON client initiates a connection, it advertises supported key exchange groups to the server in preference order. During the TLS 1.3 handshake, the first mutually supported algorithm that both the client and server agree upon is selected and used for the session: 1. `X25519MLKEM768` *(Hybrid Post-Quantum Key Exchange)* @@ -75,7 +75,7 @@ When a Google Cloud HTTP/JSON client initiates a connection, it advertises suppo > [!NOTE] > **Algorithm Selection**: -> These named groups are selected because they are supported by Conscrypt (see [Conscrypt CAPABILITIES.md](https://github.com/google/conscrypt/blob/2.6.2/CAPABILITIES.md) and `HttpJsonConscryptUtils.DEFAULT_CONSCRYPT_NAMED_GROUPS`). If your application requires a cryptographic algorithm or named group not in this list, you can configure an alternative `SecurityProvider` (e.g., Bouncy Castle; see **Section 6, Option 3**). +> These named groups are selected because they are supported by Conscrypt (see [Conscrypt CAPABILITIES.md](https://github.com/google/conscrypt/blob/2.6.2/CAPABILITIES.md) and `HttpJsonConscryptUtils.DEFAULT_CONSCRYPT_NAMED_GROUPS`). If your application requires a cryptographic algorithm or named group not in this list, you can configure an alternative `SecurityProvider` (e.g., Bouncy Castle; see **Section 8.1, Option 3**). #### Handshake Negotiation Flow: - **PQC-Enabled Google Cloud Endpoints**: Google Cloud frontends recognize `X25519MLKEM768` as their preferred group. The client and server agree on this hybrid algorithm, establishing a quantum-resistant TLS 1.3 session. @@ -101,70 +101,141 @@ When a Google Cloud HTTP/JSON client initiates a connection, it advertises suppo - Non-PQC endpoints fall back to X25519 via standard JDK SunJSSE ``` -### 2.5 Performance & Network Considerations -Note the following performance and network considerations: -- **TLS Handshake Size Overhead**: +--- + +## 3. gRPC Transport Architecture & Defaults + +### 3.1 Minimum Required Versions +PQC enablement for gRPC transport requires compatible versions of `grpc-netty-shaded` and `gax-grpc`: + +| Library | Minimum Version | Role | +| :--- | :--- | :--- | +| **`libraries-bom`** | `26.86.0+` | **Recommended**. Central BOM managing compatible versions across all Google Cloud client libraries. | +| **`gax-grpc`** | `2.83.0+` | Provides gRPC transport channel providers for Google Cloud client libraries. | +| **`grpc-netty-shaded`** | `1.83.0+` | Default gRPC transport engine. Bundles Netty and `netty-tcnative-boringssl-static` with built-in PQC hybrid key exchange support. | + +### 3.2 Why `grpc-netty-shaded`? +By default, Google Cloud Java client libraries use `grpc-netty-shaded` for gRPC transport: +1. **Bundled BoringSSL Engine**: `grpc-netty-shaded` packages a shaded version of Netty and its native OpenSSL/BoringSSL binding (`netty-tcnative-boringssl-static`). This bundles Google's BoringSSL C library directly inside the JAR. +2. **Native PQC Support Out-of-the-Box**: In `grpc-netty-shaded` version **1.83.0+**, the bundled BoringSSL engine natively supports TLS 1.3 post-quantum hybrid key exchange (`X25519MLKEM768`). +3. **Zero Configuration**: Unlike HTTP/JSON which uses Conscrypt as a pluggable `SecurityProvider`, gRPC client channels using `grpc-netty-shaded` automatically negotiate PQC hybrid key exchange without requiring any custom socket configurators, system properties, or security provider setup. + +### 3.3 How gRPC Clients Negotiate PQC +When a Google Cloud gRPC client connects to an endpoint (typically port 443 with TLS): +- **PQC-Enabled Google Cloud Endpoints (GFE)**: The client's BoringSSL engine advertises hybrid PQC algorithms in its TLS 1.3 `ClientHello`. Google Cloud frontends recognize and select `X25519MLKEM768`, establishing a quantum-resistant HTTP/2 TLS session. +- **Non-PQC Endpoints / Middleboxes**: If the endpoint or an intermediary proxy does not support PQC, it selects the first mutually supported classical algorithm (such as `X25519`). +- **Graceful Fallback**: If the bundled native BoringSSL library cannot load on the platform, gRPC safely falls back to standard Java JSSE TLS (or throws an explicit linkage error if shaded Netty native transport is strictly required). When classical TLS is negotiated, your application continues operating normally. + - **Impact of Fallback**: Fallback does not disrupt service availability. Calls continue over standard classical TLS 1.3 encryption. + +``` ++-------------------------------------------------------------------------------+ +| GAPIC gRPC Client Request | ++-------------------------------------------------------------------------------+ + | + Is grpc-netty-shaded Native BoringSSL Available? + | + +-------------------+-------------------+ + | | + [ YES ] [ NO ] + | | + v v + grpc-netty-shaded uses BoringSSL Falls back to standard + Offers Hybrid PQC (X25519MLKEM768) classical TLS (JDK JSSE) + - GFE negotiates X25519MLKEM768 - Negotiates classical X25519 + - Non-PQC endpoints fall back to X25519 via standard JDK TLS +``` + +### 3.4 gRPC Connection Architecture & Multiplexing +gRPC utilizes HTTP/2 as its underlying framing protocol: +- **Long-Lived Multiplexed Channels**: A single `ManagedChannel` maintains persistent TCP/TLS connections to Google Cloud endpoints. +- **Concurrent Stream Multiplexing**: Multiple RPCs execute concurrently over the same underlying connection without creating new TCP or TLS handshakes. +- **Handshake Frequency**: The TLS handshake happens only once when establishing the channel connection. Subsequent RPC calls share the established quantum-resistant session, resulting in zero cryptographic overhead for ongoing API traffic. + +--- + +## 4. Performance & Network Considerations + +Note the following performance and network considerations across both transports: + +### 4.1 TLS Handshake Size Overhead +- **Public Key & Ciphertext Sizes**: - Classical `X25519` public keys are very compact: **32 bytes**. - `ML-KEM-768` public keys are **1,184 bytes**, and ciphertexts are **1,088 bytes**. +- **Handshake Size**: - Consequently, the TLS `ClientHello` and `ServerHello` messages increase by approximately **1 to 2 kilobytes**. -- **Persistent HTTP Connections (`Keep-Alive`) & API Latency**: +- **Fragmentation & Middleboxes**: + - While modern networks handle handshakes of this size smoothly, rare legacy network middleboxes or firewalls with strict MTU limits or packet inspection might drop larger `ClientHello` frames. + +### 4.2 Transport Connection Characteristics & API Latency +Because both transports maintain persistent connections, the latency impact of the larger PQC handshake is limited to initial connection establishment: +- **HTTP/JSON (`Keep-Alive`)**: - The underlying HTTP transport (`NetHttpTransport` backed by Java's `HttpURLConnection`) supports standard HTTP persistent connections (`Keep-Alive`). - When connections are reused from Java's connection cache, the TLS handshake occurs **only once** when establishing the connection. - - Subsequent API requests routed through that active connection reuse the existing TLS session without repeating the handshake. The latency impact of the larger handshake therefore primarily applies to new connection establishment rather than every individual API call. (Note that applications experiencing high connection churn or making infrequent calls outside the keep-alive window will perform new handshakes more often.) + - Subsequent API requests routed through that active connection reuse the existing TLS session without repeating the handshake. (Note that applications with high connection churn or infrequent calls outside the keep-alive window will perform new handshakes more often.) +- **gRPC (HTTP/2 Multiplexing)**: + - gRPC channels maintain persistent, long-lived HTTP/2 connections. Multiple concurrent RPC requests and streaming calls are multiplexed over a single connection. + - Handshakes occur only when the `ManagedChannel` connects (or reconnects). For warm channels, the amortized latency impact of PQC on individual RPC calls is practically zero. --- -## 3. Deployment Environments & Platform Compatibility +## 5. Deployment Environments & Platform Compatibility -Because Conscrypt relies on C native shared libraries (`.so`, `.dylib`, or `.dll`) loaded via JNI, platform compatibility depends on the host operating system and container environment. +Both HTTP/JSON (via Conscrypt) and gRPC (via `grpc-netty-shaded` / `netty-tcnative`) rely on C native shared libraries (`.so`, `.dylib`, or `.dll`) loaded via JNI. Consequently, both transports share similar platform compatibility considerations. -### 3.1 Compatibility Matrix +### 5.1 Compatibility Matrix | Environment / OS | Status | Notes | | :--- | :--- | :--- | -| **Standard Linux (e.g., Ubuntu, Debian, RHEL, CentOS — non-exhaustive)** | **Fully Supported** | Requires `glibc` 2.17+ (Conscrypt 2.6.2+) or `glibc` 2.35+ (Conscrypt 2.6.0). | +| **Standard Linux (e.g., Ubuntu, Debian, RHEL, CentOS — non-exhaustive)** | **Fully Supported** | Requires `glibc` 2.17+ (Conscrypt 2.6.2+ and Netty tcnative). | | **Google Cloud Managed (Cloud Run, GKE, App Engine)** | **Fully Supported** | Default base container environments use compatible `glibc` runtimes. | -| **macOS (Apple Silicon M-series & Intel)** | **Fully Supported** | Native `osx-aarch_64` and `osx-x86_64` binaries bundled in `conscrypt-openjdk-uber`. | -| **Windows (x86_64)** | **Fully Supported** | Native `windows-x86_64` binary bundled in `conscrypt-openjdk-uber`. | -| **GraalVM Native Image** | **Supported** | Supported when including appropriate reachability metadata and configuration for Conscrypt JNI libraries. | -| **Alpine Linux / Musl libc Containers** | **Fallback to Classical** | Conscrypt native binaries are compiled for `glibc`. On Alpine (`musl`), native loading fails with `UnsatisfiedLinkError` and gracefully falls back to the configured security provider (default JDK TLS). | +| **macOS (Apple Silicon M-series & Intel)** | **Fully Supported** | Native `osx-aarch_64` and `osx-x86_64` binaries bundled in `conscrypt-openjdk-uber` and `grpc-netty-shaded`. | +| **Windows (x86_64)** | **Fully Supported** | Native `windows-x86_64` binaries bundled in `conscrypt-openjdk-uber` and `grpc-netty-shaded`. | +| **GraalVM Native Image** | **Supported** | Supported when including appropriate reachability metadata and configuration for Conscrypt or Netty JNI libraries. | +| **Alpine Linux / Musl libc Containers** | **Fallback to Classical** | Native binaries are compiled for `glibc`. On Alpine (`musl`), native library loading fails with `UnsatisfiedLinkError` and safely falls back to standard classical TLS. | -### 3.2 Handling Alpine Linux (`musl` libc) -If your container images are based on Alpine Linux (e.g., `eclipse-temurin:17-alpine` or `openjdk:11-alpine`), Conscrypt cannot load its native C library because Alpine uses `musl` libc instead of `glibc`. +### 5.2 Handling Alpine Linux (`musl` libc) +If your container images are based on Alpine Linux (e.g., `eclipse-temurin:17-alpine` or `openjdk:11-alpine`), native C libraries cannot load because Alpine uses `musl` libc instead of `glibc`. **Some Possible Options on Alpine**: -1. **Accept Classical TLS Fallback**: The client library will safely fall back to the configured security provider (by default standard JDK JSSE) and negotiate classical TLS 1.3 (`X25519`). Your application will function normally without errors. -2. **Use a Glibc-Based Container Image**: If quantum resistance via Conscrypt is desired, use a base container image that provides `glibc`. -3. **Configure an Alternative Security Provider**: Use an alternative security provider that supports your environment (such as Bouncy Castle; see **Section 6, Option 3**). +1. **Accept Classical TLS Fallback**: The client library will safely fall back to classical TLS 1.3 (`X25519`). Your application will function normally without errors. +2. **Use a Glibc-Based Container Image**: If quantum resistance via native BoringSSL is desired, use a base container image that provides `glibc` (such as Debian-, Ubuntu-, or Wolfi-based container images). +3. **Configure an Alternative Security Provider (HTTP/JSON)**: Use an alternative pure-Java security provider that supports your environment (such as Bouncy Castle; see **Section 8.1, Option 3**). -### 3.3 Handling Hardened Filesystems & `noexec /tmp` +### 5.3 Handling Hardened Filesystems & `noexec /tmp` In hardened Kubernetes pods or security-conscious Docker containers, `/tmp` may be mounted with the `noexec` flag or the entire root filesystem may be marked read-only. -When Conscrypt starts, the JVM extracts its bundled native `.so` file to a temporary directory. If that directory does not allow execution: +When native engines start, the JVM extracts bundled native `.so` files to a temporary directory. If that directory does not allow execution: ```text -java.lang.UnsatisfiedLinkError: /tmp/libconscrypt_openjdk_jni...: failed to map segment from shared object: Operation not permitted -``` -**Possible Solution**: Depending on your container configuration and security constraints, one possible solution is to provide an alternative directory that has write and execute permissions using the JVM system property: -```bash -java -Dorg.conscrypt.native.workdir=/var/run/app/tmp -jar my-application.jar +java.lang.UnsatisfiedLinkError: ... failed to map segment from shared object: Operation not permitted ``` -### 3.4 Classpath Isolation & Version Skew Warning -If your project uses multiple dependencies that transitively pull in different versions of Conscrypt (e.g., older versions like `2.5.2` alongside `2.6.2`), a JNI ABI mismatch can occur during JVM classloading. Always ensure your build tool (Maven/Gradle) resolves `conscrypt-openjdk-uber` to version `2.6.0+` (or `2.6.2+`) consistently. +**Possible Solution**: Depending on your container configuration and security constraints, one possible solution is to provide an alternative directory that has write and execute permissions using JVM system properties: +- For Conscrypt (HTTP/JSON): + ```bash + java -Dorg.conscrypt.native.workdir=/var/run/app/tmp -jar my-application.jar + ``` +- For Netty / gRPC: + ```bash + java -Dio.netty.native.workdir=/var/run/app/tmp -jar my-application.jar + ``` + +### 5.4 Classpath Isolation & Version Skew Warning +If your project uses multiple dependencies that transitively pull in different versions of Conscrypt or gRPC Netty components, JNI ABI mismatches can occur during JVM classloading. Always ensure your build tool resolves compatible versions consistently. -One possible solution for this is to use Google Cloud's `libraries-bom` (version `26.86.0+`) to manage dependency versions, ensuring a consistent and compatible Conscrypt runtime across all Google Cloud client libraries. +One possible solution for this is to use Google Cloud's `libraries-bom` (version `26.86.0+`), which centrally manages dependency versions and ensures consistent, compatible runtime dependencies across all Google Cloud client libraries. --- -## 4. Important Warning: Availability vs. Strict Compliance +## 6. Important Warning: Availability vs. Strict Compliance Google Cloud Java client libraries follow a deliberate architectural principle: **prefer service availability over hard failures**. -### 4.1 The Silent Fallback Behavior -If Conscrypt native libraries fail to initialize—due to an unsupported operating system, missing `glibc`, permission issues, or file extraction limits—`gax-httpjson` catches the exception and logs a message at **`Level.FINE` (debug level)**: -```text -FINE: Conscrypt native libraries not available. Falling back to JDK TLS. -``` +### 6.1 The Silent Fallback Behavior +If native libraries fail to initialize—due to an unsupported operating system, missing `glibc`, permission issues, or file extraction limits—the client libraries catch the exception and log debug messages: +- For HTTP/JSON: Logs at `Level.FINE`: + ```text + FINE: Conscrypt native libraries not available. Falling back to JDK TLS. + ``` The client then proceeds to establish standard classical TLS using the host JVM's configured security provider (by default `SunJSSE`). **Why does it behave this way?** @@ -175,22 +246,24 @@ To protect production workloads. A customer updating dependencies or migrating c - **Security Baseline**: Traffic remains fully encrypted with classical TLS 1.3 (e.g., ECDHE with AES-GCM), maintaining the standard security posture that Java applications use today. - **What is absent**: The connection will not be protected against future post-quantum decryption (SNDL). -### 4.2 The Compliance Warning +### 6.2 The Compliance Warning > [!WARNING] > **Active Verification is Required for Regulatory Mandates**: > If your organization operates under strict compliance, governmental, or corporate security mandates requiring Post-Quantum Cryptography today, **you cannot rely solely on the default configuration without verification**. > > Because fallback to classical TLS is silent and non-breaking by design, an unexpected environment change (such as switching to an Alpine-based Docker container or changing filesystem mount permissions) could downgrade your connections from hybrid PQC to classical TLS **without throwing exceptions or failing requests**. > -> If PQC is a mandatory requirement for your workload, you must implement automated verification in your CI/CD pipelines or startup health checks (see **Section 5**). +> If PQC is a mandatory requirement for your workload, you must implement automated verification in your CI/CD pipelines or startup health checks (see **Section 7**). --- -## 5. How to Verify PQC Negotiation +## 7. How to Verify PQC Negotiation + +To confirm whether your application is actively negotiating post-quantum hybrid key exchange, use the verification methods below depending on your chosen transport. -To confirm whether your application is actively negotiating post-quantum hybrid key exchange, use one or more of the following verification methods. +### 7.1 Verifying HTTP/JSON Transport -### 5.1 Method 1: GAX Internal Initialization Logging +#### Method 1: GAX Internal Initialization Logging Inspect whether `gax-httpjson` successfully loaded Conscrypt or fell back to the default security provider by enabling debug logging on `HttpJsonConscryptUtils`. In your `logging.properties` file: @@ -214,7 +287,7 @@ Logger.getLogger("com.google.api.gax.httpjson.HttpJsonConscryptUtils").setLevel( FINE: Conscrypt initialization failed with exception: java.lang.UnsatisfiedLinkError: ... ``` -### 5.2 Method 2: JVM TLS Handshake Tracing (`-Djavax.net.debug`) +#### Method 2: JVM TLS Handshake Tracing (`-Djavax.net.debug`) To inspect the actual cryptographic parameters negotiated during the TLS 1.3 handshake with Google Cloud servers, start your Java application with the standard JSSE debug flag: ```bash @@ -246,14 +319,85 @@ Look for the following entries in standard error during the initial HTTPS connec ``` If the negotiated group displays `X25519MLKEM768` (or `0x11ec`), your connection is fully protected with hybrid Post-Quantum Cryptography. +### 7.2 Verifying gRPC Transport + +> [!NOTE] +> **Why `-Djavax.net.debug` does not capture gRPC handshakes**: +> By default, gRPC uses `grpc-netty-shaded`, which uses its bundled native BoringSSL engine (`netty-tcnative`) via JNI, bypassing the JVM's built-in Java Secure Socket Extension (`SunJSSE`). Standard JVM `-Djavax.net.debug` flags will not output gRPC handshake details. + +#### Method 1: Netty SSL Debug Logging +You can enable debug logging for Netty's shaded SSL handler to observe TLS handshake details: + +```bash +java -Dio.grpc.netty.shaded.io.netty.handler.ssl=DEBUG -jar my-application.jar +``` + +#### Method 2: gRPC Client Interceptor Verification +In integration tests or test environments, you can verify the negotiated TLS parameters by attaching a `ClientInterceptor` to inspect response metadata returned by endpoints or test servers: + +```java +import com.google.api.gax.grpc.InstantiatingGrpcChannelProvider; +import com.google.cloud.secretmanager.v1.SecretManagerServiceClient; +import com.google.cloud.secretmanager.v1.SecretManagerServiceSettings; +import io.grpc.CallOptions; +import io.grpc.Channel; +import io.grpc.ClientCall; +import io.grpc.ClientInterceptor; +import io.grpc.ForwardingClientCall; +import io.grpc.ForwardingClientCallListener; +import io.grpc.Metadata; +import io.grpc.MethodDescriptor; +import java.util.Collections; + +public class TlsVerificationInterceptor implements ClientInterceptor { + @Override + public ClientCall interceptCall( + MethodDescriptor method, CallOptions callOptions, Channel next) { + return new ForwardingClientCall.SimpleForwardingClientCall( + next.newCall(method, callOptions)) { + @Override + public void start(Listener responseListener, Metadata headers) { + super.start( + new ForwardingClientCallListener.SimpleForwardingClientCallListener( + responseListener) { + @Override + public void onHeaders(Metadata headers) { + // Inspect response headers or TLS metadata if published by server/proxy + super.onHeaders(headers); + } + }, + headers); + } + }; + } +} + +// Attach the interceptor to the client's gRPC transport provider: +InstantiatingGrpcChannelProvider transportChannelProvider = + SecretManagerServiceSettings.defaultGrpcTransportProviderBuilder() + .setInterceptorProvider(() -> Collections.singletonList(new TlsVerificationInterceptor())) + .build(); + +SecretManagerServiceSettings settings = + SecretManagerServiceSettings.newBuilder() + .setTransportChannelProvider(transportChannelProvider) + .build(); + +try (SecretManagerServiceClient client = SecretManagerServiceClient.create(settings)) { + // Execute calls; interceptor captures response metadata +} +``` + --- -## 6. Custom & Alternative Configurations +## 8. Custom & Alternative Configurations + +By default, Google Cloud client libraries automatically negotiate PQC when supported on the environment without requiring custom code. If you need to customize transport behavior or security providers, you can configure the transports directly: -By default, client libraries automatically use Conscrypt when available on compatible platforms without requiring custom code. If you need to customize transport behavior or security providers, you can configure the transport directly: +### 8.1 HTTP/JSON Custom Configurations -### Option 1: Forcing Classical-Only Key Exchange (Disabling PQC) -If you need to use Conscrypt for high-performance TLS but want to explicitly disable post-quantum hybrid groups (for example, to isolate a network middlebox issue or benchmark legacy performance): +#### Option 1: Forcing Classical-Only Key Exchange (Disabling PQC) +If you need to use Conscrypt for high-performance TLS but want to explicitly disable post-quantum hybrid groups: ```java import com.google.api.client.http.javanet.NetHttpTransport; @@ -296,9 +440,7 @@ try (SecretManagerServiceClient client = SecretManagerServiceClient.create(setti } ``` ---- - -### Option 2: Bypassing Conscrypt to Use Standard JDK JSSE +#### Option 2: Bypassing Conscrypt to Use Standard JDK JSSE If your deployment environment prohibits native JNI libraries or you prefer using the JVM's built-in cryptographic engine (`SunJSSE`): ```java @@ -327,9 +469,7 @@ try (SecretManagerServiceClient client = SecretManagerServiceClient.create(setti } ``` ---- - -### Option 3: Configuring a Third-Party Security Provider (e.g., Bouncy Castle) +#### Option 3: Configuring a Third-Party Security Provider (e.g., Bouncy Castle) If your enterprise utilizes an alternative cryptographic provider (such as Bouncy Castle), configure it directly on the `NetHttpTransport.Builder`: ```java @@ -371,9 +511,55 @@ try (SecretManagerServiceClient client = SecretManagerServiceClient.create(setti --- -## 7. Future Outlook: Native OpenJDK PQC Support (JDK 27+) +### 8.2 gRPC Custom Configurations + +#### Option 1: Configuring Custom Netty SSL Context +For gRPC clients, you can configure `InstantiatingGrpcChannelProvider` with a channel configurator to customize Netty's SSL context (such as setting custom trust certificates, cipher suites, or SSL providers): + +```java +import com.google.api.gax.grpc.InstantiatingGrpcChannelProvider; +import com.google.cloud.secretmanager.v1.SecretManagerServiceClient; +import com.google.cloud.secretmanager.v1.SecretManagerServiceSettings; +import io.grpc.netty.shaded.io.grpc.netty.GrpcSslContexts; +import io.grpc.netty.shaded.io.grpc.netty.NettyChannelBuilder; +import java.io.File; + +// 1. Configure the gRPC channel provider with a custom Netty SSLContext +InstantiatingGrpcChannelProvider transportChannelProvider = + SecretManagerServiceSettings.defaultGrpcTransportProviderBuilder() + .setChannelConfigurator( + managedChannelBuilder -> { + if (managedChannelBuilder instanceof NettyChannelBuilder) { + try { + ((NettyChannelBuilder) managedChannelBuilder) + .sslContext( + GrpcSslContexts.forClient() + // Custom SSL options (e.g., custom trust managers or ciphers) + .build()); + } catch (Exception e) { + throw new RuntimeException("Failed to configure gRPC SSL context", e); + } + } + return managedChannelBuilder; + }) + .build(); + +// 2. Build client settings using the custom gRPC channel provider +SecretManagerServiceSettings settings = + SecretManagerServiceSettings.newBuilder() + .setTransportChannelProvider(transportChannelProvider) + .build(); + +try (SecretManagerServiceClient client = SecretManagerServiceClient.create(settings)) { + // Client communicates using customized gRPC channel +} +``` + +--- + +## 9. Future Outlook: Native OpenJDK PQC Support (JDK 27+) The cryptographic landscape is continually advancing. The OpenJDK community is integrating standardized post-quantum algorithms directly into the Java platform: - **[JEP 496](https://openjdk.org/jeps/496) (ML-KEM)**: Introduces native implementations of NIST FIPS 203 (Module-Lattice-Based Key-Encapsulation Mechanism) into OpenJDK's standard security providers (`SunJSSE` and `SunJCE`), targeted for **JDK 27+**. -- **What this means for Google Cloud Java**: Once JDK 27 becomes standard in production environments, Java applications will be capable of negotiating hybrid and pure post-quantum TLS natively without requiring JNI shared libraries or third-party dependencies like Conscrypt. -- **Future-Proofing**: As native JDK capabilities mature, Google Cloud Java client libraries will adapt to take advantage of built-in JVM providers, preserving a seamless, zero-maintenance security upgrade path for all users. +- **What this means for Google Cloud Java**: Once JDK 27 becomes standard in production environments, Java applications will be capable of negotiating hybrid and pure post-quantum TLS natively without requiring JNI shared libraries or third-party dependencies like Conscrypt or `netty-tcnative`. +- **Future-Proofing**: As native JDK capabilities mature, Google Cloud Java client libraries will adapt to take advantage of built-in JVM providers, preserving a seamless, zero-maintenance security upgrade path for all users across both HTTP/JSON and gRPC transports. From e7d9845d91ad780d5ebc270e2722c0c0b8b0eda8 Mon Sep 17 00:00:00 2001 From: Lawrence Qiu Date: Wed, 2 Sep 2026 18:53:15 +0000 Subject: [PATCH 13/25] docs: update gax-grpc version and clarify grpc-java native engine bundling and JDK bypass --- docs/post_quantum_cryptography_guide.md | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/docs/post_quantum_cryptography_guide.md b/docs/post_quantum_cryptography_guide.md index b04f293f8267..aa21c0250ee3 100644 --- a/docs/post_quantum_cryptography_guide.md +++ b/docs/post_quantum_cryptography_guide.md @@ -110,15 +110,17 @@ PQC enablement for gRPC transport requires compatible versions of `grpc-netty-sh | Library | Minimum Version | Role | | :--- | :--- | :--- | -| **`libraries-bom`** | `26.86.0+` | **Recommended**. Central BOM managing compatible versions across all Google Cloud client libraries. | -| **`gax-grpc`** | `2.83.0+` | Provides gRPC transport channel providers for Google Cloud client libraries. | -| **`grpc-netty-shaded`** | `1.83.0+` | Default gRPC transport engine. Bundles Netty and `netty-tcnative-boringssl-static` with built-in PQC hybrid key exchange support. | - -### 3.2 Why `grpc-netty-shaded`? -By default, Google Cloud Java client libraries use `grpc-netty-shaded` for gRPC transport: -1. **Bundled BoringSSL Engine**: `grpc-netty-shaded` packages a shaded version of Netty and its native OpenSSL/BoringSSL binding (`netty-tcnative-boringssl-static`). This bundles Google's BoringSSL C library directly inside the JAR. -2. **Native PQC Support Out-of-the-Box**: In `grpc-netty-shaded` version **1.83.0+**, the bundled BoringSSL engine natively supports TLS 1.3 post-quantum hybrid key exchange (`X25519MLKEM768`). -3. **Zero Configuration**: Unlike HTTP/JSON which uses Conscrypt as a pluggable `SecurityProvider`, gRPC client channels using `grpc-netty-shaded` automatically negotiate PQC hybrid key exchange without requiring any custom socket configurators, system properties, or security provider setup. +| **`libraries-bom`** | `26.88.0+` | **Recommended**. Central BOM managing compatible versions across all Google Cloud client libraries. | +| **`gax-grpc`** | `2.85.0+` | Provides gRPC transport channel providers for Google Cloud client libraries. | +| **`grpc-netty-shaded`** | `1.83.0+` | Bundled by `grpc-java`. Includes Netty and `netty-tcnative-boringssl-static` with built-in PQC hybrid key exchange support. | + +### 3.2 Bundled BoringSSL Engine in `grpc-java` (Bypassing JDK Security Provider) +Google Cloud Java client libraries rely on **`grpc-java`** for gRPC transport, which chooses by default to bundle **`grpc-netty-shaded`**: + +1. **Bundled BoringSSL Native Engine**: The upstream `grpc-java` project bundles a shaded version of Netty along with its native BoringSSL binding (`netty-tcnative-boringssl-static`). This packages Google's BoringSSL C library directly inside the JAR. +2. **Complete Bypass of Host JDK Security Provider**: Netty's OpenSSL engine interfaces directly with the native BoringSSL binary via JNI. It completely bypasses the host JVM's built-in Java Secure Socket Extension provider (`SunJSSE`) and the JVM security provider registry (`java.security.Security`). +3. **Independent of JDK Version**: Because the host JDK's TLS provider is bypassed, `grpc-netty-shaded` delivers post-quantum hybrid key exchange across **all supported JDK versions** (Java 8, 11, 17, 21, and 25). The host JVM's built-in TLS capabilities (or lack of native PQC in `SunJSSE` prior to JDK 27) do not affect gRPC TLS handshakes. +4. **Zero Configuration**: In `grpc-java` version **1.83.0+**, the bundled BoringSSL engine natively enables and prefers TLS 1.3 post-quantum hybrid key exchange (`X25519MLKEM768`) out-of-the-box. Applications using standard client construction negotiate PQC automatically without requiring custom socket configurators or security provider registration. ### 3.3 How gRPC Clients Negotiate PQC When a Google Cloud gRPC client connects to an endpoint (typically port 443 with TLS): From 7503b90f4b6246f31bd4c5bca869cbfcd55aeae9 Mon Sep 17 00:00:00 2001 From: Lawrence Qiu Date: Wed, 2 Sep 2026 19:47:06 +0000 Subject: [PATCH 14/25] docs: reorder gRPC before HTTP/JSON, remove internal GAPIC references, and refine gRPC fallback --- docs/post_quantum_cryptography_guide.md | 385 ++++++++++++------------ 1 file changed, 198 insertions(+), 187 deletions(-) diff --git a/docs/post_quantum_cryptography_guide.md b/docs/post_quantum_cryptography_guide.md index aa21c0250ee3..78fab728c014 100644 --- a/docs/post_quantum_cryptography_guide.md +++ b/docs/post_quantum_cryptography_guide.md @@ -38,9 +38,68 @@ Adopting PQC in Google Cloud Java client libraries requires no changes to applic --- -## 2. HTTP/JSON Transport Architecture & Defaults +## 2. gRPC Transport Architecture & Defaults + +As the default transport for Google Cloud Java client libraries, gRPC offers high-performance RPCs multiplexed over HTTP/2. ### 2.1 Minimum Required Versions +PQC enablement for gRPC transport requires compatible versions of `grpc-netty-shaded` and `gax-grpc`: + +| Library | Minimum Version | Role | +| :--- | :--- | :--- | +| **`libraries-bom`** | `26.88.0+` | **Recommended**. Central BOM managing compatible versions across all Google Cloud client libraries. | +| **`gax-grpc`** | `2.85.0+` | Provides gRPC transport channel providers for Google Cloud client libraries. | +| **`grpc-netty-shaded`** | `1.83.0+` | Bundled by `grpc-java`. Includes Netty and `netty-tcnative-boringssl-static` with built-in PQC hybrid key exchange support. | + +### 2.2 Bundled BoringSSL Engine in `grpc-java` (Bypassing JDK Security Provider) +Google Cloud Java client libraries rely on **`grpc-java`** for gRPC transport, which chooses by default to bundle **`grpc-netty-shaded`**: + +1. **Bundled BoringSSL Native Engine**: The upstream `grpc-java` project bundles a shaded version of Netty along with its native BoringSSL binding (`netty-tcnative-boringssl-static`). This packages Google's BoringSSL C library directly inside the JAR. +2. **Complete Bypass of Host JDK Security Provider**: Netty's OpenSSL engine interfaces directly with the native BoringSSL binary via JNI. It completely bypasses the host JVM's built-in Java Secure Socket Extension provider (`SunJSSE`) and the JVM security provider registry (`java.security.Security`). +3. **Independent of JDK Version**: Because the host JDK's TLS provider is bypassed, `grpc-netty-shaded` delivers post-quantum hybrid key exchange across **all supported JDK versions** (Java 8, 11, 17, 21, and 25). The host JVM's built-in TLS capabilities (or lack of native PQC in `SunJSSE` prior to JDK 27) do not affect gRPC TLS handshakes. +4. **Zero Configuration**: In `grpc-java` version **1.83.0+**, the bundled BoringSSL engine natively enables and prefers TLS 1.3 post-quantum hybrid key exchange (`X25519MLKEM768`) out-of-the-box. Applications using standard client construction negotiate PQC automatically without requiring custom socket configurators or security provider registration. + +### 2.3 How gRPC Clients Negotiate PQC +When a Google Cloud gRPC client connects to an endpoint (typically port 443 with TLS): +- **PQC-Enabled Google Cloud Endpoints**: The client's BoringSSL engine advertises hybrid PQC algorithms (`X25519MLKEM768`) in its TLS 1.3 `ClientHello`. Google Cloud frontends recognize and select `X25519MLKEM768`, establishing a quantum-resistant HTTP/2 TLS session. +- **Non-PQC Endpoints / Middleboxes**: If the endpoint or an intermediary proxy does not support PQC, standard TLS 1.3 negotiation selects the first mutually supported classical algorithm (such as `X25519`). +- **Transport & Provider Resolution**: Unlike HTTP/JSON (where fallback is explicitly intercepted and handled by the SDK's `HttpJsonConscryptUtils`), the Google Cloud Java SDK does not implement custom TLS fallback logic for gRPC. Instead, upstream `grpc-java` (`grpc-netty-shaded`) manages SSL provider selection: + - By default, `grpc-netty-shaded` bundles native BoringSSL (`netty-tcnative-boringssl-static`) and configures Netty's OpenSSL provider (`SslProvider.OPENSSL`). + - If native BoringSSL cannot be loaded (for example, on environments without compatible `glibc` or where native library extraction is restricted), `grpc-java`'s `GrpcSslContexts` checks for an available JDK security provider supporting ALPN (present by default via `SunJSSE` on Java 9+) and falls back to Netty's JDK JSSE provider (`SslProvider.JDK`). + - If neither native OpenSSL nor an ALPN-capable JDK provider is available, channel initialization fails with an `IllegalStateException`. +- **Impact of Classical Fallback**: If classical TLS is negotiated, your application continues operating normally without disruption. Calls continue over standard classical TLS 1.3 encryption (`X25519`). + +``` ++-------------------------------------------------------------------------------+ +| Google Cloud gRPC Client Request | ++-------------------------------------------------------------------------------+ + | + Is grpc-netty-shaded Native BoringSSL Available? + | + +-------------------+-------------------+ + | | + [ YES ] [ NO ] + | | + v v + grpc-netty-shaded uses BoringSSL grpc-java selects JDK JSSE + Offers Hybrid PQC (X25519MLKEM768) (Java 9+ ALPN supported) + - Google Cloud negotiates X25519MLKEM768 - Negotiates classical X25519 + - Non-PQC endpoints fall back to X25519 via standard JDK SunJSSE +``` + +### 2.4 gRPC Connection Architecture & Multiplexing +gRPC utilizes HTTP/2 as its underlying framing protocol: +- **Long-Lived Multiplexed Channels**: A single `ManagedChannel` maintains persistent TCP/TLS connections to Google Cloud endpoints. +- **Concurrent Stream Multiplexing**: Multiple RPCs execute concurrently over the same underlying connection without creating new TCP or TLS handshakes. +- **Handshake Frequency**: The TLS handshake happens only once when establishing the channel connection. Subsequent RPC calls share the established quantum-resistant session, resulting in zero cryptographic overhead for ongoing API traffic. + +--- + +## 3. HTTP/JSON Transport Architecture & Defaults + +For environments where HTTP/1.1 REST is preferred or required, Google Cloud Java client libraries provide HTTP/JSON transport. + +### 3.1 Minimum Required Versions PQC enablement for HTTP/JSON transport requires compatible versions of `conscrypt-openjdk-uber`, `gax-httpjson`, and `google-http-client`: | Library | Minimum Version | Role | @@ -50,7 +109,7 @@ PQC enablement for HTTP/JSON transport requires compatible versions of `conscryp | **`google-http-client`** | `2.2.0+` | Provides transport-level security provider registration on `NetHttpTransport.Builder`. | | **`conscrypt-openjdk-uber`** | `2.6.0+` *(2.6.2+ recommended)* | Provides Google's BoringSSL native C engine and TLS 1.3 PQC hybrid named groups. | -### 2.2 Why Conscrypt? +### 3.2 Why Conscrypt? Built-in Java Development Kits (Java 8 through Java 26) do not support Post-Quantum Cryptography in their default Java Secure Socket Extension provider (`SunJSSE`). While native ML-KEM support is in development for future Java releases (**JDK 27+** via [JEP 496](https://openjdk.org/jeps/496)), requiring all production enterprise workloads to immediately upgrade to bleeding-edge JDK versions is impractical. To bridge this gap, Google Cloud Java client libraries use **Conscrypt** (`conscrypt-openjdk-uber`) as the default security provider for HTTP/JSON transport: @@ -58,13 +117,13 @@ To bridge this gap, Google Cloud Java client libraries use **Conscrypt** (`consc 2. **Zero Code Changes**: When `gax-httpjson` detects compatible Conscrypt libraries on the classpath, it automatically configures the HTTPS transport without requiring manual SSLContext setup. 3. **High Performance**: BoringSSL contains hardware-accelerated assembly optimizations for modern CPU architectures (x86_64 and ARM64). -### 2.3 Scoped Security Provider (No Global JVM Impact) +### 3.3 Scoped Security Provider (No Global JVM Impact) The Google Cloud Java SDK scopes Conscrypt strictly to Google Cloud Java SDK requests: - `gax-httpjson` configures the Conscrypt `Provider` instance directly on the client's internal `NetHttpTransport.Builder` rather than installing it into the global JVM security registry (`java.security.Security.addProvider(...)`). - As a result, enabling Conscrypt for Google Cloud calls **does not alter the TLS behavior, cipher suites, or security providers of any other HTTP clients or libraries** in your application (e.g., Apache HttpClient, Spring WebClient, OkHttp, or direct `HttpsURLConnection` calls). Your existing JVM-wide cryptographic configurations remain completely undisturbed. -### 2.4 How HTTP/JSON Clients Negotiate PQC +### 3.4 How HTTP/JSON Clients Negotiate PQC When a Google Cloud HTTP/JSON client initiates a connection, it advertises supported key exchange groups to the server in preference order. During the TLS 1.3 handshake, the first mutually supported algorithm that both the client and server agree upon is selected and used for the session: 1. `X25519MLKEM768` *(Hybrid Post-Quantum Key Exchange)* @@ -75,84 +134,32 @@ When a Google Cloud HTTP/JSON client initiates a connection, it advertises suppo > [!NOTE] > **Algorithm Selection**: -> These named groups are selected because they are supported by Conscrypt (see [Conscrypt CAPABILITIES.md](https://github.com/google/conscrypt/blob/2.6.2/CAPABILITIES.md) and `HttpJsonConscryptUtils.DEFAULT_CONSCRYPT_NAMED_GROUPS`). If your application requires a cryptographic algorithm or named group not in this list, you can configure an alternative `SecurityProvider` (e.g., Bouncy Castle; see **Section 8.1, Option 3**). +> These named groups are selected because they are supported by Conscrypt (see [Conscrypt CAPABILITIES.md](https://github.com/google/conscrypt/blob/2.6.2/CAPABILITIES.md) and `HttpJsonConscryptUtils.DEFAULT_CONSCRYPT_NAMED_GROUPS`). If your application requires a cryptographic algorithm or named group not in this list, you can configure an alternative `SecurityProvider` (e.g., Bouncy Castle; see **Section 8.2, Option 3**). #### Handshake Negotiation Flow: - **PQC-Enabled Google Cloud Endpoints**: Google Cloud frontends recognize `X25519MLKEM768` as their preferred group. The client and server agree on this hybrid algorithm, establishing a quantum-resistant TLS 1.3 session. - **Non-PQC Endpoints / Middleboxes**: If a server or intermediate network proxy does not support post-quantum cryptography, it ignores the unrecognized post-quantum identifiers and selects the first mutually supported classical group (e.g., `X25519`). -- **Graceful Client Fallback**: If Conscrypt native libraries cannot load on the client host, the client seamlessly falls back to the environment's configured security provider (which defaults to standard JDK JSSE / `SunJSSE`), negotiating classical TLS 1.3. +- **SDK-Managed Graceful Fallback**: The Google Cloud Java SDK explicitly configures graceful fallback for HTTP/JSON in `HttpJsonConscryptUtils`. If Conscrypt native libraries cannot load on the client host, the SDK catches the linkage error and leaves `NetHttpTransport` unconfigured with Conscrypt, safely defaulting to the environment's configured security provider (standard JDK JSSE / `SunJSSE`), negotiating classical TLS 1.3. - **Impact of Fallback**: Fallback is completely safe and non-breaking for application availability. Your API calls will continue to execute successfully without throwing errors or dropping traffic. The connection remains fully encrypted using industry-standard classical cryptography (such as `X25519` via standard JDK TLS); it simply does not include quantum-resistant hybrid key exchange for that session. ``` +-------------------------------------------------------------------------------+ -| GAPIC HTTP/JSON Client Request | -+-------------------------------------------------------------------------------+ - | - Is Conscrypt JNI Available on This Platform? - | - +-------------------+-------------------+ - | | - [ YES ] [ NO ] - | | - v v - google-http-client uses Conscrypt Falls back to configured - Offers Hybrid PQC + Classical Groups security provider (JDK JSSE) - - Google Cloud negotiates X25519MLKEM768 - Negotiates classical X25519 - - Non-PQC endpoints fall back to X25519 via standard JDK SunJSSE -``` - ---- - -## 3. gRPC Transport Architecture & Defaults - -### 3.1 Minimum Required Versions -PQC enablement for gRPC transport requires compatible versions of `grpc-netty-shaded` and `gax-grpc`: - -| Library | Minimum Version | Role | -| :--- | :--- | :--- | -| **`libraries-bom`** | `26.88.0+` | **Recommended**. Central BOM managing compatible versions across all Google Cloud client libraries. | -| **`gax-grpc`** | `2.85.0+` | Provides gRPC transport channel providers for Google Cloud client libraries. | -| **`grpc-netty-shaded`** | `1.83.0+` | Bundled by `grpc-java`. Includes Netty and `netty-tcnative-boringssl-static` with built-in PQC hybrid key exchange support. | - -### 3.2 Bundled BoringSSL Engine in `grpc-java` (Bypassing JDK Security Provider) -Google Cloud Java client libraries rely on **`grpc-java`** for gRPC transport, which chooses by default to bundle **`grpc-netty-shaded`**: - -1. **Bundled BoringSSL Native Engine**: The upstream `grpc-java` project bundles a shaded version of Netty along with its native BoringSSL binding (`netty-tcnative-boringssl-static`). This packages Google's BoringSSL C library directly inside the JAR. -2. **Complete Bypass of Host JDK Security Provider**: Netty's OpenSSL engine interfaces directly with the native BoringSSL binary via JNI. It completely bypasses the host JVM's built-in Java Secure Socket Extension provider (`SunJSSE`) and the JVM security provider registry (`java.security.Security`). -3. **Independent of JDK Version**: Because the host JDK's TLS provider is bypassed, `grpc-netty-shaded` delivers post-quantum hybrid key exchange across **all supported JDK versions** (Java 8, 11, 17, 21, and 25). The host JVM's built-in TLS capabilities (or lack of native PQC in `SunJSSE` prior to JDK 27) do not affect gRPC TLS handshakes. -4. **Zero Configuration**: In `grpc-java` version **1.83.0+**, the bundled BoringSSL engine natively enables and prefers TLS 1.3 post-quantum hybrid key exchange (`X25519MLKEM768`) out-of-the-box. Applications using standard client construction negotiate PQC automatically without requiring custom socket configurators or security provider registration. - -### 3.3 How gRPC Clients Negotiate PQC -When a Google Cloud gRPC client connects to an endpoint (typically port 443 with TLS): -- **PQC-Enabled Google Cloud Endpoints (GFE)**: The client's BoringSSL engine advertises hybrid PQC algorithms in its TLS 1.3 `ClientHello`. Google Cloud frontends recognize and select `X25519MLKEM768`, establishing a quantum-resistant HTTP/2 TLS session. -- **Non-PQC Endpoints / Middleboxes**: If the endpoint or an intermediary proxy does not support PQC, it selects the first mutually supported classical algorithm (such as `X25519`). -- **Graceful Fallback**: If the bundled native BoringSSL library cannot load on the platform, gRPC safely falls back to standard Java JSSE TLS (or throws an explicit linkage error if shaded Netty native transport is strictly required). When classical TLS is negotiated, your application continues operating normally. - - **Impact of Fallback**: Fallback does not disrupt service availability. Calls continue over standard classical TLS 1.3 encryption. - -``` -+-------------------------------------------------------------------------------+ -| GAPIC gRPC Client Request | +| Google Cloud HTTP/JSON Client Request | +-------------------------------------------------------------------------------+ | - Is grpc-netty-shaded Native BoringSSL Available? + Is Conscrypt JNI Available on This Platform? | - +-------------------+-------------------+ - | | - [ YES ] [ NO ] - | | - v v - grpc-netty-shaded uses BoringSSL Falls back to standard - Offers Hybrid PQC (X25519MLKEM768) classical TLS (JDK JSSE) - - GFE negotiates X25519MLKEM768 - Negotiates classical X25519 - - Non-PQC endpoints fall back to X25519 via standard JDK TLS + +-------------------+-------------------+ + | | + [ YES ] [ NO ] + | | + v v + google-http-client uses Conscrypt Falls back to configured + Offers Hybrid PQC + Classical Groups security provider (JDK JSSE) + - Google Cloud negotiates X25519MLKEM768 - Negotiates classical X25519 + - Non-PQC endpoints fall back to X25519 via standard JDK SunJSSE ``` -### 3.4 gRPC Connection Architecture & Multiplexing -gRPC utilizes HTTP/2 as its underlying framing protocol: -- **Long-Lived Multiplexed Channels**: A single `ManagedChannel` maintains persistent TCP/TLS connections to Google Cloud endpoints. -- **Concurrent Stream Multiplexing**: Multiple RPCs execute concurrently over the same underlying connection without creating new TCP or TLS handshakes. -- **Handshake Frequency**: The TLS handshake happens only once when establishing the channel connection. Subsequent RPC calls share the established quantum-resistant session, resulting in zero cryptographic overhead for ongoing API traffic. - --- ## 4. Performance & Network Considerations @@ -170,29 +177,29 @@ Note the following performance and network considerations across both transports ### 4.2 Transport Connection Characteristics & API Latency Because both transports maintain persistent connections, the latency impact of the larger PQC handshake is limited to initial connection establishment: +- **gRPC (HTTP/2 Multiplexing)**: + - gRPC channels maintain persistent, long-lived HTTP/2 connections. Multiple concurrent RPC requests and streaming calls are multiplexed over a single connection. + - Handshakes occur only when the `ManagedChannel` connects (or reconnects). For warm channels, the amortized latency impact of PQC on individual RPC calls is practically zero. - **HTTP/JSON (`Keep-Alive`)**: - The underlying HTTP transport (`NetHttpTransport` backed by Java's `HttpURLConnection`) supports standard HTTP persistent connections (`Keep-Alive`). - When connections are reused from Java's connection cache, the TLS handshake occurs **only once** when establishing the connection. - Subsequent API requests routed through that active connection reuse the existing TLS session without repeating the handshake. (Note that applications with high connection churn or infrequent calls outside the keep-alive window will perform new handshakes more often.) -- **gRPC (HTTP/2 Multiplexing)**: - - gRPC channels maintain persistent, long-lived HTTP/2 connections. Multiple concurrent RPC requests and streaming calls are multiplexed over a single connection. - - Handshakes occur only when the `ManagedChannel` connects (or reconnects). For warm channels, the amortized latency impact of PQC on individual RPC calls is practically zero. --- ## 5. Deployment Environments & Platform Compatibility -Both HTTP/JSON (via Conscrypt) and gRPC (via `grpc-netty-shaded` / `netty-tcnative`) rely on C native shared libraries (`.so`, `.dylib`, or `.dll`) loaded via JNI. Consequently, both transports share similar platform compatibility considerations. +Both gRPC (via `grpc-netty-shaded` / `netty-tcnative`) and HTTP/JSON (via Conscrypt) rely on C native shared libraries (`.so`, `.dylib`, or `.dll`) loaded via JNI. Consequently, both transports share similar platform compatibility considerations. ### 5.1 Compatibility Matrix | Environment / OS | Status | Notes | | :--- | :--- | :--- | -| **Standard Linux (e.g., Ubuntu, Debian, RHEL, CentOS — non-exhaustive)** | **Fully Supported** | Requires `glibc` 2.17+ (Conscrypt 2.6.2+ and Netty tcnative). | +| **Standard Linux (e.g., Ubuntu, Debian, RHEL, CentOS — non-exhaustive)** | **Fully Supported** | Requires `glibc` 2.17+ (`grpc-netty-shaded` and Conscrypt 2.6.2+). | | **Google Cloud Managed (Cloud Run, GKE, App Engine)** | **Fully Supported** | Default base container environments use compatible `glibc` runtimes. | -| **macOS (Apple Silicon M-series & Intel)** | **Fully Supported** | Native `osx-aarch_64` and `osx-x86_64` binaries bundled in `conscrypt-openjdk-uber` and `grpc-netty-shaded`. | -| **Windows (x86_64)** | **Fully Supported** | Native `windows-x86_64` binaries bundled in `conscrypt-openjdk-uber` and `grpc-netty-shaded`. | -| **GraalVM Native Image** | **Supported** | Supported when including appropriate reachability metadata and configuration for Conscrypt or Netty JNI libraries. | +| **macOS (Apple Silicon M-series & Intel)** | **Fully Supported** | Native `osx-aarch_64` and `osx-x86_64` binaries bundled in `grpc-netty-shaded` and `conscrypt-openjdk-uber`. | +| **Windows (x86_64)** | **Fully Supported** | Native `windows-x86_64` binaries bundled in `grpc-netty-shaded` and `conscrypt-openjdk-uber`. | +| **GraalVM Native Image** | **Supported** | Supported when including appropriate reachability metadata and configuration for Netty or Conscrypt JNI libraries. | | **Alpine Linux / Musl libc Containers** | **Fallback to Classical** | Native binaries are compiled for `glibc`. On Alpine (`musl`), native library loading fails with `UnsatisfiedLinkError` and safely falls back to standard classical TLS. | ### 5.2 Handling Alpine Linux (`musl` libc) @@ -201,7 +208,7 @@ If your container images are based on Alpine Linux (e.g., `eclipse-temurin:17-al **Some Possible Options on Alpine**: 1. **Accept Classical TLS Fallback**: The client library will safely fall back to classical TLS 1.3 (`X25519`). Your application will function normally without errors. 2. **Use a Glibc-Based Container Image**: If quantum resistance via native BoringSSL is desired, use a base container image that provides `glibc` (such as Debian-, Ubuntu-, or Wolfi-based container images). -3. **Configure an Alternative Security Provider (HTTP/JSON)**: Use an alternative pure-Java security provider that supports your environment (such as Bouncy Castle; see **Section 8.1, Option 3**). +3. **Configure an Alternative Security Provider (HTTP/JSON)**: Use an alternative pure-Java security provider that supports your environment (such as Bouncy Castle; see **Section 8.2, Option 3**). ### 5.3 Handling Hardened Filesystems & `noexec /tmp` In hardened Kubernetes pods or security-conscious Docker containers, `/tmp` may be mounted with the `noexec` flag or the entire root filesystem may be marked read-only. @@ -212,19 +219,19 @@ java.lang.UnsatisfiedLinkError: ... failed to map segment from shared object: Op ``` **Possible Solution**: Depending on your container configuration and security constraints, one possible solution is to provide an alternative directory that has write and execute permissions using JVM system properties: -- For Conscrypt (HTTP/JSON): - ```bash - java -Dorg.conscrypt.native.workdir=/var/run/app/tmp -jar my-application.jar - ``` - For Netty / gRPC: ```bash java -Dio.netty.native.workdir=/var/run/app/tmp -jar my-application.jar ``` +- For Conscrypt (HTTP/JSON): + ```bash + java -Dorg.conscrypt.native.workdir=/var/run/app/tmp -jar my-application.jar + ``` ### 5.4 Classpath Isolation & Version Skew Warning -If your project uses multiple dependencies that transitively pull in different versions of Conscrypt or gRPC Netty components, JNI ABI mismatches can occur during JVM classloading. Always ensure your build tool resolves compatible versions consistently. +If your project uses multiple dependencies that transitively pull in different versions of gRPC Netty components or Conscrypt, JNI ABI mismatches can occur during JVM classloading. Always ensure your build tool resolves compatible versions consistently. -One possible solution for this is to use Google Cloud's `libraries-bom` (version `26.86.0+`), which centrally manages dependency versions and ensures consistent, compatible runtime dependencies across all Google Cloud client libraries. +One possible solution for this is to use Google Cloud's `libraries-bom` (version `26.88.0+`), which centrally manages dependency versions and ensures consistent, compatible runtime dependencies across all Google Cloud client libraries. --- @@ -233,12 +240,14 @@ One possible solution for this is to use Google Cloud's `libraries-bom` (version Google Cloud Java client libraries follow a deliberate architectural principle: **prefer service availability over hard failures**. ### 6.1 The Silent Fallback Behavior -If native libraries fail to initialize—due to an unsupported operating system, missing `glibc`, permission issues, or file extraction limits—the client libraries catch the exception and log debug messages: -- For HTTP/JSON: Logs at `Level.FINE`: +If native libraries fail to initialize—due to an unsupported operating system, missing `glibc`, permission issues, or file extraction limits—connections continue using classical TLS: +- **For HTTP/JSON**: The Google Cloud Java SDK explicitly configures fallback in `HttpJsonConscryptUtils`. If Conscrypt native libraries fail to load, the SDK catches the `LinkageError`, logs at `Level.FINE`: ```text - FINE: Conscrypt native libraries not available. Falling back to JDK TLS. + FINE: Conscrypt native library unavailable. Falling back to default JDK TLS. ``` -The client then proceeds to establish standard classical TLS using the host JVM's configured security provider (by default `SunJSSE`). + and proceeds to establish standard classical TLS using the host JVM's configured security provider (by default `SunJSSE`). +- **For gRPC**: The SDK delegates transport and channel creation to upstream `grpc-java` (`grpc-netty-shaded`). If the bundled native BoringSSL library fails to load, `grpc-java`'s `GrpcSslContexts` checks for an available ALPN-capable JDK security provider (provided by `SunJSSE` on Java 9+) and falls back to standard JDK JSSE. +- **At the TLS Handshake Layer**: In both transports, if the server endpoint or an intermediate network proxy does not support PQC, the TLS 1.3 handshake naturally negotiates classical algorithms (such as `X25519`). **Why does it behave this way?** To protect production workloads. A customer updating dependencies or migrating container images should not experience broken API calls or catastrophic application outages simply because a native optimization library could not load on their environment. @@ -263,7 +272,78 @@ To protect production workloads. A customer updating dependencies or migrating c To confirm whether your application is actively negotiating post-quantum hybrid key exchange, use the verification methods below depending on your chosen transport. -### 7.1 Verifying HTTP/JSON Transport +### 7.1 Verifying gRPC Transport + +> [!NOTE] +> **Why `-Djavax.net.debug` does not capture gRPC handshakes**: +> By default, gRPC uses `grpc-netty-shaded`, which uses its bundled native BoringSSL engine (`netty-tcnative`) via JNI, bypassing the JVM's built-in Java Secure Socket Extension (`SunJSSE`). Standard JVM `-Djavax.net.debug` flags will not output gRPC handshake details. + +#### Method 1: Netty SSL Debug Logging +You can enable debug logging for Netty's shaded SSL handler to observe TLS handshake details: + +```bash +java -Dio.grpc.netty.shaded.io.netty.handler.ssl=DEBUG -jar my-application.jar +``` + +#### Method 2: gRPC Client Interceptor Verification +In integration tests or test environments, you can verify the negotiated TLS parameters by attaching a `ClientInterceptor` to inspect response metadata returned by endpoints or test servers: + +```java +import com.google.api.gax.grpc.InstantiatingGrpcChannelProvider; +import com.google.cloud.secretmanager.v1.SecretManagerServiceClient; +import com.google.cloud.secretmanager.v1.SecretManagerServiceSettings; +import io.grpc.CallOptions; +import io.grpc.Channel; +import io.grpc.ClientCall; +import io.grpc.ClientInterceptor; +import io.grpc.ForwardingClientCall; +import io.grpc.ForwardingClientCallListener; +import io.grpc.Metadata; +import io.grpc.MethodDescriptor; +import java.util.Collections; + +public class TlsVerificationInterceptor implements ClientInterceptor { + @Override + public ClientCall interceptCall( + MethodDescriptor method, CallOptions callOptions, Channel next) { + return new ForwardingClientCall.SimpleForwardingClientCall( + next.newCall(method, callOptions)) { + @Override + public void start(Listener responseListener, Metadata headers) { + super.start( + new ForwardingClientCallListener.SimpleForwardingClientCallListener( + responseListener) { + @Override + public void onHeaders(Metadata headers) { + // Inspect response headers or TLS metadata if published by server/proxy + super.onHeaders(headers); + } + }, + headers); + } + }; + } +} + +// Attach the interceptor to the client's gRPC transport provider: +InstantiatingGrpcChannelProvider transportChannelProvider = + SecretManagerServiceSettings.defaultGrpcTransportProviderBuilder() + .setInterceptorProvider(() -> Collections.singletonList(new TlsVerificationInterceptor())) + .build(); + +SecretManagerServiceSettings settings = + SecretManagerServiceSettings.newBuilder() + .setTransportChannelProvider(transportChannelProvider) + .build(); + +try (SecretManagerServiceClient client = SecretManagerServiceClient.create(settings)) { + // Execute calls; interceptor captures response metadata +} +``` + +--- + +### 7.2 Verifying HTTP/JSON Transport #### Method 1: GAX Internal Initialization Logging Inspect whether `gax-httpjson` successfully loaded Conscrypt or fell back to the default security provider by enabling debug logging on `HttpJsonConscryptUtils`. @@ -321,82 +401,59 @@ Look for the following entries in standard error during the initial HTTPS connec ``` If the negotiated group displays `X25519MLKEM768` (or `0x11ec`), your connection is fully protected with hybrid Post-Quantum Cryptography. -### 7.2 Verifying gRPC Transport +--- -> [!NOTE] -> **Why `-Djavax.net.debug` does not capture gRPC handshakes**: -> By default, gRPC uses `grpc-netty-shaded`, which uses its bundled native BoringSSL engine (`netty-tcnative`) via JNI, bypassing the JVM's built-in Java Secure Socket Extension (`SunJSSE`). Standard JVM `-Djavax.net.debug` flags will not output gRPC handshake details. +## 8. Custom & Alternative Configurations -#### Method 1: Netty SSL Debug Logging -You can enable debug logging for Netty's shaded SSL handler to observe TLS handshake details: +By default, Google Cloud client libraries automatically negotiate PQC when supported on the environment without requiring custom code. If you need to customize transport behavior or security providers, you can configure the transports directly: -```bash -java -Dio.grpc.netty.shaded.io.netty.handler.ssl=DEBUG -jar my-application.jar -``` +### 8.1 gRPC Custom Configurations -#### Method 2: gRPC Client Interceptor Verification -In integration tests or test environments, you can verify the negotiated TLS parameters by attaching a `ClientInterceptor` to inspect response metadata returned by endpoints or test servers: +#### Option 1: Configuring Custom Netty SSL Context +For gRPC clients, you can configure `InstantiatingGrpcChannelProvider` with a channel configurator to customize Netty's SSL context (such as setting custom trust certificates, cipher suites, or SSL providers): ```java import com.google.api.gax.grpc.InstantiatingGrpcChannelProvider; import com.google.cloud.secretmanager.v1.SecretManagerServiceClient; import com.google.cloud.secretmanager.v1.SecretManagerServiceSettings; -import io.grpc.CallOptions; -import io.grpc.Channel; -import io.grpc.ClientCall; -import io.grpc.ClientInterceptor; -import io.grpc.ForwardingClientCall; -import io.grpc.ForwardingClientCallListener; -import io.grpc.Metadata; -import io.grpc.MethodDescriptor; -import java.util.Collections; - -public class TlsVerificationInterceptor implements ClientInterceptor { - @Override - public ClientCall interceptCall( - MethodDescriptor method, CallOptions callOptions, Channel next) { - return new ForwardingClientCall.SimpleForwardingClientCall( - next.newCall(method, callOptions)) { - @Override - public void start(Listener responseListener, Metadata headers) { - super.start( - new ForwardingClientCallListener.SimpleForwardingClientCallListener( - responseListener) { - @Override - public void onHeaders(Metadata headers) { - // Inspect response headers or TLS metadata if published by server/proxy - super.onHeaders(headers); - } - }, - headers); - } - }; - } -} +import io.grpc.netty.shaded.io.grpc.netty.GrpcSslContexts; +import io.grpc.netty.shaded.io.grpc.netty.NettyChannelBuilder; +import java.io.File; -// Attach the interceptor to the client's gRPC transport provider: +// 1. Configure the gRPC channel provider with a custom Netty SSLContext InstantiatingGrpcChannelProvider transportChannelProvider = SecretManagerServiceSettings.defaultGrpcTransportProviderBuilder() - .setInterceptorProvider(() -> Collections.singletonList(new TlsVerificationInterceptor())) + .setChannelConfigurator( + managedChannelBuilder -> { + if (managedChannelBuilder instanceof NettyChannelBuilder) { + try { + ((NettyChannelBuilder) managedChannelBuilder) + .sslContext( + GrpcSslContexts.forClient() + // Custom SSL options (e.g., custom trust managers or ciphers) + .build()); + } catch (Exception e) { + throw new RuntimeException("Failed to configure gRPC SSL context", e); + } + } + return managedChannelBuilder; + }) .build(); +// 2. Build client settings using the custom gRPC channel provider SecretManagerServiceSettings settings = SecretManagerServiceSettings.newBuilder() .setTransportChannelProvider(transportChannelProvider) .build(); try (SecretManagerServiceClient client = SecretManagerServiceClient.create(settings)) { - // Execute calls; interceptor captures response metadata + // Client communicates using customized gRPC channel } ``` --- -## 8. Custom & Alternative Configurations - -By default, Google Cloud client libraries automatically negotiate PQC when supported on the environment without requiring custom code. If you need to customize transport behavior or security providers, you can configure the transports directly: - -### 8.1 HTTP/JSON Custom Configurations +### 8.2 HTTP/JSON Custom Configurations #### Option 1: Forcing Classical-Only Key Exchange (Disabling PQC) If you need to use Conscrypt for high-performance TLS but want to explicitly disable post-quantum hybrid groups: @@ -513,55 +570,9 @@ try (SecretManagerServiceClient client = SecretManagerServiceClient.create(setti --- -### 8.2 gRPC Custom Configurations - -#### Option 1: Configuring Custom Netty SSL Context -For gRPC clients, you can configure `InstantiatingGrpcChannelProvider` with a channel configurator to customize Netty's SSL context (such as setting custom trust certificates, cipher suites, or SSL providers): - -```java -import com.google.api.gax.grpc.InstantiatingGrpcChannelProvider; -import com.google.cloud.secretmanager.v1.SecretManagerServiceClient; -import com.google.cloud.secretmanager.v1.SecretManagerServiceSettings; -import io.grpc.netty.shaded.io.grpc.netty.GrpcSslContexts; -import io.grpc.netty.shaded.io.grpc.netty.NettyChannelBuilder; -import java.io.File; - -// 1. Configure the gRPC channel provider with a custom Netty SSLContext -InstantiatingGrpcChannelProvider transportChannelProvider = - SecretManagerServiceSettings.defaultGrpcTransportProviderBuilder() - .setChannelConfigurator( - managedChannelBuilder -> { - if (managedChannelBuilder instanceof NettyChannelBuilder) { - try { - ((NettyChannelBuilder) managedChannelBuilder) - .sslContext( - GrpcSslContexts.forClient() - // Custom SSL options (e.g., custom trust managers or ciphers) - .build()); - } catch (Exception e) { - throw new RuntimeException("Failed to configure gRPC SSL context", e); - } - } - return managedChannelBuilder; - }) - .build(); - -// 2. Build client settings using the custom gRPC channel provider -SecretManagerServiceSettings settings = - SecretManagerServiceSettings.newBuilder() - .setTransportChannelProvider(transportChannelProvider) - .build(); - -try (SecretManagerServiceClient client = SecretManagerServiceClient.create(settings)) { - // Client communicates using customized gRPC channel -} -``` - ---- - ## 9. Future Outlook: Native OpenJDK PQC Support (JDK 27+) The cryptographic landscape is continually advancing. The OpenJDK community is integrating standardized post-quantum algorithms directly into the Java platform: - **[JEP 496](https://openjdk.org/jeps/496) (ML-KEM)**: Introduces native implementations of NIST FIPS 203 (Module-Lattice-Based Key-Encapsulation Mechanism) into OpenJDK's standard security providers (`SunJSSE` and `SunJCE`), targeted for **JDK 27+**. - **What this means for Google Cloud Java**: Once JDK 27 becomes standard in production environments, Java applications will be capable of negotiating hybrid and pure post-quantum TLS natively without requiring JNI shared libraries or third-party dependencies like Conscrypt or `netty-tcnative`. -- **Future-Proofing**: As native JDK capabilities mature, Google Cloud Java client libraries will adapt to take advantage of built-in JVM providers, preserving a seamless, zero-maintenance security upgrade path for all users across both HTTP/JSON and gRPC transports. +- **Future-Proofing**: As native JDK capabilities mature, Google Cloud Java client libraries will adapt to take advantage of built-in JVM providers, preserving a seamless, zero-maintenance security upgrade path for all users across both gRPC and HTTP/JSON transports. From cdc8ad75445981faa188d9a29bb40f10c679684b Mon Sep 17 00:00:00 2001 From: Lawrence Qiu Date: Thu, 3 Sep 2026 15:04:50 +0000 Subject: [PATCH 15/25] docs: address review comments on PQC user guide --- docs/post_quantum_cryptography_guide.md | 54 ++++++++++--------------- 1 file changed, 22 insertions(+), 32 deletions(-) diff --git a/docs/post_quantum_cryptography_guide.md b/docs/post_quantum_cryptography_guide.md index 348c0ec48705..222189a6969f 100644 --- a/docs/post_quantum_cryptography_guide.md +++ b/docs/post_quantum_cryptography_guide.md @@ -1,12 +1,14 @@ # Post-Quantum Cryptography (PQC) User Guide for HTTP/JSON (REST) Java Client Libraries -## 1. Executive Summary & Core Concepts +## 1. Core Concepts ### 1.1 What is Post-Quantum Cryptography (PQC)? Traditional Transport Layer Security (TLS) public-key cryptography—such as RSA and Elliptic Curve Diffie-Hellman (ECDH)—relies on mathematical problems (integer factorization and discrete logarithms) that are practically impossible for classical computers to solve in a reasonable timeframe. However, sufficiently large, cryptographically relevant quantum computers (CRQCs) will be capable of breaking these mathematical foundations using [Shor's algorithm](https://en.wikipedia.org/wiki/Shor%27s_algorithm). **Post-Quantum Cryptography (PQC)** refers to a new class of cryptographic algorithms designed to run on classical hardware while remaining mathematically secure against attacks from both classical and quantum computers. +For more background on PQC and Google Cloud's broader post-quantum security initiatives, see the [Google Cloud Post-quantum TLS documentation](https://cloud.google.com/load-balancing/docs/tls-versions#post-quantum-tls), [Google Cloud KMS PQC Overview](https://cloud.google.com/security/docs/asymmetric-pqc-insights), and [NIST FIPS 203 (ML-KEM)](https://csrc.nist.gov/pubs/fips/203/final). + ### 1.2 The Threat: "Store-Now, Decrypt-Later" (SNDL) The primary threat addressed by PQC today is **Store-Now, Decrypt-Later (SNDL)**: - **The Attack**: Adversaries can intercept and archive encrypted network communications traversing the public internet today. @@ -85,20 +87,20 @@ When a Google Cloud HTTP/JSON client initiates a connection, it advertises suppo ``` +-------------------------------------------------------------------------------+ -| GAPIC HTTP/JSON Client Request | +| Google Cloud HTTP/JSON Client Request | +-------------------------------------------------------------------------------+ | - Is Conscrypt JNI Available on This Platform? + Is Conscrypt JNI Available on This Platform? | - +-------------------+-------------------+ - | | - [ YES ] [ NO ] - | | - v v - google-http-client uses Conscrypt Falls back to configured - Offers Hybrid PQC + Classical Groups security provider (JDK JSSE) - - Google Cloud negotiates X25519MLKEM768 - Negotiates classical X25519 - - Non-PQC endpoints fall back to X25519 via standard JDK SunJSSE + +-------------------+-------------------+ + | | + [ YES ] [ NO ] + | | + v v + google-http-client uses Conscrypt Falls back to configured + Offers Hybrid PQC + Classical Groups security provider (JDK JSSE) + - Google Cloud negotiates X25519MLKEM768 - Negotiates classical X25519 + - Non-PQC endpoints fall back to X25519 via standard JDK SunJSSE ``` ### 2.5 Performance & Network Considerations @@ -127,29 +129,17 @@ Because Conscrypt relies on C native shared libraries (`.so`, `.dylib`, or `.dll | **macOS (Apple Silicon M-series & Intel)** | **Fully Supported** | Native `osx-aarch_64` and `osx-x86_64` binaries bundled in `conscrypt-openjdk-uber`. | | **Windows (x86_64)** | **Fully Supported** | Native `windows-x86_64` binary bundled in `conscrypt-openjdk-uber`. | | **GraalVM Native Image** | **Supported** | Supported when including appropriate reachability metadata and configuration for Conscrypt JNI libraries. | -| **Alpine Linux / Musl libc Containers** | **Fallback to Classical** | Conscrypt native binaries are compiled for `glibc`. On Alpine (`musl`), native loading fails with `UnsatisfiedLinkError` and gracefully falls back to the configured security provider (default JDK TLS). | - -### 3.2 Handling Alpine Linux (`musl` libc) -If your container images are based on Alpine Linux (e.g., `eclipse-temurin:17-alpine` or `openjdk:11-alpine`), Conscrypt cannot load its native C library because Alpine uses `musl` libc instead of `glibc`. +| **Alpine Linux / Musl libc Containers** | **Fallback to Classical** | Conscrypt native binaries require `glibc`. On Alpine (`musl`), native loading is unsupported and safely falls back to standard classical TLS. | -**Some Possible Options on Alpine**: -1. **Accept Classical TLS Fallback**: The client library will safely fall back to the configured security provider (by default standard JDK JSSE) and negotiate classical TLS 1.3 (`X25519`). Your application will function normally without errors. -2. **Use a Glibc-Based Container Image**: If quantum resistance via Conscrypt is desired, use a base container image that provides `glibc`. -3. **Configure an Alternative Security Provider**: Use an alternative security provider that supports your environment (such as Bouncy Castle; see **Section 6, Option 3**). +### 3.2 Unsupported Scenarios & Graceful Fallback +Certain deployment environments do not support native Conscrypt binaries out of the box. In these scenarios, the client libraries do not fail; they gracefully fall back to the host JVM's default security provider (standard classical TLS): -### 3.3 Handling Hardened Filesystems & `noexec /tmp` -In hardened Kubernetes pods or security-conscious Docker containers, `/tmp` may be mounted with the `noexec` flag or the entire root filesystem may be marked read-only. - -When Conscrypt starts, the JVM extracts its bundled native `.so` file to a temporary directory. If that directory does not allow execution: -```text -java.lang.UnsatisfiedLinkError: /tmp/libconscrypt_openjdk_jni...: failed to map segment from shared object: Operation not permitted -``` -**Possible Solution**: Depending on your container configuration and security constraints, one possible solution is to provide an alternative directory that has write and execute permissions using the JVM system property: -```bash -java -Dorg.conscrypt.native.workdir=/var/run/app/tmp -jar my-application.jar -``` +- **Alpine Linux (`musl` libc)**: + Precompiled Conscrypt native binaries require `glibc` and cannot load on Alpine Linux or other `musl`-based container distributions (e.g., `eclipse-temurin:17-alpine`). On these platforms, Conscrypt native loading fails with an `UnsatisfiedLinkError`, and the client automatically falls back to classical TLS (`X25519`). Workloads requiring post-quantum hybrid key exchange should use a `glibc`-compatible base image (such as Debian, Ubuntu, or Wolfi). +- **Hardened Filesystems (`noexec /tmp`)**: + In security-hardened container or Kubernetes environments where `/tmp` is mounted with the `noexec` flag or the filesystem is strictly read-only, the JVM cannot load native shared libraries extracted to `/tmp`, resulting in an `UnsatisfiedLinkError` (`failed to map segment from shared object: Operation not permitted`). The client safely falls back to classical TLS. If PQC is required in these environments, configure an executable working directory using JVM system properties (e.g., `-Dorg.conscrypt.native.workdir=/path/to/executable/dir`). -### 3.4 Classpath Isolation & Version Skew Warning +### 3.3 Classpath Isolation & Version Skew Warning If your project uses multiple dependencies that transitively pull in different versions of Conscrypt (e.g., older versions like `2.5.2` alongside `2.6.2`), a JNI ABI mismatch can occur during JVM classloading. Always ensure your build tool (Maven/Gradle) resolves `conscrypt-openjdk-uber` to version `2.6.0+` (or `2.6.2+`) consistently. One possible solution for this is to use Google Cloud's `libraries-bom` (version `26.86.0+`) to manage dependency versions, ensuring a consistent and compatible Conscrypt runtime across all Google Cloud client libraries. From 1ffb7e9c2d2d0db91bd8341c8dc3f4d38ea7e7b9 Mon Sep 17 00:00:00 2001 From: Lawrence Qiu Date: Thu, 3 Sep 2026 15:07:37 +0000 Subject: [PATCH 16/25] docs: remove external PQC background links --- docs/post_quantum_cryptography_guide.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/docs/post_quantum_cryptography_guide.md b/docs/post_quantum_cryptography_guide.md index 222189a6969f..490f7197b0fb 100644 --- a/docs/post_quantum_cryptography_guide.md +++ b/docs/post_quantum_cryptography_guide.md @@ -7,8 +7,6 @@ Traditional Transport Layer Security (TLS) public-key cryptography—such as RSA However, sufficiently large, cryptographically relevant quantum computers (CRQCs) will be capable of breaking these mathematical foundations using [Shor's algorithm](https://en.wikipedia.org/wiki/Shor%27s_algorithm). **Post-Quantum Cryptography (PQC)** refers to a new class of cryptographic algorithms designed to run on classical hardware while remaining mathematically secure against attacks from both classical and quantum computers. -For more background on PQC and Google Cloud's broader post-quantum security initiatives, see the [Google Cloud Post-quantum TLS documentation](https://cloud.google.com/load-balancing/docs/tls-versions#post-quantum-tls), [Google Cloud KMS PQC Overview](https://cloud.google.com/security/docs/asymmetric-pqc-insights), and [NIST FIPS 203 (ML-KEM)](https://csrc.nist.gov/pubs/fips/203/final). - ### 1.2 The Threat: "Store-Now, Decrypt-Later" (SNDL) The primary threat addressed by PQC today is **Store-Now, Decrypt-Later (SNDL)**: - **The Attack**: Adversaries can intercept and archive encrypted network communications traversing the public internet today. From f0b69d8600dd1a2f29a433c16e17599bd63dc434 Mon Sep 17 00:00:00 2001 From: Lawrence Qiu Date: Thu, 3 Sep 2026 15:10:23 +0000 Subject: [PATCH 17/25] docs: add references to official Google Cloud PQC documentation --- docs/post_quantum_cryptography_guide.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/post_quantum_cryptography_guide.md b/docs/post_quantum_cryptography_guide.md index 490f7197b0fb..34b101831bba 100644 --- a/docs/post_quantum_cryptography_guide.md +++ b/docs/post_quantum_cryptography_guide.md @@ -7,6 +7,8 @@ Traditional Transport Layer Security (TLS) public-key cryptography—such as RSA However, sufficiently large, cryptographically relevant quantum computers (CRQCs) will be capable of breaking these mathematical foundations using [Shor's algorithm](https://en.wikipedia.org/wiki/Shor%27s_algorithm). **Post-Quantum Cryptography (PQC)** refers to a new class of cryptographic algorithms designed to run on classical hardware while remaining mathematically secure against attacks from both classical and quantum computers. +For more information on Google Cloud's PQC roadmap and security resources, see [PQC in Plaintext: Google Cloud's Post-Quantum Cryptography Roadmap](https://cloud.google.com/blog/products/identity-security/pqc-in-plaintext-google-clouds-post-quantum-cryptography-roadmap) and [Google Cloud Post-Quantum Cryptography Resources](https://cloud.google.com/security/resources/post-quantum-cryptography). + ### 1.2 The Threat: "Store-Now, Decrypt-Later" (SNDL) The primary threat addressed by PQC today is **Store-Now, Decrypt-Later (SNDL)**: - **The Attack**: Adversaries can intercept and archive encrypted network communications traversing the public internet today. From 1d9df622cfdbc33a44e9bcd6276d5484f6e02341 Mon Sep 17 00:00:00 2001 From: Lawrence Qiu Date: Thu, 3 Sep 2026 18:18:01 +0000 Subject: [PATCH 18/25] docs: simplify introductory PQC section and add official Google references --- docs/post_quantum_cryptography_guide.md | 48 +++++++++---------------- 1 file changed, 16 insertions(+), 32 deletions(-) diff --git a/docs/post_quantum_cryptography_guide.md b/docs/post_quantum_cryptography_guide.md index 34b101831bba..3ba509a3f5ac 100644 --- a/docs/post_quantum_cryptography_guide.md +++ b/docs/post_quantum_cryptography_guide.md @@ -2,41 +2,25 @@ ## 1. Core Concepts -### 1.1 What is Post-Quantum Cryptography (PQC)? -Traditional Transport Layer Security (TLS) public-key cryptography—such as RSA and Elliptic Curve Diffie-Hellman (ECDH)—relies on mathematical problems (integer factorization and discrete logarithms) that are practically impossible for classical computers to solve in a reasonable timeframe. - -However, sufficiently large, cryptographically relevant quantum computers (CRQCs) will be capable of breaking these mathematical foundations using [Shor's algorithm](https://en.wikipedia.org/wiki/Shor%27s_algorithm). **Post-Quantum Cryptography (PQC)** refers to a new class of cryptographic algorithms designed to run on classical hardware while remaining mathematically secure against attacks from both classical and quantum computers. - -For more information on Google Cloud's PQC roadmap and security resources, see [PQC in Plaintext: Google Cloud's Post-Quantum Cryptography Roadmap](https://cloud.google.com/blog/products/identity-security/pqc-in-plaintext-google-clouds-post-quantum-cryptography-roadmap) and [Google Cloud Post-Quantum Cryptography Resources](https://cloud.google.com/security/resources/post-quantum-cryptography). - -### 1.2 The Threat: "Store-Now, Decrypt-Later" (SNDL) -The primary threat addressed by PQC today is **Store-Now, Decrypt-Later (SNDL)**: -- **The Attack**: Adversaries can intercept and archive encrypted network communications traversing the public internet today. -- **The Consequence**: Even if attackers cannot read ciphertext now, they can store the encrypted traffic indefinitely and decrypt it in the future once quantum computers become available. -- **The Impact**: Any data with a long secrecy lifecycle—such as customer records, credentials, intellectual property, health information, and financial transactions—is vulnerable to retroactive exposure unless protected before transmission. - -### 1.3 Addressing the Threat: Hybrid Key Exchange -Rather than completely replacing proven classical algorithms with brand-new post-quantum mechanisms, client libraries can utilize **Hybrid Key Exchange** (e.g., combining classical ECDH with post-quantum algorithms such as `X25519MLKEM768`): - -> [!TIP] -> **The Two-Lock Analogy**: -> Think of hybrid key exchange like securing a door with **two distinct locks**: -> 1. A battle-tested **classical lock** (`X25519` elliptic curve). -> 2. A quantum-resistant **post-quantum lock** (`ML-KEM-768`, NIST FIPS 203). -> -> To decrypt the session, an attacker must break **both** locks simultaneously: -> - If an unforeseen mathematical weakness is ever discovered in the post-quantum algorithm, the classical algorithm still maintains security. -> - If a quantum computer breaks the classical algorithm, the post-quantum algorithm still maintains security. - -### 1.4 What Changes vs. What Stays the Same? -Adopting PQC in Google Cloud Java client libraries requires no changes to business logic: +**Post-Quantum Cryptography (PQC)** refers to cryptographic algorithms designed to protect encrypted communications against attacks from future quantum computers. The primary threat addressed today is **Store-Now, Decrypt-Later (SNDL)**—where encrypted network traffic is intercepted and stored today by an adversary with the goal of decrypting it once cryptographically relevant quantum computers emerge. + +To defend against this without sacrificing stability, Google Cloud Java client libraries adopt **Hybrid Key Exchange** (combining classical algorithms like `X25519` with standardized post-quantum algorithms like `ML-KEM-768`). This ensures connections remain secure even if an unforeseen mathematical weakness is discovered in either algorithm. + +For in-depth background on PQC, NIST standards, and Google's quantum-safe roadmap, refer to the following resources: +- [Google Cloud Post-Quantum Cryptography Resources](https://cloud.google.com/security/resources/post-quantum-cryptography) +- [How Google is preparing for a post-quantum world](https://cloud.google.com/blog/products/identity-security/how-google-is-preparing-for-a-post-quantum-world/?e=48754805) +- [PQC in Plaintext: Google Cloud's Post-Quantum Cryptography Roadmap](https://cloud.google.com/blog/products/identity-security/pqc-in-plaintext-google-clouds-post-quantum-cryptography-roadmap) +- [Post-Quantum Cryptography Standards: What you need to know](https://security.googleblog.com/2024/08/post-quantum-cryptography-standards.html) + +### 1.1 What Changes in Google Cloud Java Client Libraries? +Enabling PQC in Google Cloud Java client libraries requires **zero changes to application business logic**: - **What stays exactly the same**: - - Your application source code and business logic. - - How you construct and call API clients (e.g., `SecretManagerServiceClient`, `StorageClient`). + - Application source code and business logic. + - How you construct and invoke API clients (e.g., `SecretManagerServiceClient`, `StorageClient`). - Authentication tokens, Service Account keys, and OAuth2 credentials. - Request and response JSON payloads. -- **What changes**: - - Only the initial **TLS 1.3 cryptographic handshake** (Layer 4/6) performed when the client opens an HTTPS connection to Google Cloud service endpoints. By default, this under-the-hood improvement is completely seamless and requires **zero application code changes**. +- **What changes under the hood**: + - Only the initial **TLS 1.3 cryptographic handshake** (Layer 4/6) performed when establishing an HTTPS connection to Google Cloud service endpoints. The client automatically negotiates hybrid post-quantum key exchange (`X25519MLKEM768`) instead of classical-only key exchange (`X25519`). --- From ed25d37278de99bd43c82e86e1b03a046dda9414 Mon Sep 17 00:00:00 2001 From: Lawrence Qiu Date: Thu, 3 Sep 2026 19:21:00 +0000 Subject: [PATCH 19/25] docs: streamline platform section and highlight GraalVM --- docs/post_quantum_cryptography_guide.md | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/docs/post_quantum_cryptography_guide.md b/docs/post_quantum_cryptography_guide.md index 3ba509a3f5ac..a381dbbdab9b 100644 --- a/docs/post_quantum_cryptography_guide.md +++ b/docs/post_quantum_cryptography_guide.md @@ -100,20 +100,12 @@ Note the following performance and network considerations: --- -## 3. Deployment Environments & Platform Compatibility +## 3. Environment & Runtime Considerations -Because Conscrypt relies on C native shared libraries (`.so`, `.dylib`, or `.dll`) loaded via JNI, platform compatibility depends on the host operating system and container environment. +Because PQC negotiation relies on native BoringSSL C binaries (via Conscrypt) loaded over JNI, compatibility depends on the underlying runtime environment. Most standard Linux (`glibc`), macOS, and Windows environments support native execution out of the box. -### 3.1 Compatibility Matrix - -| Environment / OS | Status | Notes | -| :--- | :--- | :--- | -| **Standard Linux (e.g., Ubuntu, Debian, RHEL, CentOS — non-exhaustive)** | **Fully Supported** | Requires `glibc` 2.17+ (Conscrypt 2.6.2+) or `glibc` 2.35+ (Conscrypt 2.6.0). | -| **Google Cloud Managed (Cloud Run, GKE, App Engine)** | **Fully Supported** | Default base container environments use compatible `glibc` runtimes. | -| **macOS (Apple Silicon M-series & Intel)** | **Fully Supported** | Native `osx-aarch_64` and `osx-x86_64` binaries bundled in `conscrypt-openjdk-uber`. | -| **Windows (x86_64)** | **Fully Supported** | Native `windows-x86_64` binary bundled in `conscrypt-openjdk-uber`. | -| **GraalVM Native Image** | **Supported** | Supported when including appropriate reachability metadata and configuration for Conscrypt JNI libraries. | -| **Alpine Linux / Musl libc Containers** | **Fallback to Classical** | Conscrypt native binaries require `glibc`. On Alpine (`musl`), native loading is unsupported and safely falls back to standard classical TLS. | +### 3.1 GraalVM Native Image +GraalVM Native Image compilation is supported for applications that include the appropriate reachability metadata and JNI configuration for Conscrypt native libraries. ### 3.2 Unsupported Scenarios & Graceful Fallback Certain deployment environments do not support native Conscrypt binaries out of the box. In these scenarios, the client libraries do not fail; they gracefully fall back to the host JVM's default security provider (standard classical TLS): From 97b84b7809bb3bd851c1e9eb7c6884277500ceb0 Mon Sep 17 00:00:00 2001 From: Lawrence Qiu Date: Thu, 3 Sep 2026 19:28:13 +0000 Subject: [PATCH 20/25] docs: simplify HTTP/JSON handshake negotiation and remove redundant diagram --- docs/post_quantum_cryptography_guide.md | 34 ++++--------------------- 1 file changed, 5 insertions(+), 29 deletions(-) diff --git a/docs/post_quantum_cryptography_guide.md b/docs/post_quantum_cryptography_guide.md index a381dbbdab9b..ce6e74560b71 100644 --- a/docs/post_quantum_cryptography_guide.md +++ b/docs/post_quantum_cryptography_guide.md @@ -51,41 +51,17 @@ The Google Cloud Java SDK scopes Conscrypt strictly to Google Cloud Java SDK req - As a result, enabling Conscrypt for Google Cloud calls **does not alter the TLS behavior, cipher suites, or security providers of any other HTTP clients or libraries** in your application (e.g., Apache HttpClient, Spring WebClient, OkHttp, or direct `HttpsURLConnection` calls). Your existing JVM-wide cryptographic configurations remain completely undisturbed. ### 2.4 How Client and Google Cloud Endpoints Negotiate PQC -When a Google Cloud HTTP/JSON client initiates a connection, it advertises supported key exchange groups to the server in preference order. During the TLS 1.3 handshake, the first mutually supported algorithm that both the client and server agree upon is selected and used for the session: - +When a Google Cloud HTTP/JSON client initiates a connection, it advertises supported key exchange groups in preference order: 1. `X25519MLKEM768` *(Hybrid Post-Quantum Key Exchange)* 2. `MLKEM1024` *(Pure Post-Quantum Key Exchange)* 3. `X25519` *(Classical ECDH)* 4. `secp256r1` *(Classical ECDH)* 5. `secp384r1` *(Classical ECDH)* -> [!NOTE] -> **Algorithm Selection**: -> These named groups are selected because they are supported by Conscrypt (see [Conscrypt CAPABILITIES.md](https://github.com/google/conscrypt/blob/2.6.2/CAPABILITIES.md) and `HttpJsonConscryptUtils.DEFAULT_CONSCRYPT_NAMED_GROUPS`). If your application requires a cryptographic algorithm or named group not in this list, you can configure an alternative `SecurityProvider` (e.g., Bouncy Castle; see **Section 6, Option 3**). - -#### Handshake Negotiation Flow: -- **PQC-Enabled Google Cloud Endpoints**: Google Cloud frontends recognize `X25519MLKEM768` as their preferred group. The client and server agree on this hybrid algorithm, establishing a quantum-resistant TLS 1.3 session. -- **Non-PQC Endpoints / Middleboxes**: If a server or intermediate network proxy does not support post-quantum cryptography, it ignores the unrecognized post-quantum identifiers and selects the first mutually supported classical group (e.g., `X25519`). -- **Graceful Client Fallback**: If Conscrypt native libraries cannot load on the client host, the client seamlessly falls back to the environment's configured security provider (which defaults to standard JDK JSSE / `SunJSSE`), negotiating classical TLS 1.3. - - **Impact of Fallback**: Fallback is completely safe and non-breaking for application availability. Your API calls will continue to execute successfully without throwing errors or dropping traffic. The connection remains fully encrypted using industry-standard classical cryptography (such as `X25519` via standard JDK TLS); it simply does not include quantum-resistant hybrid key exchange for that session. - -``` -+-------------------------------------------------------------------------------+ -| Google Cloud HTTP/JSON Client Request | -+-------------------------------------------------------------------------------+ - | - Is Conscrypt JNI Available on This Platform? - | - +-------------------+-------------------+ - | | - [ YES ] [ NO ] - | | - v v - google-http-client uses Conscrypt Falls back to configured - Offers Hybrid PQC + Classical Groups security provider (JDK JSSE) - - Google Cloud negotiates X25519MLKEM768 - Negotiates classical X25519 - - Non-PQC endpoints fall back to X25519 via standard JDK SunJSSE -``` +During the TLS 1.3 handshake: +- **PQC-Enabled Google Cloud Endpoints**: Google Cloud frontends recognize and select `X25519MLKEM768`, establishing a quantum-resistant TLS 1.3 session. +- **Non-PQC Endpoints / Middleboxes**: If a server or intermediate network proxy does not support post-quantum cryptography, it ignores unrecognized post-quantum identifiers and standard TLS 1.3 negotiation selects the first mutually supported classical group (`X25519`). +- **Graceful Client Fallback**: If Conscrypt native libraries cannot load on the client host, `gax-httpjson` catches the linkage error and defaults to the environment's configured security provider (standard JDK `SunJSSE`), safely negotiating classical TLS 1.3 without failing application requests. ### 2.5 Performance & Network Considerations Note the following performance and network considerations: From 518b6b77b3dd492fc98846d8c47a5dd42d7a70d2 Mon Sep 17 00:00:00 2001 From: Lawrence Qiu Date: Thu, 3 Sep 2026 19:29:37 +0000 Subject: [PATCH 21/25] docs: dedicate section to fallback mechanics, triggers, implications, and compliance --- docs/post_quantum_cryptography_guide.md | 42 +++++++++++++------------ 1 file changed, 22 insertions(+), 20 deletions(-) diff --git a/docs/post_quantum_cryptography_guide.md b/docs/post_quantum_cryptography_guide.md index ce6e74560b71..1d03728d530b 100644 --- a/docs/post_quantum_cryptography_guide.md +++ b/docs/post_quantum_cryptography_guide.md @@ -83,46 +83,48 @@ Because PQC negotiation relies on native BoringSSL C binaries (via Conscrypt) lo ### 3.1 GraalVM Native Image GraalVM Native Image compilation is supported for applications that include the appropriate reachability metadata and JNI configuration for Conscrypt native libraries. -### 3.2 Unsupported Scenarios & Graceful Fallback -Certain deployment environments do not support native Conscrypt binaries out of the box. In these scenarios, the client libraries do not fail; they gracefully fall back to the host JVM's default security provider (standard classical TLS): - -- **Alpine Linux (`musl` libc)**: - Precompiled Conscrypt native binaries require `glibc` and cannot load on Alpine Linux or other `musl`-based container distributions (e.g., `eclipse-temurin:17-alpine`). On these platforms, Conscrypt native loading fails with an `UnsatisfiedLinkError`, and the client automatically falls back to classical TLS (`X25519`). Workloads requiring post-quantum hybrid key exchange should use a `glibc`-compatible base image (such as Debian, Ubuntu, or Wolfi). -- **Hardened Filesystems (`noexec /tmp`)**: - In security-hardened container or Kubernetes environments where `/tmp` is mounted with the `noexec` flag or the filesystem is strictly read-only, the JVM cannot load native shared libraries extracted to `/tmp`, resulting in an `UnsatisfiedLinkError` (`failed to map segment from shared object: Operation not permitted`). The client safely falls back to classical TLS. If PQC is required in these environments, configure an executable working directory using JVM system properties (e.g., `-Dorg.conscrypt.native.workdir=/path/to/executable/dir`). - -### 3.3 Classpath Isolation & Version Skew Warning +### 3.2 Classpath Isolation & Version Skew Warning If your project uses multiple dependencies that transitively pull in different versions of Conscrypt (e.g., older versions like `2.5.2` alongside `2.6.2`), a JNI ABI mismatch can occur during JVM classloading. Always ensure your build tool (Maven/Gradle) resolves `conscrypt-openjdk-uber` to version `2.6.0+` (or `2.6.2+`) consistently. One possible solution for this is to use Google Cloud's `libraries-bom` (version `26.86.0+`) to manage dependency versions, ensuring a consistent and compatible Conscrypt runtime across all Google Cloud client libraries. --- -## 4. Important Warning: Availability vs. Strict Compliance +## 4. Classical Fallback: Mechanics, Implications & Concerns Google Cloud Java client libraries follow a deliberate architectural principle: **prefer service availability over hard failures**. -### 4.1 The Silent Fallback Behavior -If Conscrypt native libraries fail to initialize—due to an unsupported operating system, missing `glibc`, permission issues, or file extraction limits—`gax-httpjson` catches the exception and logs a message at **`Level.FINE` (debug level)**: +### 4.1 Fallback Mechanics: Availability Over Hard Failures +If Conscrypt native libraries cannot load on the host platform—due to an unsupported operating system, missing `glibc`, permission constraints, or file extraction limits—`gax-httpjson` catches the exception and logs a debug message at `Level.FINE`: ```text -FINE: Conscrypt native libraries not available. Falling back to JDK TLS. +FINE: Conscrypt native library unavailable. Falling back to default JDK TLS. ``` The client then proceeds to establish standard classical TLS using the host JVM's configured security provider (by default `SunJSSE`). **Why does it behave this way?** -To protect production workloads. A customer updating dependencies or migrating container images should not experience broken API calls or catastrophic application outages simply because a native optimization library could not load on their environment. +To protect production workloads. Updating dependencies or migrating container images should not cause broken API calls or catastrophic application outages simply because a native optimization library could not load on a given runtime. + +### 4.2 Common Scenarios Triggering Fallback +Several operational conditions can trigger a fallback to classical TLS: +- **Alpine Linux (`musl` libc)**: + Precompiled Conscrypt native binaries require `glibc` and cannot load on Alpine Linux or other `musl`-based container distributions (e.g., `eclipse-temurin:17-alpine`). On these platforms, Conscrypt native loading fails with an `UnsatisfiedLinkError`, and the client automatically falls back to classical TLS (`X25519`). Workloads requiring post-quantum hybrid key exchange should use a `glibc`-compatible base image (such as Debian, Ubuntu, or Wolfi). +- **Hardened Filesystems (`noexec /tmp`)**: + In security-hardened container or Kubernetes environments where `/tmp` is mounted with the `noexec` flag or the filesystem is strictly read-only, the JVM cannot load native shared libraries extracted to `/tmp`, resulting in an `UnsatisfiedLinkError` (`failed to map segment from shared object: Operation not permitted`). The client safely falls back to classical TLS. If PQC is required in these environments, configure an executable working directory using JVM system properties (e.g., `-Dorg.conscrypt.native.workdir=/path/to/executable/dir`). +- **Non-PQC Endpoints & Middleboxes**: + If a server endpoint or an intermediate network proxy does not support post-quantum cryptography, standard TLS 1.3 negotiation naturally selects the first mutually supported classical algorithm (`X25519`). -**What fallback means for your application**: -- **Application Availability**: Requests continue to succeed normally. No exceptions or errors are raised to application code. -- **Security Baseline**: Traffic remains fully encrypted with classical TLS 1.3 (e.g., ECDHE with AES-GCM), maintaining the standard security posture that Java applications use today. -- **What is absent**: The connection will not be protected against future post-quantum decryption (SNDL). +### 4.3 Security & Operational Implications +When fallback occurs, understand what this means for your workload: +- **Application Availability (Preserved)**: Requests continue to succeed normally. No exceptions or errors are raised to application code. +- **Security Baseline (Preserved)**: Traffic remains fully encrypted with standard classical TLS 1.3 (e.g., ECDHE with AES-GCM), maintaining the standard security posture that Java applications use today. +- **Post-Quantum Protection (Absent)**: The connection will **not** be protected against future quantum decryption. Encrypted traffic archived by adversaries remains susceptible to future Store-Now, Decrypt-Later (SNDL) attacks. -### 4.2 The Compliance Warning +### 4.4 Regulatory & Compliance Concerns (Silent Fallback Warning) > [!WARNING] > **Active Verification is Required for Regulatory Mandates**: > If your organization operates under strict compliance, governmental, or corporate security mandates requiring Post-Quantum Cryptography today, **you cannot rely solely on the default configuration without verification**. > -> Because fallback to classical TLS is silent and non-breaking by design, an unexpected environment change (such as switching to an Alpine-based Docker container or changing filesystem mount permissions) could downgrade your connections from hybrid PQC to classical TLS **without throwing exceptions or failing requests**. +> Because fallback to classical TLS is silent and non-breaking by design, an unexpected environment change (such as switching base container images to Alpine or changing filesystem mount permissions) could downgrade your connections from hybrid PQC to classical TLS **without throwing exceptions or failing requests**. > > If PQC is a mandatory requirement for your workload, you must implement automated verification in your CI/CD pipelines or startup health checks (see **Section 5**). From 5906f5fbd4483f4532f5d2783d9eecc61b46eebc Mon Sep 17 00:00:00 2001 From: Lawrence Qiu Date: Thu, 3 Sep 2026 19:56:49 +0000 Subject: [PATCH 22/25] docs: remove verbose transport connection characteristics section --- docs/post_quantum_cryptography_guide.md | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/docs/post_quantum_cryptography_guide.md b/docs/post_quantum_cryptography_guide.md index 1d03728d530b..59269e8c3767 100644 --- a/docs/post_quantum_cryptography_guide.md +++ b/docs/post_quantum_cryptography_guide.md @@ -63,16 +63,6 @@ During the TLS 1.3 handshake: - **Non-PQC Endpoints / Middleboxes**: If a server or intermediate network proxy does not support post-quantum cryptography, it ignores unrecognized post-quantum identifiers and standard TLS 1.3 negotiation selects the first mutually supported classical group (`X25519`). - **Graceful Client Fallback**: If Conscrypt native libraries cannot load on the client host, `gax-httpjson` catches the linkage error and defaults to the environment's configured security provider (standard JDK `SunJSSE`), safely negotiating classical TLS 1.3 without failing application requests. -### 2.5 Performance & Network Considerations -Note the following performance and network considerations: -- **TLS Handshake Size Overhead**: - - Classical `X25519` public keys are very compact: **32 bytes**. - - `ML-KEM-768` public keys are **1,184 bytes**, and ciphertexts are **1,088 bytes**. - - Consequently, the TLS `ClientHello` and `ServerHello` messages increase by approximately **1 to 2 kilobytes**. -- **Persistent HTTP Connections (`Keep-Alive`) & API Latency**: - - The underlying HTTP transport (`NetHttpTransport` backed by Java's `HttpURLConnection`) supports standard HTTP persistent connections (`Keep-Alive`). - - When connections are reused from Java's connection cache, the TLS handshake occurs **only once** when establishing the connection. - - Subsequent API requests routed through that active connection reuse the existing TLS session without repeating the handshake. The latency impact of the larger handshake therefore primarily applies to new connection establishment rather than every individual API call. (Note that applications experiencing high connection churn or making infrequent calls outside the keep-alive window will perform new handshakes more often.) --- From 7e88adc6188fbb1bed9617c3c303eacd7e3cc6ee Mon Sep 17 00:00:00 2001 From: Lawrence Qiu Date: Thu, 3 Sep 2026 20:13:27 +0000 Subject: [PATCH 23/25] docs: streamline BOM recommendation, Conscrypt bridge, supported groups, and fallback section --- docs/post_quantum_cryptography_guide.md | 69 ++++++++++--------------- 1 file changed, 28 insertions(+), 41 deletions(-) diff --git a/docs/post_quantum_cryptography_guide.md b/docs/post_quantum_cryptography_guide.md index 59269e8c3767..cbde36bdeab7 100644 --- a/docs/post_quantum_cryptography_guide.md +++ b/docs/post_quantum_cryptography_guide.md @@ -27,20 +27,21 @@ Enabling PQC in Google Cloud Java client libraries requires **zero changes to ap ## 2. HTTP/JSON Transport Architecture & Defaults ### 2.1 Minimum Required Versions -PQC enablement for HTTP/JSON transport requires compatible versions of `conscrypt-openjdk-uber`, `gax-httpjson`, and `google-http-client`: +We recommend using Google Cloud's **`libraries-bom` (version `26.86.0+`)** to guarantee that dependencies have compatible, required versions. + +If managing dependencies directly, ensure the following minimum versions are present: | Library | Minimum Version | Role | | :--- | :--- | :--- | -| **`libraries-bom`** | `26.86.0+` | **Recommended**. Central BOM managing compatible versions across all Google Cloud client libraries. | | **`gax-httpjson`** | `2.83.0+` | Automatically configures Conscrypt as the TLS security provider and sets PQC named groups. | | **`google-http-client`** | `2.2.0+` | Provides transport-level security provider registration on `NetHttpTransport.Builder`. | | **`conscrypt-openjdk-uber`** | `2.6.0+` *(2.6.2+ recommended)* | Provides Google's BoringSSL native C engine and TLS 1.3 PQC hybrid named groups. | ### 2.2 Why Conscrypt? -Built-in Java Development Kits (Java 8 through Java 26) do not support Post-Quantum Cryptography in their default Java Secure Socket Extension provider (`SunJSSE`). While native ML-KEM support is in development for future Java releases (**JDK 27+** via [JEP 496](https://openjdk.org/jeps/496)), requiring all production enterprise workloads to immediately upgrade to bleeding-edge JDK versions is impractical. +Built-in Java Development Kits (Java 8 - 26) do not support Post-Quantum Cryptography in their default Java Secure Socket Extension provider (`SunJSSE`). While native ML-KEM support is in development for future Java releases (**JDK 27+** via [JEP 496](https://openjdk.org/jeps/496)), requiring all production enterprise workloads to immediately upgrade to bleeding-edge JDK versions is impractical. -To bridge this gap, Google Cloud Java client libraries use **Conscrypt** (`conscrypt-openjdk-uber`) as the default security provider for HTTP/JSON transport: -1. **Immediate PQC Availability Across Java 8+**: Conscrypt embeds Google's open-source BoringSSL cryptographic engine via Java Native Interface (JNI). This enables quantum-resistant TLS 1.3 handshakes on existing production runtimes (Java 8, 11, 17, 21, and 25). +To bridge until users can upgrade to JDK 27+, Google Cloud Java client libraries use **Conscrypt** (`conscrypt-openjdk-uber`) as the default security provider for HTTP/JSON transport: +1. **Immediate PQC Availability Across Java 8 - 26**: Conscrypt embeds Google's open-source BoringSSL cryptographic engine via Java Native Interface (JNI). This enables quantum-resistant TLS 1.3 handshakes on existing production runtimes. 2. **Zero Code Changes**: When `gax-httpjson` detects compatible Conscrypt libraries on the classpath, it automatically configures the HTTPS transport without requiring manual SSLContext setup. 3. **High Performance**: BoringSSL contains hardware-accelerated assembly optimizations for modern CPU architectures (x86_64 and ARM64). @@ -50,19 +51,15 @@ The Google Cloud Java SDK scopes Conscrypt strictly to Google Cloud Java SDK req - `gax-httpjson` configures the Conscrypt `Provider` instance directly on the client's internal `NetHttpTransport.Builder` rather than installing it into the global JVM security registry (`java.security.Security.addProvider(...)`). - As a result, enabling Conscrypt for Google Cloud calls **does not alter the TLS behavior, cipher suites, or security providers of any other HTTP clients or libraries** in your application (e.g., Apache HttpClient, Spring WebClient, OkHttp, or direct `HttpsURLConnection` calls). Your existing JVM-wide cryptographic configurations remain completely undisturbed. -### 2.4 How Client and Google Cloud Endpoints Negotiate PQC -When a Google Cloud HTTP/JSON client initiates a connection, it advertises supported key exchange groups in preference order: +### 2.4 Supported Key Exchange Algorithms & Preference Order +HTTP/JSON clients advertise supported key exchange groups in the following preference order: 1. `X25519MLKEM768` *(Hybrid Post-Quantum Key Exchange)* 2. `MLKEM1024` *(Pure Post-Quantum Key Exchange)* 3. `X25519` *(Classical ECDH)* 4. `secp256r1` *(Classical ECDH)* 5. `secp384r1` *(Classical ECDH)* -During the TLS 1.3 handshake: -- **PQC-Enabled Google Cloud Endpoints**: Google Cloud frontends recognize and select `X25519MLKEM768`, establishing a quantum-resistant TLS 1.3 session. -- **Non-PQC Endpoints / Middleboxes**: If a server or intermediate network proxy does not support post-quantum cryptography, it ignores unrecognized post-quantum identifiers and standard TLS 1.3 negotiation selects the first mutually supported classical group (`X25519`). -- **Graceful Client Fallback**: If Conscrypt native libraries cannot load on the client host, `gax-httpjson` catches the linkage error and defaults to the environment's configured security provider (standard JDK `SunJSSE`), safely negotiating classical TLS 1.3 without failing application requests. - +Because Google Cloud servers support PQC algorithms, `X25519MLKEM768` will typically be selected. If an intermediate proxy or non-PQC endpoint does not support post-quantum cryptography, standard TLS 1.3 negotiation selects the first mutually supported classical group (`X25519`). --- @@ -80,36 +77,8 @@ One possible solution for this is to use Google Cloud's `libraries-bom` (version --- -## 4. Classical Fallback: Mechanics, Implications & Concerns - -Google Cloud Java client libraries follow a deliberate architectural principle: **prefer service availability over hard failures**. - -### 4.1 Fallback Mechanics: Availability Over Hard Failures -If Conscrypt native libraries cannot load on the host platform—due to an unsupported operating system, missing `glibc`, permission constraints, or file extraction limits—`gax-httpjson` catches the exception and logs a debug message at `Level.FINE`: -```text -FINE: Conscrypt native library unavailable. Falling back to default JDK TLS. -``` -The client then proceeds to establish standard classical TLS using the host JVM's configured security provider (by default `SunJSSE`). - -**Why does it behave this way?** -To protect production workloads. Updating dependencies or migrating container images should not cause broken API calls or catastrophic application outages simply because a native optimization library could not load on a given runtime. - -### 4.2 Common Scenarios Triggering Fallback -Several operational conditions can trigger a fallback to classical TLS: -- **Alpine Linux (`musl` libc)**: - Precompiled Conscrypt native binaries require `glibc` and cannot load on Alpine Linux or other `musl`-based container distributions (e.g., `eclipse-temurin:17-alpine`). On these platforms, Conscrypt native loading fails with an `UnsatisfiedLinkError`, and the client automatically falls back to classical TLS (`X25519`). Workloads requiring post-quantum hybrid key exchange should use a `glibc`-compatible base image (such as Debian, Ubuntu, or Wolfi). -- **Hardened Filesystems (`noexec /tmp`)**: - In security-hardened container or Kubernetes environments where `/tmp` is mounted with the `noexec` flag or the filesystem is strictly read-only, the JVM cannot load native shared libraries extracted to `/tmp`, resulting in an `UnsatisfiedLinkError` (`failed to map segment from shared object: Operation not permitted`). The client safely falls back to classical TLS. If PQC is required in these environments, configure an executable working directory using JVM system properties (e.g., `-Dorg.conscrypt.native.workdir=/path/to/executable/dir`). -- **Non-PQC Endpoints & Middleboxes**: - If a server endpoint or an intermediate network proxy does not support post-quantum cryptography, standard TLS 1.3 negotiation naturally selects the first mutually supported classical algorithm (`X25519`). - -### 4.3 Security & Operational Implications -When fallback occurs, understand what this means for your workload: -- **Application Availability (Preserved)**: Requests continue to succeed normally. No exceptions or errors are raised to application code. -- **Security Baseline (Preserved)**: Traffic remains fully encrypted with standard classical TLS 1.3 (e.g., ECDHE with AES-GCM), maintaining the standard security posture that Java applications use today. -- **Post-Quantum Protection (Absent)**: The connection will **not** be protected against future quantum decryption. Encrypted traffic archived by adversaries remains susceptible to future Store-Now, Decrypt-Later (SNDL) attacks. +## 4. Classical Fallback -### 4.4 Regulatory & Compliance Concerns (Silent Fallback Warning) > [!WARNING] > **Active Verification is Required for Regulatory Mandates**: > If your organization operates under strict compliance, governmental, or corporate security mandates requiring Post-Quantum Cryptography today, **you cannot rely solely on the default configuration without verification**. @@ -118,6 +87,24 @@ When fallback occurs, understand what this means for your workload: > > If PQC is a mandatory requirement for your workload, you must implement automated verification in your CI/CD pipelines or startup health checks (see **Section 5**). +### 4.1 Security & Operational Implications +When fallback occurs: +- **Application Availability (Preserved)**: Requests continue to succeed normally. No exceptions or errors are raised to application code. +- **Security Baseline (Preserved)**: Traffic remains fully encrypted with standard classical TLS 1.3 (e.g., ECDHE with AES-GCM), maintaining the standard security posture that Java applications use today. +- **Post-Quantum Protection (Absent)**: The connection will **not** be protected against future quantum decryption. Encrypted traffic archived by adversaries remains susceptible to future Store-Now, Decrypt-Later (SNDL) attacks. + +### 4.2 How to Detect Fallback +If Conscrypt native libraries fail to load (or are unavailable on the host platform), `gax-httpjson` catches the linkage error, logs a debug message at `Level.FINE`, and defaults to standard JDK TLS (`SunJSSE`): +```text +FINE: Conscrypt native library unavailable. Falling back to default JDK TLS. +``` +See **Section 5** for instructions on enabling internal logging or tracing TLS handshakes to verify whether your application is using PQC. + +### 4.3 Common Triggers for Fallback +- **Alpine Linux (`musl` libc)**: Precompiled Conscrypt binaries require `glibc`. On `musl`-based distributions (e.g., `alpine`), Conscrypt cannot load and falls back to classical TLS. Use a `glibc`-compatible base image (such as Debian, Ubuntu, or Wolfi) for PQC. +- **Hardened Filesystems (`noexec /tmp`)**: If `/tmp` is mounted with `noexec` or is read-only, Conscrypt cannot load extracted native libraries. To enable PQC, specify an executable directory via `-Dorg.conscrypt.native.workdir=/path/to/executable/dir`. +- **Non-PQC Endpoints or Middleboxes**: If a network proxy or endpoint does not support PQC, TLS 1.3 negotiation automatically selects classical `X25519`. + --- ## 5. How to Verify PQC Negotiation From cc94dad43dda635856ec7bb8512c696769305fc9 Mon Sep 17 00:00:00 2001 From: Lawrence Qiu Date: Thu, 3 Sep 2026 20:20:24 +0000 Subject: [PATCH 24/25] docs: simplify scoped provider, link Conscrypt capabilities, remove warning example, and rename to Fallback Implications --- docs/post_quantum_cryptography_guide.md | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/docs/post_quantum_cryptography_guide.md b/docs/post_quantum_cryptography_guide.md index cbde36bdeab7..c49228d710fb 100644 --- a/docs/post_quantum_cryptography_guide.md +++ b/docs/post_quantum_cryptography_guide.md @@ -46,13 +46,10 @@ To bridge until users can upgrade to JDK 27+, Google Cloud Java client libraries 3. **High Performance**: BoringSSL contains hardware-accelerated assembly optimizations for modern CPU architectures (x86_64 and ARM64). ### 2.3 Scoped Security Provider (No Global JVM Impact) -The Google Cloud Java SDK scopes Conscrypt strictly to Google Cloud Java SDK requests: - -- `gax-httpjson` configures the Conscrypt `Provider` instance directly on the client's internal `NetHttpTransport.Builder` rather than installing it into the global JVM security registry (`java.security.Security.addProvider(...)`). -- As a result, enabling Conscrypt for Google Cloud calls **does not alter the TLS behavior, cipher suites, or security providers of any other HTTP clients or libraries** in your application (e.g., Apache HttpClient, Spring WebClient, OkHttp, or direct `HttpsURLConnection` calls). Your existing JVM-wide cryptographic configurations remain completely undisturbed. +The Google Cloud Java SDK scopes Conscrypt strictly to Google Cloud client requests and avoids modifying global JVM security defaults. As a result, enabling Conscrypt for Google Cloud calls **does not alter the TLS behavior, cipher suites, or security providers of any other HTTP clients or libraries** in your application (e.g., Apache HttpClient, Spring WebClient, OkHttp, or direct `HttpsURLConnection` calls). ### 2.4 Supported Key Exchange Algorithms & Preference Order -HTTP/JSON clients advertise supported key exchange groups in the following preference order: +Based on [Conscrypt's supported named groups](https://github.com/google/conscrypt/blob/2.6.2/CAPABILITIES.md#supported-named-groups), HTTP/JSON clients advertise supported key exchange groups in the following preference order: 1. `X25519MLKEM768` *(Hybrid Post-Quantum Key Exchange)* 2. `MLKEM1024` *(Pure Post-Quantum Key Exchange)* 3. `X25519` *(Classical ECDH)* @@ -83,11 +80,11 @@ One possible solution for this is to use Google Cloud's `libraries-bom` (version > **Active Verification is Required for Regulatory Mandates**: > If your organization operates under strict compliance, governmental, or corporate security mandates requiring Post-Quantum Cryptography today, **you cannot rely solely on the default configuration without verification**. > -> Because fallback to classical TLS is silent and non-breaking by design, an unexpected environment change (such as switching base container images to Alpine or changing filesystem mount permissions) could downgrade your connections from hybrid PQC to classical TLS **without throwing exceptions or failing requests**. +> Because fallback to classical TLS is silent and non-breaking by design, an unexpected environment change could downgrade your connections from hybrid PQC to classical TLS **without throwing exceptions or failing requests**. > > If PQC is a mandatory requirement for your workload, you must implement automated verification in your CI/CD pipelines or startup health checks (see **Section 5**). -### 4.1 Security & Operational Implications +### 4.1 Fallback Implications When fallback occurs: - **Application Availability (Preserved)**: Requests continue to succeed normally. No exceptions or errors are raised to application code. - **Security Baseline (Preserved)**: Traffic remains fully encrypted with standard classical TLS 1.3 (e.g., ECDHE with AES-GCM), maintaining the standard security posture that Java applications use today. From 4aaa7dc9e3e555cde837bc6951f467bb0660617d Mon Sep 17 00:00:00 2001 From: Lawrence Qiu Date: Fri, 4 Sep 2026 02:43:55 +0000 Subject: [PATCH 25/25] docs: update JDK 27 section title, link to Option 2, and remove future-proofing commitment --- docs/post_quantum_cryptography_guide.md | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/docs/post_quantum_cryptography_guide.md b/docs/post_quantum_cryptography_guide.md index c49228d710fb..78b0277ebe24 100644 --- a/docs/post_quantum_cryptography_guide.md +++ b/docs/post_quantum_cryptography_guide.md @@ -289,9 +289,8 @@ try (SecretManagerServiceClient client = SecretManagerServiceClient.create(setti --- -## 7. Future Outlook: Native OpenJDK PQC Support (JDK 27+) +## 7. Native OpenJDK PQC Support (JDK 27+) -The cryptographic landscape is continually advancing. The OpenJDK community is integrating standardized post-quantum algorithms directly into the Java platform: +The OpenJDK community is integrating standardized post-quantum algorithms directly into the Java platform: - **[JEP 496](https://openjdk.org/jeps/496) (ML-KEM)**: Introduces native implementations of NIST FIPS 203 (Module-Lattice-Based Key-Encapsulation Mechanism) into OpenJDK's standard security providers (`SunJSSE` and `SunJCE`), targeted for **JDK 27+**. -- **What this means for Google Cloud Java**: Once JDK 27 becomes standard in production environments, Java applications will be capable of negotiating hybrid and pure post-quantum TLS natively without requiring JNI shared libraries or third-party dependencies like Conscrypt. -- **Future-Proofing**: As native JDK capabilities mature, Google Cloud Java client libraries will adapt to take advantage of built-in JVM providers, preserving a seamless, zero-maintenance security upgrade path for all users. +- **What this means for Google Cloud Java**: On JDK 27+, applications configuring the standard JDK security provider (see **Option 2** in Section 6) will negotiate post-quantum TLS natively using `SunJSSE`, without requiring Conscrypt or JNI native shared libraries.