Logo
blank Skip to main content

PQC Testing: Why Post-Quantum Needs a Special Security Testing Approach (+ Practical Examples)

QA

Key takeaways:

  • Poorly implemented quantum‑safe algorithms can still leak data, break interoperability, or fail under active attack.
  • Consequences of potential quantum attacks can be severe, from long‑term exposure of sensitive data to system‑wide outages and silent degradation of security guarantees.
  • Key goals of PQC testing include ensuring that PQC algorithms are implemented correctly and checking that they perform as intended even under heavy load (like in real-world systems).
  • PQC security testing is crucial to evaluate how well your algorithms can withstand MITM attacks and other threats.

Adopting post‑quantum cryptography (PQC) is now a strategic necessity for any security‑focused product or infrastructure.

But while most organizations correctly focus on selecting and integrating NIST‑approved algorithms like ML‑KEM (Kyber), ML‑DSA (Dilithium), or SLH‑DSA, an uncomfortable truth remains:

Cryptographic migration without proper testing is more dangerous than not migrating at all.

In this article, we guide you through:

✓ Actual benefits of PQC testing

✓ Key attack vectors to keep in mind

✓ Main emulation tools to use for protection

✓ Practical testing scenarios and how to interpret results

Why PQC testing is a must

Why PQC testing is a must

PQC implementations help your product prepare for the threats of the post‑quantum world, such as the famous harvest now, decrypt later risks.

At Apriorit, we’ve seen many requests for assisting with PQC adoption. What we’ve also noticed across various projects is that even if your team integrates PQC by the book, you can’t assume your system is secure until you test how your PQC implementation behaves in real-life conditions. This is because:

1. PQC implementations are complex and highly error-prone. Real‑world PQC failures come from the wrong key encapsulation flow, encoding/decoding mismatches across components, and side‑channel vulnerabilities in software implementations. PQC algorithms are more sensitive to timing, cache access, and memory operations than classical RSA/ECC.

Only dedicated PQC testing — including negative testing, boundary cases, side-channel simulation, and multi‑platform runs — can uncover these implementation‑specific flaws.

2. PQC breaks interoperability, which can break your product. Unlike classical RSA/ECC algorithms, PQC algorithms generate larger payloads, require multi‑message exchanges, and increase handshake times and packet fragmentation. One untested handshake on a single poorly configured device can break the entire communication chain.

PQC migration requires cross‑platform, cross‑version, and hybrid interoperability testing. Otherwise, you can miss issues like Transport Layer Security (TLS) handshake failures and broken certificate chains.

3. PQC implementation might impact performance, depending on what algorithms you use and for what purpose. There’s a risk of slowing down mobile apps, on‑device encryption, embedded and automotive ECUs, and low-resource IoT devices. Skipping PQC performance testing can potentially lead to increased latency, unexpected server CPU spikes, and scalability issues on SaaS platforms.

Performance issues can’t be fully predicted based on documentation. To discover them, you need to test your PQC implementation across different devices, network conditions, and real production-like workloads. It’s better to confirm zero performance trade-offs during testing than to receive negative feedback after release.

4. Systems that adopt PQC aren’t automatically crypto‑agile. Crypto agility is the ability to upgrade cryptography without rebuilding the system. To ensure your team has actually achieved it, you must check, say, that replacing RSA with Kyber won’t cause system-wide outages. Or make sure that misaligned key formats won’t silently corrupt data.

5. Rushed PQC implementation may require costly re-engineering later. Migrating to PQC is a multi‑year journey involving extra work with protocol stacks, firmware, cloud services, client applications, identity systems, and key management infrastructure. Diligent PQC testing helps you discover and fix issues before deployment.

6. PQC implementations are still maturing. Even widely used implementations may contain incomplete algorithm support or integration issues with existing protocols (TLS, SSH, VPNs). PQC tests are therefore necessary to ensure correct algorithm implementation, compatibility with existing cryptographic stacks, and safe fallback mechanisms when hybrid cryptography is used.

Watch webinar

Post-Quantum Cryptography: Practical Readiness and Secure Integration

Learn how to assess your organization’s readiness for post-quantum threats and avoid costly security gaps. Explore practical approaches to secure integration of next-generation cryptographic solutions.

Watch now

What to look for during PQC testing: key attack vectors

Before your team can meaningfully test PQC deployments, it’s crucial to clearly understand the threats your project might face.

Common PQC threats to consider when developing a testing strategy

Attack vectorWhy it’s dangerousConsequences
MITM & hybrid‑mode attacksIf hybrid negotiation is flawed, the attacker may force a fallback to a vulnerable classical path.– Silent interception
– Malicious code injection
– Traffic manipulation
Implementation weaknessesBugs in cryptographic libraries, incorrect parameter handling, or insecure randomness generation can introduce vulnerabilities.– Decryption failures
– Key leakage
– Signature forgery
Side‑channel & timing attacksNon‑constant time implementations or cache‑sensitive operations can leak key‑dependent information.– Recovery of private keys
– Forging signatures
– Decrypting protected communications
Replay & traffic‑reproduction attacksIf message freshness or session logic isn’t enforced, attackers may cause unintended state transitions.– Repeated execution of sensitive operations
– Session desynchronization
– Potential denial of service

How to test PQC systems without post-quantum computers: Welcome post‑quantum emulators

A challenge that researchers and security engineers now face is how to test cryptographic systems against quantum‑level threats when real large‑scale quantum computers don’t yet exist.

This is where post‑quantum emulators become essential: they simulate the cryptographic conditions under which classical algorithms become vulnerable and only quantum‑resistant schemes remain reliable.

A PQC emulator provides software‑based implementations of quantum‑safe mechanisms while:

  • Supporting key generation, encapsulation, decapsulation, and digital signatures
  • Using algorithms specifically designed to resist quantum attacks
  • Allowing engineers to test PQC in authentic system environments: network protocols, encrypted traffic, client–server interactions, file encryption workflows, and more
  • Enabling teams to test their systems as if the quantum era has already arrived
  • Allowing organizations to proactively strengthen their infrastructure before quantum attacks become practical

