-
Notifications
You must be signed in to change notification settings - Fork 1.2k
docs: Add a Http/Json Post-Quantum Cryptography Guide #13963
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Draft
lqiu96
wants to merge
6
commits into
main
Choose a base branch
from
pqc-user-guide
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Draft
Changes from all commits
Commits
Show all changes
6 commits
Select commit
Hold shift + click to select a range
fbb6c26
docs: add Post-Quantum Cryptography (PQC) User Guide
lqiu96 8248bc3
docs: refine PQC user guide for HTTP/JSON transport with verification…
lqiu96 a2be787
docs: remove mTLS/gRPC references, add default algorithms and fallbac…
lqiu96 cd1d649
docs: refine HTTP/JSON PQC guide with exact versions, concise intro, …
lqiu96 ea66642
docs: reorganize HTTP/JSON PQC guide with versions first and clarify …
lqiu96 67661f5
docs: update PQC guide with debug-level logging and prominent WARNING…
lqiu96 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,244 @@ | ||
| # Post-Quantum Cryptography (PQC) User Guide for HTTP/JSON Java Client Libraries | ||
|
|
||
| ## 1. The Quantum Threat & Why PQC is Critical | ||
|
|
||
| Traditional TLS public-key encryption (such as RSA and ECDH) is vulnerable to future decryption by quantum computers. | ||
|
|
||
| - **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. | ||
|
|
||
| --- | ||
|
|
||
| ## 2. HTTP/JSON (REST) Client Library Support | ||
|
|
||
| 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 | ||
|
|
||
| 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 | | ||
| | :--- | :--- | :--- | | ||
| | **`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`. | | ||
|
|
||
| ### 2.2 Why Conscrypt? | ||
|
|
||
| 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. | ||
|
|
||
| **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 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. | ||
|
|
||
| ``` | ||
| +-------------------------------------------------------------------+ | ||
| | 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 | ||
| ``` | ||
|
|
||
| ### 2.4 Supported Key Exchange Groups | ||
|
|
||
| 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` | ||
|
|
||
| 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 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. 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 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 | ||
|
|
||
| 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 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 | ||
| ``` | ||
| - 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 | ||
|
|
||
| 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 | ||
|
|
||
| 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; | ||
|
|
||
| // 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) { | ||
| // Ignore or log socket configuration failure | ||
| } | ||
| } | ||
| }) | ||
| .build(); | ||
|
|
||
| // Step 2: Build transport channel provider using the custom transport | ||
| InstantiatingHttpJsonChannelProvider transportChannelProvider = | ||
| SecretManagerServiceSettings.defaultHttpJsonTransportProviderBuilder() | ||
| .setHttpTransport(transport) | ||
| .build(); | ||
|
|
||
| // Step 3: Instantiate client with settings | ||
| SecretManagerServiceSettings settings = | ||
| SecretManagerServiceSettings.newHttpJsonBuilder() | ||
| .setTransportChannelProvider(transportChannelProvider) | ||
| .build(); | ||
|
|
||
| try (SecretManagerServiceClient client = SecretManagerServiceClient.create(settings)) { | ||
| // Client communicates using classical X25519 TLS 1.3 | ||
| } | ||
| ``` | ||
|
|
||
| #### Alternative 2: Bypassing Conscrypt to Use Standard JDK JSSE | ||
|
|
||
| To bypass Conscrypt completely and use the standard JDK JSSE TLS 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 a standard NetHttpTransport without GAX 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 communicates using standard JDK JSSE TLS | ||
| } | ||
| ``` | ||
|
|
||
| #### 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(...)`: | ||
|
|
||
| ```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.Provider; | ||
|
|
||
| // Step 1: Instantiate custom security provider | ||
| Provider customProvider = new org.bouncycastle.jce.provider.BouncyCastleProvider(); | ||
|
|
||
| // Step 2: Configure NetHttpTransport with custom security provider and SSLSocketConfigurator | ||
| NetHttpTransport customTransport = | ||
| new NetHttpTransport.Builder() | ||
| .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) | ||
| .build(); | ||
|
|
||
| SecretManagerServiceSettings settings = | ||
| SecretManagerServiceSettings.newHttpJsonBuilder() | ||
| .setTransportChannelProvider(transportProvider) | ||
| .build(); | ||
|
|
||
| try (SecretManagerServiceClient client = SecretManagerServiceClient.create(settings)) { | ||
| // Client communicates using custom security provider scoped strictly to this transport | ||
| } | ||
| ``` | ||
|
|
||
| --- | ||
|
|
||
| ## 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). | ||
| - **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+. | ||
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
NetHttpTransport.Builderdoes not have asetSecurityProvidermethod. To use a custom security provider, you should configure anSSLContextwith the custom provider and set theSSLSocketFactoryon the builder.