Welcome to Chapter 4!
In the previous chapter, Certificate Loader, we built a utility to find and load our cryptographic keys from the disk. Before that, in TLS Credentials Factory, we built the machinery to create secure connections.
We have the lock, and we have the key. But here is the scary question: Is the door actually locked?
In cryptography, it is very easy to think you are secure when you are not.
We need a Quality Assurance (QA) Layer. We call this the PQC Validation Suite.
It is a collection of scripts and tests that act like a safety inspector. It pokes and prods our system to prove that we are actually using ML-KEM (Kyber) or ML-DSA (Dilithium) algorithms on the wire.
Before we even run our code, we need to check our environment. Post-Quantum Cryptography is new. It requires OpenSSL 3.5+. If you try to run this on an old laptop with OpenSSL 1.1, it won't work.
We use a script called tls_groups_check.sh to verify the "engine" of our car before we start the engine.
This script asks OpenSSL: "Do you know how to speak PQC?"
# From scripts/tls_groups_check.sh
# 1. Check Version (Must be >= 3.5.0)
openssl version
# 2. Check for Key Encapsulation Mechanisms (KEM)
# We look for "mlkem", "kyber", or "ml-kem"
openssl list -kem-algorithms | grep -iE 'mlkem|kyber'
What this does:
ml-kem-768 or similar, it gives us a green light.Now that we know the environment is good, we need to test our C++ code.
We write an Integration Test using Google Test. This test spins up a real Server and a real Client inside the test memory. They talk to each other, and we check the transcript.
We want to prove that when Client connects to Server, they negotiate a Hybrid Group (Classical X25519 + Post-Quantum ML-KEM).
Let's look at tests/test_tls_handshake.cpp.
We use the Factory we built in Chapter 2.
// Inside the test body
pqc_common::CertConfig config = GetTestConfig(); // Helper to get paths
// Create credentials with PQC enabled (true)
auto server_creds = pqc_common::CreateServerCredentials(config, true);
grpc::ServerBuilder builder;
builder.AddListeningPort("localhost:50551", server_creds);
// ... Start the server ...
The client also uses our Factory.
// Create client credentials, also PQC enabled
auto channel_creds = pqc_common::CreateChannelCredentials(config, true);
// Dial the server
auto channel = grpc::CreateChannel("localhost:50551", channel_creds);
auto stub = pqc::servicea::ServiceA::NewStub(channel);
After the client sends a message ("hello-pqc"), the server replies. The critical part is checking how they talked.
// The server sends back the group name it used
// We expect something like "X25519MLKEM768" (Hybrid)
EXPECT_FALSE(response.negotiated_group().empty());
if (response.negotiated_group() != "unknown") {
// Verify it contains the magic PQC words
EXPECT_TRUE(response.negotiated_group().find("MLKEM") != std::string::npos);
}
Explanation: If this test passes, we have mathematical proof that our C++ code is correctly instructing the underlying library to use Post-Quantum algorithms.
What happens if an old client (who doesn't understand PQC) tries to connect? We don't want the server to crash or reject them (unless we want strict security). We want Backward Compatibility.
We test this in tests/test_fallback.cpp.
// Create Client credentials with PQC DISABLED (false)
auto old_client_creds = pqc_common::CreateChannelCredentials(config, false);
// Connect to the SAME PQC-enabled server
auto channel = grpc::CreateChannel("localhost:50551", old_client_creds);
The Expectation:
The connection should succeed, but the negotiated_group should be "Classical" (like X25519 or secp256r1), not ML-KEM.
How does the suite orchestrate all this?
Unit tests are great, but sometimes we want to see the "wire" traffic ourselves. For this, we use the scripts/validate_tls.sh tool.
This script acts like a hacker or a network inspector. It uses the openssl s_client command-line tool to inspect the handshake from the outside.
# Inside scripts/validate_tls.sh
# Connect to our running server and verify the groups
openssl s_client -connect localhost:50051 \
-groups X25519MLKEM768:x25519 \
-CAfile certs/ca.pem
The script then scans the text output for a specific line:
Server Temp Key: X25519MLKEM768
Let's put it all together. You are a developer deploying this system. How do you ensure it's working?
# 1. Check tools
./scripts/tls_groups_check.sh
# Output: "All checks passed"
# 2. Run C++ Integration Tests
./build/tests/test_tls_handshake
# Output: "[ PASSED ] 1 test."
# 3. Run Wire Verification
./scripts/validate_tls.sh
# Output: "validate_tls: hybrid PQC group negotiated (Server Temp Key): X25519MLKEM768"
If you see these three checks pass, you can sleep soundly knowing your application is quantum-resistant.
In this chapter, we built the PQC Validation Suite. We learned that implementing crypto isn't enough; we must verify it.
tls_groups_check.sh.test_tls_handshake.cpp.test_fallback.cpp.validate_tls.sh.Now that we know our system is secure and running, we need to know how well it is running. Is the encryption slowing us down? How many bytes are we sending?
In the next chapter, we will build a system to watch the performance.
Next Chapter: TLS Metrics Observer
Generated by Code IQ