Here are the main tools and platforms for post‑quantum emulation as of today:

  1. Open Quantum Safe (OQS) is one of the leading projects in the field. Its liboqs library implements a wide range of post‑quantum algorithms including Kyber, Dilithium, and SPHINCS+. OQS is commonly used for testing key encapsulation, signatures, and full cryptographic flows within real software stacks.
  2. OQS‑OpenSSL is an extension of the classic OpenSSL library that integrates PQC algorithms. This allows practical testing of quantum‑safe TLS connections, hybrid key exchanges, and PQC‑enhanced certificates using familiar tooling.
  3. PQClean is a project offering clean, auditable reference implementations of PQC algorithms. It’s designed for correctness review, performance comparison, and reproducibility. PQClean is often used as the baseline implementation when verifying or benchmarking other libraries.
  4. Large vendors like IBM and Microsoft have begun integrating PQC into their platforms, signing mechanisms, and cloud services. IBM provides PQC‑based algorithm suites built around CRYSTALS‑Kyber and CRYSTALS‑Dilithium, while Microsoft Research contributes to PQC tooling for system‑level testing and migration planning.
  5. Virtualization and containerized environments like QEMU and Docker now allow engineers to set up isolated testing environments that simulate entire systems (clients, servers, adversarial nodes) and analyze encrypted traffic in detail.

To help you and your team better understand how this may work in practice, we have prepared several practical examples on how we test:

Or you can reach out and we’ll discuss effective ways to assess and enhance the protection of your product’s PQC layer.

Concerned about vulnerabilities in post-quantum algorithms?

Leverage Apriorit’s security testing expertise to evaluate your system against evolving threats and cybersecurity skills and advance your product’s defences.

PQC implementation testing: Apriorit’s multilevel structure

In cryptography, an implementation mistake may result in failed secure connections or hidden vulnerabilities. This is why we recommend taking a multi-level approach and starting with assessing your PQC algorithm implementation before you move to security testing.

For our example, let’s take the ML-KEM-512 algorithm. ML-KEM belongs to the class of Key Encapsulation Mechanisms (KEM). The purpose of a KEM is to allow two parties to agree on a shared secret over an open communication channel.

For a program under testing, let’s say we have a simple PQC-driven solution that runs the following steps:

  1. Key generation. The receiver generates a key pair: a public key (can be shared openly) and a private key (must remain secret).
  2. Encapsulation. Using the receiver’s public key, the sender generates a ciphertext and derives a shared secret (shared_secret_A). This step is typically executed by the sender during connection establishment.
  3. Decapsulation. The receiver uses their private key and the received ciphertext to derive the corresponding shared secret (shared_secret_B).

As this section offers a simplified, illustrative example of how to run PQC testing, we’ll only check for three metrics:

  • Correctness 一 To make sure the algorithm is implemented correctly and works as intended
  • Performance 一 To validate whether the algorithm is suitable for real-world deployments
  • Compliance 一 To check whether the algorithm is implemented according to the FIPS 203 standard

With that in mind, let’s start testing the algorithm implementation.

Verify ML-KEM-512 implementation correctness using liboqs

Our task here is to:

  • Verify the correctness of the ML-KEM-512 implementation standardized by NIST (FIPS 203) using the liboqs library
  • Confirm that encapsulation and decapsulation operations produce the same shared secret on both sides

The implementation is considered correct if the following condition holds: shared_secret_A == shared_secret_B.

1. Prepare an isolated environment using a clean Docker container:

Python
docker run -it --name pqc-lab ubuntu:22.04 bash

After execution, the new Ubuntu 22.04 environment starts up and the following message appears indicating that the session is running inside the container: root@<container_id>:/#,

2. Install dependencies. Since the container initially contains some system packages, we have to update the package list:

Python
apt update

Now, we can install the required tools:

Python
apt install -y build-essential cmake ninja-build git libssl-dev

Note: If libssl-dev is not installed, the build process will fail due to missing OpenSSL components.

3. Obtain the source code:

Python
git clone https://github.com/open-quantum-safe/liboqs.git
cd liboqs

4. Create a separate build directory:

Python
mkdir build
cd build

Now, we can configure the project:

Python
cmake -GNinja -DOQS_BUILD_ONLY_LIB=OFF ..

If the configuration is successful, the output will include:

Python
-- Configuring done
-- Generating done

Now we can compile the project: ninja

5. Run the ML-KEM-512 test:

Python
./tests/test_kem ML-KEM-512

Finally, here’s our output:

Python
Testing KEM algorithms using liboqs version 0.15.0   #Displays the library version. Configuration info
==================
Target platform:  aarch64-Linux-6.10.14-linuxkit  #Beginning of environment and build configuration details
Compiler:     	gcc (11.4.0).  #Shows the CPU architecture and operating system where the test is running
Compile options:  [-march=armv8-a+crypto;-Wa,--noexecstack;-O3;-fomit-frame-pointer;-fdata-sections;-ffunction-sections;-Wl,--gc-sections;-Wbad-function-cast]   #Indicates which compiler and version were used to build the library
OQS version:  	0.15.0 (major: 0, minor: 15, patch: 0) #Displays optimization and security-related compilation flags applied during build
Git commit:   	f1e80d17b452ec71a01b68ac7cbb52649f0b7544 #Confirms the exact version of liboqs being tested
OpenSSL enabled:  Yes (OpenSSL 3.0.2 15 Mar 2022) #Specifies the exact source code revision used, ensuring reproducibility
#Confirms that OpenSSL is integrated and shows its version
AES:          	OpenSSL
SHA-2:        	OpenSSL
SHA-3:        	C
OQS build flags:  OQS_DIST_BUILD OQS_LIBJADE_BUILD OQS_OPT_TARGET=generic CMAKE_BUILD_TYPE=Release #Indicates which backend implementation is used for cryptographic primitives
CPU exts active:  AES SHA2 SHA3 NEON #Shows compilation configuration flags for the OQS build
================================================================================
#Lists active hardware acceleration extensions available on the CPU
sample computation for KEM ML-KEM-512
Version source: FIPS203
================================================================================
#Indicates that a test computation is being performed for ML-KEM-512, following the FIPS 203 specification
shared secrets are equal
shared secrets are equal

Both lines confirm that the shared secrets computed by the sender and receiver match.

Let’s check the return code: echo $?

A return value of 0 indicates successful execution.

This verification:

  • Demonstrates that the ML-KEM-512 implementation behaves exactly as defined in the FIPS 203 specification
  • Confirms that key pair generation operates correctly, meaning that public and private keys are produced in a valid and internally consistent manner
  • Verifies that the encapsulation procedure correctly derives a ciphertext and an initial shared secret on the sender’s side
  • Confirms that the decapsulation procedure on the receiver’s side reconstructs the identical shared secret from the ciphertext using the corresponding private key

Practical significance: If this verification were to fail, it would indicate a fundamental implementation problem. In practical systems, such failure would prevent successful key agreement between communicating parties.

Any protocol relying on ML-KEM for secure session establishment — including TLS-based systems, VPN tunnels, or encrypted messaging frameworks — would either fail during handshake or produce unstable connections.

After verifying that ML-KEM-512 functions correctly and produces identical shared secrets on both sides, the next logical step is to evaluate its computational performance.

Related project

Auditing the Security of a Connected Vehicle Communication System

Discover how we identified critical vulnerabilities in a vehicle communication system and helped enhance its overall security posture through a comprehensive audit and targeted remediation.

Project details
Assessing the Security of Connected Vehicle Communication System

Measure ML-KEM-512 performance

Our objectives here are to:

  • Find out whether the algorithm is suitable for real-world deployment under load
  • Measure the execution time of key generation, encapsulation, and decapsulation
  • Assess whether ML-KEM-512 can be used in production environments such as TLS handshakes, VPN systems, and high-load servers without introducing unacceptable latency

From a performance perspective, encapsulation and decapsulation are particularly important because they occur during every secure session establishment. If these operations are slow, overall handshake latency increases accordingly. Performance benchmarking provides quantitative data about how long each operation takes and how many operations can be performed per second.

Alexander, Test Engineer at Apriorit

1. Prepare the environment. We’ll use the same Docker container as in the previous section to ensure consistency of the environment, including:

  • CPU architecture
  • Compiler version
  • Optimization flags
  • OpenSSL configuration
  • liboqs version

Now, we can:

  • Move to the build directory: cd /liboqs/build
  • Verify that benchmarking tools are available: ls tests
  • Check that output includes the binary: speed_kem

2. Launch the built-in benchmarking tool for the ML-KEM-512 algorithm:

Python
./tests/speed_kem ML-KEM-512

The output begins with configuration information describing the execution environment:

Python
Configuration info
==================
Target platform:  aarch64-Linux-6.10.14-linuxkit
Compiler:         gcc (11.4.0)
Compile options:  [-march=armv8-a+crypto;-Wa,--noexecstack;-O3;-fomit-frame-pointer;-fdata-sections;-ffunction-sections;-Wl,--gc-sections;-Wbad-function-cast]
OQS version:      0.15.0 (major: 0, minor: 15, patch: 0)
Git commit:       97f6b86b1b6d109cfd43cf276ae39c2e776aed80
OpenSSL enabled:  Yes (OpenSSL 3.0.2 15 Mar 2022)
AES:              OpenSSL
SHA-2:            OpenSSL
SHA-3:            C
OQS build flags:  BUILD_SHARED_LIBS OQS_DIST_BUILD OQS_LIBJADE_BUILD OQS_OPT_TARGET=generic CMAKE_BUILD_TYPE=Release
CPU exts active:  AES SHA2 SHA3 NEON
Speed test
==========

This section confirms:

  • ARM64 architecture (aarch64)
  • GCC compiler version
  • Aggressive optimization (-O3)
  • Hardware cryptographic acceleration (AES, SHA, NEON)

3. Interpret the speed test results:

Python
Speed test
==========
Started at 2026-04-05 18:20:24
Operation                            | Iterations | Total time (s) | Time (us): mean | pop. stdev | High-prec time (ns): mean | pop. stdev
------------------------------------ | ----------:| --------------:| ---------------:| ----------:| -------------------------:| ----------:
ML-KEM-512                           |            |                |                 |            |                           |
keygen                               |     494462 |          3.000 |           6.067 |     11.735 |                      6036 |      11732
encaps                               |     448017 |          3.000 |           6.696 |      1.550 |                      6665 |       1478
decaps                               |     400699 |          3.000 |           7.487 |     10.937 |                      7456 |      10927
  • Each operation is executed repeatedly for a fixed duration of three seconds.
  • The program measures how many iterations can be performed within that time and calculates the average execution time.
  • Key generation was performed 484,367 times in three seconds, resulting in an average time of approximately 6.2 microseconds per operation. This corresponds to roughly 160,000 key generations per second.
  • Encapsulation averaged approximately 6.8 microseconds. This operation is typically performed by the client in a TLS handshake.
  • Decapsulation averaged approximately 8.2 microseconds. It is slightly slower due to additional internal computations.

We can conclude that all operations complete within single-digit microseconds.

Practical interpretation: One millisecond equals 1,000 microseconds. Typical internet latency ranges from several milliseconds to tens of milliseconds. This means ML-KEM operations execute approximately one thousand times faster than typical network delays.

What this verification confirms:

  • ML-KEM-512 has high computational efficiency on the tested ARM64 architecture with hardware acceleration enabled.
  • Our algorithm maintains stable timing characteristics.
  • The computational cost of ML-KEM-512 doesn’t significantly affect overall connection establishment time.

These results indicate that ML-KEM-512 is suitable for deployment in real-world systems, including TLS-based secure communication and high-throughput server environments.

Read also

How to Integrate Post-Quantum Cryptography Algorithms into Your Software: A Practical Guide

Find out how to effectively integrate post-quantum cryptography into your applications and infrastructure. Discover proven approaches that help you strengthen security, reduce risks, and ensure readiness for evolving threats.

Learn more
How to integrate post-quantum cryptography

Verify ML-KEM-512 compliance using known answer tests (KAT)

Under normal operation, ML-KEM uses cryptographically secure randomness. For KAT, this randomness is replaced with a fixed seed. The algorithm receives a strictly defined input and must produce a strictly defined output.

Effectively, ML-KEM temporarily behaves as a deterministic function: seed → pk, sk, ct, ss

For this test, our goals are to:

  • Confirm that the ML-KEM-512 implementation reproduces exactly the same values defined by the FIPS 203 standard
  • Check correctness of polynomial ring arithmetic
  • Ensure proper serialization and encoding
  • Check correctness of hashing procedures

If even a single byte differs from the reference value, the implementation is considered non-compliant.

1. Prepare an environment using the same Docker container as for previous tests and taking the same steps.

2. Run KAT and analyze the output:

Python
./tests/kat_kem ML-KEM-512

The output begins as follows:

Python
count = 0
seed = 061550234D158C5EC95595FE04EF7A25767F2E24CC2BC479D09D86DC9ABCFDE7056A8C266F9EF97ED08541DBD2E1FFA1
pk = 400865ED10B619AA5811139BC086825782B2B7124F757C83AE794444BC78A47896ACF1262C81351077893BFC56F90449C2FA5F6E586DD37C0B9B581992638CB7E7BCBBB99AFE4781D80A50E69463FBD988722C3635423E27466C71DCC674527CCD728968CBCDC00C5C9035BB0AF2C9922C7881A41DD2875273925131230F6CA59E9136B39F956C93B3B2D14C641B089E07D0A840C893ECD76BBF92C805456668D07C621491C5C054991A656F511619556EB97782E27A3C785124C70B0DABA6C624D18E0F9793F96BA9E1599B17B30DCCC0B4F3766A07B23B257309CD76ABA072C2B9C9744394C6AB9CB6C54A97B5C57861A58DC0A03519832EE32A07654A070C0C8C4E8648ADDC355F274FC6B92A087B3F9751923E44274F858C49CABA72B65851B3ADC48936955097CAD9553F5A263F1844B52A020FF7CA89E881A01B95D957A3153C0A5E0A1CCD66B1821A2B8632546E24C7CBBC4CB08808CAC37F7DA6B16F8ACED052CDB2564948F1AB0F768A0D3286CCC7C3749C63C781530FA1AE670542855004A645B522881EC1412BDAE342085A9DD5F8126AF96BBDB0C1AF69A15562CB2A155A100309D1B641D08B2D4ED17BFBF0BC04265F9B10C108F850309504D772811BBA8E2BE16249AA737D879FC7FB255EE7A6A0A753BD93741C61658EC074F6E002B019345769113CC013FF7494BA8378B11A172260AAA53421BDE03A35589D57E322FEFA4100A4743926AB7D62258B87B31CCBB5E6B89CB10B271AA05D994BB5708B23AB327ECB93C0F3156869F0883DA2064F795E0E2AB7D3C64D61D2303FC3A29E1619923CA801E59FD752CA6E7649D303C9D20788E1214651B06995EB260C929A1344A849B25CA0A01F1EB52913686BBA619E23714464031A78439287FCA78F4C0476223EEA61B7F25A7CE42CCA901B2AEA129817894BA3470823854F3E5B28D86BA979E54671862D90470B1E7838972A81A48107D6AC0611406B21FBCCE1DB7702EA9DD6BA6E40527B9DC663F3C93BAD056DC28511F66C3E0B928DB8879D22C592685CC775A6CD574AC3BCE3B27591C821929076358A2200B377365F7EFB9E40C3BF0FF0432986AE4BC1A242CE9921AA9E22448819585DEA308EB039
sk = 9CDA1686A3396A7C109B415289F56A9EC44CD5B9B674C38A3BBAB30A2C90F00437A264B0BE9A1E8BA887D3C3B100898054272F941C88A1F208F1C914F964C1AAD613A6A84F88E42D3556835FB161FDC5CD15A3BC7E74B6F2612FA8271C7EA112B05C2A36CC707CE38D5D1ACC5115462A8C1AABF07276C72318337F74B5CBEFEA7A803790BC0393F3A54C724A5765A48F296B03F484376023626930222704C08FD3BC729315D1FC70EB7975A97B9DEED162F486BBC64A097111952D89B57D765E8A991A2E564206EA7BF5E4007A66358831CA0E34B2F6A84D10F79C477CB66A8A952569367388130D7B974A63AA51996C97709BB8EABC94E6A535D792D2905474952D6B8C2222B2AE56DC66FB0461192066CDDB43EC05984FB4982649771397C6A8379F3B5643069848875919E89CC439A3BE2F081490F341BD1240ADD80DDB8C9963B47A2A0992290338DA9C3B725C6DA44718C01046812562AFB084837ACB3C575E4F93936C352AC0E70AA3845EE485296E6B02DE0B47B5C4C96B0B7CF94C4ABE95486153118E43C2B9C84D9DA91C6C5ACD5A57002D058497992799E5BA1CE6C25EB29844D858BA1C37850C0C2F57C60DE37F77C082EC14494EBA288A65915116C20A325DE31AAADD680DB19C0CFCC3460F0AA01A87A6A580C6CA291FAEF0CCC49B76A8DAC4F9D41640509DBD0B4045C1530ED34755D47462700F2A8CAF9680A6D7E38A7E2A63E937650A23306D855DA2A2B7EF505CA596AB0485013EA927C7342343613643BA4007D6C874B980C79C3AA1C74F8581C34849B36EA79815FBB4CCF9610583081D7C5B4409B8D0531C04BCAF7CC751103A5FD1BA4470833E89775ADED970B5471859250FE7267105835F390030C5E7CD3F961019EAAEA23777D347BB2ADCB673C02034F394342271BCEA6414E546C3B20BD57481C7EA14C77C388CC86251C12558B100F8C5B3D03CA2C70713909659C8BA26D0D1765E0BC823D68CA5570DE600CD0941725D386E14C1012DF5951BEB8D8281A4F6815D3760B764295AD0406C2BF7928AD65032B65F14B77CCB8917C93A29D6287D8A6062399CB6400865ED10B619AA5811139BC086825782B2B7124F757C83AE794444BC78A47896ACF1262C81351077893BFC56F90449C2FA5F6E586DD37C0B9B581992638CB7E7BCBBB99AFE4781D80A50E69463FBD988722C3635423E27466C71DCC674527CCD728968CBCDC00C5C9035BB0AF2C9922C7881A41DD2875273925131230F6CA59E9136B39F956C93B3B2D14C641B089E07D0A840C893ECD76BBF92C805456668D07C621491C5C054991A656F511619556EB97782E27A3C785124C70B0DABA6C624D18E0F9793F96BA9E1599B17B30DCCC0B4F3766A07B23B257309CD76ABA072C2B9C9744394C6AB9CB6C54A97B5C57861A58DC0A03519832EE32A07654A070C0C8C4E8648ADDC355F274FC6B92A087B3F9751923E44274F858C49CABA72B65851B3ADC48936955097CAD9553F5A263F1844B52A020FF7CA89E881A01B95D957A3153C0A5E0A1CCD66B1821A2B8632546E24C7CBBC4CB08808CAC37F7DA6B16F8ACED052CDB2564948F1AB0F768A0D3286CCC7C3749C63C781530FA1AE670542855004A645B522881EC1412BDAE342085A9DD5F8126AF96BBDB0C1AF69A15562CB2A155A100309D1B641D08B2D4ED17BFBF0BC04265F9B10C108F850309504D772811BBA8E2BE16249AA737D879FC7FB255EE7A6A0A753BD93741C61658EC074F6E002B019345769113CC013FF7494BA8378B11A172260AAA53421BDE03A35589D57E322FEFA4100A4743926AB7D62258B87B31CCBB5E6B89CB10B271AA05D994BB5708B23AB327ECB93C0F3156869F0883DA2064F795E0E2AB7D3C64D61D2303FC3A29E1619923CA801E59FD752CA6E7649D303C9D20788E1214651B06995EB260C929A1344A849B25CA0A01F1EB52913686BBA619E23714464031A78439287FCA78F4C0476223EEA61B7F25A7CE42CCA901B2AEA129817894BA3470823854F3E5B28D86BA979E54671862D90470B1E7838972A81A48107D6AC0611406B21FBCCE1DB7702EA9DD6BA6E40527B9DC663F3C93BAD056DC28511F66C3E0B928DB8879D22C592685CC775A6CD574AC3BCE3B27591C821929076358A2200B377365F7EFB9E40C3BF0FF0432986AE4BC1A242CE9921AA9E22448819585DEA308EB03950C8DD152A4531AAB560D2FC7CA9A40AD8AF25AD1DD08C6D79AFE4DD4D1EEE5AB505D7CFAD1B497499323C8686325E4792F267AAFA3F87CA60D01CB54F29202A
ct = 521C88486C35F6C245839212AB0E23660CD5B68FCCD5A7B41EB5A3CE8844A31088C878EEFEB44739CF9130013A83FAAA78037443E5D749BA4D6F156934CC89C2D9ABC76CB7FF050B4EEEB4A58611BE330B3FDEE875C1F366216AD659FABBEBCE37114E795C65F1EECA93181343005410FEBAE042DFAEEAD873CF1C575D38CE26EC5C02940C0224E983881C2A1A4771BA316628A0F425EF54E984FE70E3866C79780B7572462CE5A9E116B55439AE921FF8B0D89D8616D405135DFAB8F14D7DA03F752517DA847458AB83646CE5B4073788C66A6B60FAF64B8FED507EE2A7D931F746B9F2595769721A59D93E4852AAF8185114F4A04F0F6F3CA144BA8EE1BA52DB4AA7DC274156862812DC36E06997942BAB02822BFC5FDFCDACEA869C1A7672A4C794C9C09CC8A76DF894324C14A53E9961CF40F0E70DC18583AA5E3D025A5B8D9CEDA71D7902EBC5D499F059386B9910C75BA834B9D0C70AD9B9EA683AA699865F9CA7F3F30D20B78FF99850216A62F919A9D9ECA482A52EAA2500FE5B80853CBB88E17CE593EB23709BAC01FDFC941B527F5180E0DECC3785F04D9120098F14C07F9244B441F2897F243C846A1D093D6A9C0B40E842A6D12E1D2E01BB44693D61C875EF007673787AAF167C1EC2B2F61AB8B504032A14490C109A0C2AEE872FCD629594992EBD6DCDE42FF6A602A5C7E15F50B799A7780829DB1CB2E70E89944CF543224D4339CCF317A0BA195A07DF0F43D7EEE2400080DA25A40F320061B15AE23EA0DEE42474B2274D92C72C7E82F938BF826934CA2AAACA49CD73EB36D182591B8145D89AC8D6CEB7BE8A1D7960D04171D7D03D84580BCA9B5976AD1ED6CC8B021BEECDBCC8B51A9B091C6625861097A32FB5A41E15B856CDA135C3CA29C8656603CE3EB78071494197F0906D8B2A2CB208076EC89CE5760B199E937E13FEBC7893665AB6B2D5C85DC9A5D873CBF55B4A69343D768FBEEF4B5EB88D0C31FFD366C66E13866E3F33EECBF2C3329C111C0CDE2B9560892CE1A2686A2A1C18B7A7261A55BDA57ADE241544F3561390BDC69514429C8D5FBEA9188BAF2892
ss = B4C8E3C4115F9511F2FDDB288C4B78C5CD7C89D2D4D321F46B4EDC54DDF0EB36

Let’s break down what the received output means:

  • line count = 0 indicates the test vector number.
  • seed is the fixed deterministic input used for generation.
  • pk is the public key derived strictly from the provided seed.
  • sk is the corresponding private key.
  • ct is the encapsulation result.
  • ss is the shared secret computed during the test.

Each of these values matches the official reference vectors defined by the standard.

What this verification confirms:

  • ML-KEM-512 implementation behaves deterministically when supplied with a fixed seed.
  • Every value produced during the test — public key, private key, ciphertext, and derived shared secret — is fully determined by the initial seed value.
  • Our algorithm is implemented precisely according to the FIPS 203 specification, as every byte of every output matches the expected reference output.

With correctness confirmed, performance measured, and deterministic conformance validated, the ML-KEM-512 implementation has passed the foundational layers of cryptographic testing. These stages collectively establish confidence in both the functional and structural integrity of the algorithm before it’s integrated into higher-level protocols such as TLS or hybrid cryptographic deployments.

Read also

Preparing Your Software for Post-Quantum Cryptography: A Practical Guide to Crypto-Agility

Learn how to build crypto agility into your systems and adapt quickly to emerging security standards. Strengthen your approach to post-quantum readiness with practical implementation insights.

Learn more
Preparing your software for postquantum security through crypto-agility

PQC security testing using Wireshark

Let’s shift from checking algorithm correctness to testing security.

First, we need to generate encryption/decryption code as our base for testing and prepare an environment for PQC testing. Then, to test post-quantum cryptography algorithms, we’ll run two scenarios, showing you how PQC testing looks in practice.

Generating code for encryption/decryption

Using AI, we created the encryption and decryption code in Python.

Encryption code:

Python
import oqs
import os
 
def encrypt_file(input_file, public_key_file, encrypted_file, ciphertext_file):
    kem = oqs.KeyEncapsulation("Kyber512")
     
    with open(public_key_file, "rb") as f:
        public_key = f.read()
         
    with open(input_file, "rb") as f:
        plaintext = f.read()
         
    ciphertext, shared_secret = kem.encap_secret(public_key)
 
    # Extend shared_secret to cover the entire plaintext
    extended_secret = (shared_secret * (len(plaintext) // len(shared_secret) + 1))[:len(plaintext)]
     
    # Encrypt the entire file
    encrypted_data = bytes(a ^ b for a, b in zip(plaintext, extended_secret))
     
    with open(encrypted_file, "wb") as f:
        f.write(encrypted_data)
         
    with open(ciphertext_file, "wb") as f:
        f.write(ciphertext)
         
    print(f"File encrypted successfully! Encrypted file: {encrypted_file}, Ciphertext: {ciphertext_file}")
 
 
def generate_keys(public_key_file, private_key_file):
    kem = oqs.KeyEncapsulation("Kyber512")
     
    public_key = kem.generate_keypair()
    private_key = kem.export_secret_key()
     
    with open(public_key_file, "wb") as f:
        f.write(public_key)
         
    with open(private_key_file, "wb") as f:
        f.write(private_key)
         
    print(f"Keys generated successfully! Public key: {public_key_file}, Private key: {private_key_file}")
 
 
if __name__ == "__main__":
    input_file = "pqc.txt"
    public_key_file = "public_key.bin"
    private_key_file = "private_key.bin"
    encrypted_file = "pqc_encrypted.bin"
    ciphertext_file = "ct.bin"
 
    generate_keys(public_key_file, private_key_file)
    encrypt_file(input_file, public_key_file, encrypted_file, ciphertext_file)
     
    print("Send the files pqc_encrypted.bin and ct.bin to your friend.")

This is how it works:

  1. We run the following code: python3 encrypt_pqc.py.
  2. Our program creates a pair of keys (public and private) using Kyber512: public_key.bin and private_key.bin.
  3. The program takes public_key.bin and pqc.txt as inputs.
  4. The program creates a shared secret and a ciphertext: ct.bin.
  5. The program encrypts the content of pqc.txt with the secret key (here we used simple XOR for illustrative purposes; in real-life solutions, it should be AES).
  6. The result is saved as pqc_encrypted.bin (the encrypted file) and ct.bin (the ciphertext).

If we open the pqc_encrypted.bin file, we’ll see the following:

Python
×?/»±†ï?Llè¥4·_ë-îñö ÒÆG>

After executing the program, the following output is produced:

Python
python3 encrypt_pqc.py
The keys are created! Public: public_key.bin, Private: private_key.bin
The file is encrypted! The encrypted file: pqc_encrypted.bin, the ciphertext: ct.bin
Send files to a friend: pqc_encrypted.bin and ct.bin

Now, let’s look at the decryption code:

Python
import oqs
import os
 
 
def decrypt_file(encrypted_file, ciphertext_file, private_key_file, output_file):
    kem = oqs.KeyEncapsulation("Kyber512")
 
    with open(private_key_file, "rb") as f:
        private_key = f.read()
 
    with open(ciphertext_file, "rb") as f:
        ciphertext = f.read()
 
    kem = oqs.KeyEncapsulation("Kyber512", private_key)
    shared_secret = kem.decap_secret(ciphertext)
 
    with open(encrypted_file, "rb") as f:
        encrypted_data = f.read()
 
    # Extend shared_secret to cover the entire encrypted data
    extended_secret = (shared_secret * (len(encrypted_data) // len(shared_secret) + 1))[:len(encrypted_data)]
 
    # Decrypt all data
    decrypted_data = bytes(a ^ b for a, b in zip(encrypted_data, extended_secret))
 
    with open(output_file, "wb") as f:
        f.write(decrypted_data)
 
    print(f"File decrypted successfully! Output: {output_file}")
 
 
if __name__ == "__main__":
    encrypted_file = "pqc_encrypted.bin"
    ciphertext_file = "ct.bin"
    private_key_file = "private_key.bin"
    output_file = "pqc_decrypted.txt"
 
    for file in [encrypted_file, ciphertext_file, private_key_file]:
        if not os.path.exists(file):
            print(f"Error: file {file} was not found!")
            exit()
 
    decrypt_file(encrypted_file, ciphertext_file, private_key_file, output_file)
 
    with open(output_file, "r", encoding="utf-8") as f:
        print("Decrypted file contents:", f.read())

Let’s run python3 decrypt_pqc.py. This code:

  • Checks whether a folder contains pqc_encrypted.bin, ct.bin and private_key.bin
  • Takes the key and ciphertext and extracts the secret code
  • Decrypts and saves the secret code in pqc_decrypted.txt

And here’s the outcome:

Python
python3 decrypt_pqc.py
File decrypted successfully! Output: pqc_decrypted.txt
Decrypted file contents: Hello, this is a secret!

Preparing the environment for PQC testing

To practically evaluate the security of data transmission, we’ll use a local Docker-based environment. This approach makes it possible to reproduce a realistic network model with multiple nodes without relying on physical machines or virtual servers.

Note: We’re running this experiment on macOS, but the architecture itself is platform-independent.

1. Prepare the working directory for Docker on the host system, and mount this directory into the Docker containers:

Python
mkdir -p ~/pqc_lab

Now, we copy required files into this directory:

Python
cp /Users/user/PCQ/* ~/pqc_lab/

And run verification:

Python
ls -lh ~/pqc_lab

Expected output:

Python
-rw-r--r--@  1 user  staff   768 Feb  6 11:08 ct.bin
-rw-r--r--@  1 user  staff	22 Feb  6 11:08 pqc_encrypted.bin
-rw-r--r--@  1 user  staff	22 Feb  6 11:08 pqc.txt
-rw-r--r--@  1 user  staff  1632 Feb  6 11:08 private_key.bin
-rw-r--r--@  1 user  staff   800 Feb  6 11:08 public_key.bin

2. Create a Docker network:

Python
docker network create pqcnet

The pqcnet network acts as a private LAN inside Docker, as each container receives a private IP address, containers can communicate directly over TCP/IP, and traffic remains inside a controlled subnet.

The main reason for this setup is experimental control: we intentionally create a small internal network where traffic can be intercepted and analyzed under a passive attacker model.

3. Launch machines. Machine A (Sender) represents the sending endpoint:

Python
docker run -d --name machine-a \
  --network pqcnet \
  -v ~/pqc_lab:/lab \
  ubuntu:22.04 sleep infinity

Machine B (Receiver) represents the receiving endpoint:

Python
docker run -d --name machine-b \
  --network pqcnet \
  -v ~/pqc_lab:/lab \
  ubuntu:22.04 sleep infinity

4. Launch an Observer (passive sniffer) that represents a passive monitoring attacker:

Python
docker run -d --name observer \
  --network container:machine-b \
  -v ~/pqc_lab:/lab \
  ubuntu:22.04 sleep infinity

5. Install network tools. To keep the setup simple, we can only install two tools:

  • netcat (nc) on Machine A and Machine B to transmit raw TCP byte streams without encryption or application-level protocol overhead
  • tcpdump on Observer to capture packets in PCAP format for later offline analysis in Wireshark
Python
docker exec -it machine-a bash -lc "apt update && apt install -y netcat-openbsd"
docker exec -it machine-b bash -lc "apt update && apt install -y netcat-openbsd"
docker exec -it observer  bash -lc "apt update && apt install -y tcpdump iproute2"

Let’s run verification:

Python
docker exec -it machine-a bash -lc "which nc"
docker exec -it machine-b bash -lc "which nc"
docker exec -it observer  bash -lc "which tcpdump"

Expected output:

Python
/usr/bin/nc
/usr/bin/nc
/usr/bin/tcpdump

6. Verify test file availability. Before running the network experiment, we need to validate the plaintext input inside the containers. This way, we’ll ensure that the mounted dataset is accessible and consistent.

Python
docker exec -it machine-a bash -lc "cat /lab/pqc.txt"

Expected output:

Python
Hello, it's a secret!

At this point, preparations are finally done, and we can start PQC security testing.

Read also

Shifting to Post-Quantum Cryptography in Automotive Projects: Reasons, Challenges, Considerations

Gain insights into applying quantum-resistant encryption to automotive systems and ensuring compliance with evolving security expectations. Learn how to enhance protection across connected and autonomous vehicle components.

Learn more
Post-Quantum Cryptography in automotive

Note: We usually start by establishing a baseline: testing plaintext transmission with passive traffic interception. Such a test demonstrates how easily data confidentiality fails when plaintext is transmitted over a network. To spare you the details, let’s just show you the results (Screenshot 1) and move to more interesting tests.

Wireshark analysis results (plaintext transmission)
Screenshot 1. Wireshark analysis results (plaintext transmission)

Testing scenario 1: Post-quantum encrypted transmission with passive traffic interception

Let’s evaluate whether a passive observer — capable of capturing full packet payloads — can reconstruct the original message when transmitted data is encrypted using a post-quantum scheme (Kyber512 + symmetric masking).

Note: In these tests, we continue working with ML-KEM-512. Kyber was the name used during the NIST PQC competition (specifically, CRYSTALS-Kyber). When standardized, NIST renamed it to ML-KEM (Module-Lattice KEM). In simple terms: Kyber512 = ML‑KEM‑512 under the FIPS 203 standard.

1. Prepare packet capture on Observer (port 9999):

Python
docker exec -d observer bash -lc \
"tcpdump -i eth0 -s 0 -nn -U -c 50 \
-w /lab/s2_pqc_encrypted_observer.pcap 'tcp port 9999'"

Why these parameters matter:

  • -i eth0 → capture on receiver interface
  • -s 0 → capture full payload (not truncated)
  • -nn → disable name resolution (raw IP/port)
  • -U → write packets immediately (prevents corrupted files)
  • -c 50 → stop automatically after capture completes

This ensures a clean, finalized PCAP file suitable for forensic analysis.

2. Start the encrypted Receiver listener (Machine B):

Python
docker exec -d machine-b bash -lc \
"cd /lab; rm -f recv_pqc_encrypted.bin; nc -l -p 9999 > recv_pqc_encrypted.bin"

At this stage:

  • The receiver is waiting
  • Observer is capturing
  • No data has yet been transmitted

3. Send the encrypted file from Machine A:

Python
docker exec -it machine-a bash -lc \
"cd /lab; nc -q 1 172.18.0.2 9999 < pqc_encrypted.bin"

Let’s break down the code:

  • 172.18.0.2 is a private IP address of Machine B
  • 9999 is a dedicated port for encrypted transmission
  • -q 1 ensures clean connection termination
  • < pqc_encrypted.bin sends raw binary payload

No TLS or transport-layer encryption is used. The only protection applied is at the payload level.

4. Verify correct reception on Machine B:

Python
docker exec -it machine-b bash -lc \
"ls -lh /lab/recv_pqc_encrypted.bin; \
wc -c /lab/recv_pqc_encrypted.bin /lab/pqc_encrypted.bin"

Expected outcome:

  • File sizes match exactly
  • No truncation
  • Transmission integrity confirmed

This proves that the encrypted payload was delivered correctly end to end.

5. Confirm that Observer recorded the traffic:

Python
docker exec -it observer bash -lc \
"ls -lh /lab/s2_pqc_encrypted_observer.pcap"

If file size > 0, capture succeeded.

6. Export PCAP to macOS:

Python
docker cp observer:/lab/s2_pqc_encrypted_observer.pcap ~/pqc_lab/

7. Run Wireshark analysis (offline):

Python
pen ~/pqc_lab/s1_plain_observer.pcap

The PCAP file is opened in Wireshark on macOS. Steps in Wireshark:

  • Right-click on any packet → Follow → TCP Stream
  • Select ASCII mode
Wireshark analysis results (encrypted transmission)
Screenshot 2. Wireshark analysis results (encrypted transmission)

This time, we see:

  • No readable message appears
  • Payload appears as high-entropy binary data
  • No recognizable ASCII fragments
  • No semantic content is recoverable

Read also

Future-proof Your FinTech Business with Post-Quantum Cryptography

Learn how to prepare your financial and banking solutions for post-quantum challenges and reduce exposure to cryptographic risks. Get actionable guidance for building resilient and secure systems.

Learn more
v3-1 -Marketing article-Quantum-resistant-cryptography-in-Fintech-cover

Testing scenario 2: Interception of pqc_encrypted.bin and ct.bin without the private key

The goal of Scenario 2 is to model a realistic passive attacker who intercepts a feasible set of artifacts transmitted over the network, including:

  • pqc_encrypted.bin (encrypted payload)
  • ct.bin (KEM ciphertext)

However, an attacker doesn’t have private_key.bin. This scenario demonstrates that interception doesn’t equal decryption. Even with both intercepted files, an attacker can’t recover the shared secret (and therefore can’t reconstruct plaintext) because decapsulation requires the private key.

Here’s data we’ll use for this testing scenario:

  • pqc_encrypted.bin is encrypted payload (masked using the derived shared secret)
  • ct.bin is Kyber512 ciphertext (KEM output)
  • private_key.bin exists only on the Receiver side (Machine B) and is not available to the attacker

1. Prepare packet capture on Observer (port 7777):

Python
docker exec -d observer bash -lc \
"tcpdump -i eth0 -s 0 -nn -U -c 50 \
-w /lab/s3_ct_observer.pcap 'tcp port 7777'"

This produces a stable PCAP artifact for later analysis in Wireshark. Using -U + -c 50 prevents truncated/empty captures.

2. Start Receiver listener on Machine B (for ct.bin):

Python
docker exec -d machine-b bash -lc \
"cd /lab; rm -f recv_ct.bin; nc -l -p 7777 > recv_ct.bin"

At this moment:

  • Receiver is waiting on port 7777
  • Observer is sniffing
  • No data has been transmitted yet

3. To send ct.bin from Machine A to Machine B, first get the IP:

Python
docker inspect -f '{{range.NetworkSettings.Networks}}{{.IPAddress}}{{end}}' machine-b

Send ct.bin:

Python
docker exec -it machine-a bash -lc \
"cd /lab; nc -q 1 172.18.0.2 7777 < ct.bin"

4. Verify successful reception of ct.bin on Machine B:

Python
docker exec -it machine-a bash -lc \
"cd /lab; nc -q 1 172.18.0.2 7777 < ct.bin"

Here, we expect file sizes to be equal and transmission integrity to be confirmed.

5. Ensure that Observer captured traffic:

Python
docker exec -it observer bash -lc \
"ls -lh /lab/s3_ct_observer.pcap"

6. Export PCAP to the host and analyze it using Wireshark:

Python
docker cp observer:/lab/s3_ct_observer.pcap ~/pqc_lab/

Screenshot 3 shows the results:

Wireshark analysis results
Screenshot 3. Wireshark analysis results (intercepting pqc_encrypted.bin and ct.bin without the private key)

What an attacker observes:

In TCP Stream, the attacker sees a sequence of bytes with no readable structure. This is expected because ct.bin is not plaintext and the Kyber output is KEM ciphertext (cryptographic binary material).

Scenario 2 demonstrates that:

  • A passive MITM attack can intercept both the encrypted payload and Kyber ciphertext.
  • Captured data is insufficient to recover the shared secret.
  • Decryption is only feasible for the legitimate receiver holding the private key.

Evaluating test results

The key result demonstrated by our experiments is that even with full MITM visibility, attackers can’t reconstruct the plaintext or derive the symmetric secret.

Since encryption takes place on the sender’s side before data enters the network, attackers only see the results of cryptographic transformations.

The private_key.bin is never transmitted, making decapsulation impossible. Thus, MITM attacks threaten communication availability but don’t compromise confidentiality in this PQC architecture.

Related project

Developing a Custom Secrets Management Desktop Application for Secure Password Sharing and Storage

Find out how we created a tailored secrets management application that enhanced data security, simplified credential handling, and helped the client reduce risks associated with sensitive information exposure.

Project details
Developing a Custom Secrets Management Desktop Application for Secure Password Sharing and Storage

Ensure secure and efficient PQC adoption with Apriorit

With 20+ years of experience in cybersecurity and software development, we are continuously expanding our expertise. Apriorit experts have been researching and working with PQC algorithms for several years now and keep going.

Apriorit teams know what PQC algorithms to use for different projects, how to implement them successfully, and — most importantly 一 how to test algorithm correctness, security, and performance. Delegate PQC testing to our specialists to make sure your strategic security investments truly work for you.

Choose Apriorit for:

  • Hands-on experience implementing post-quantum cryptography in software projects, as we help clients leverage new technologies to meet business and security goals
  • Expertise in testing PQC implementations with a focus on checking algorithms’ implementation, performance, security, and impact on the user experience
  • Strong cybersecurity engineering skills to help you assess your product protection and suggest meaningful and relevant enhancements
  • Cross-industry experience, assisting clients in automotive, FinTech, IoT, and other spheres with advanced encryption and protection measures

Post-quantum cryptography promises protection against future quantum-enabled attacks, but deploying it safely is far from trivial. For cybersecurity vendors and enterprises building long-lived digital systems, adopting PQC without rigorous testing introduces significant operational and security risks.

At Apriorit, we’re ready to help your team and product embrace new technologies with caution, accurate testing, and actual results.

Planning for secure systems in the quantum era?

Work with our team to uncover hidden vulnerabilities, validate PQC implementations, and align your product with modern security standards.

FAQ

Why isn’t traditional cryptographic testing enough for post‑quantum systems?

<p>Traditional tests will miss vulnerabilities specific to PQC implementations because:</p>
<ul class=apriorit-list-markers-green>
<li>Traditional testing focuses on RSA/ECC behaviors, key sizes, timing, and compatibility that no longer apply in the same way to complex PQC algorithms.</li>
<li>PQC introduces larger key and ciphertext sizes, different memory patterns, new failure modes, hybrid negotiation complexities, and different side‑channel risks. All of these require testing post-quantum cryptography implementations in a new way.</li>
</ul>

What are the main types of PQC testing?

<p>The PQC testing workflow can vary for different projects, but most commonly it includes the following tests:</p>
<ul class=apriorit-list-markers-green>
<li>Cryptographic correctness testing: verifying that key generation, encapsulation/decapsulation, and signature verification work as intended</li>
<li>Interoperability testing: ensuring PQC works across devices, protocols, and hybrid classical + PQC configurations</li>
<li>Performance and resource benchmarking: measuring handshake latency, CPU use, memory footprint, and packet sizes</li>
<li>Security testing under active attacks: MITM, downgrade attempts, replay attacks, malformed ciphertext injection, etc.</li>
<li>Resilience testing: verifying behavior under packet loss, buffer pressure, network fragmentation, and error edges</li>
</ul>

How do post‑quantum emulators support testing and migration planning?

<p>Post‑quantum emulators like liboqs and OQS‑OpenSSL let teams test PQC algorithms as if quantum‑capable adversaries already existed (being sort of a quantum computing simulator), providing:</p>
<ul class=apriorit-list-markers-green>
<li>Stable implementations of Kyber, Dilithium, SPHINCS+, and other algorithms</li>
<li>Ability to run real-world experiments such as traffic interception, failure injection, hybrid handshake analysis, and performance benchmarking</li>
<li>Ability to run tests without requiring physical quantum hardware</li>
</ul>

Can attackers still perform meaningful attacks on PQC‑encrypted systems today?

<p>Yes, attackers may target the implementation around PQC, aiming to bypass or misuse the system rather than decrypt the data. For example:</p>
<ul class=apriorit-list-markers-green>
<li>A poorly implemented hybrid mode may allow a downgrade to classical crypto.</li>
<li>Malformed ciphertext handling may cause information leaks or crashes.</li>
<li>Replay or MITM attempts can manipulate system behavior even if the attacker can’t read the encrypted content.</li>
</ul>
<p>In all these cases, the goal is to exploit weaknesses in how PQC is integrated, validated, or used within your application.</p>

Have a question?

Ask our expert!

Maryna-Prudka
Maryna Prudka

VP of Engineering

Tell us about
your project

...And our team will:

  • Process your request within 1-2 business days.
  • Get back to you with an offer based on your project's scope and requirements.
  • Set a call to discuss your future project in detail and finalize the offer.
  • Sign a contract with you to start working on your project.

Do not have any specific task for us in mind but our skills seem interesting? Get a quick Apriorit intro to better understand our team capabilities.

* By sending us your request you confirm that you read and accepted our Terms & Conditions and Privacy Policy.