paragonie / pqcrypto_compat
Pure PHP implementation of pqcrypto; uses the PHP extension if it exists
Requires
- php: ^8.1
- php-64bit: *
- paragonie/sodium_compat: ^2
Requires (Dev)
- c2sp/wycheproof: dev-main
- giorgiosironi/eris: ^1
- phpunit/phpunit: ^10|^11|^12|^13
- trailofbits/wycheproof: ^0|^1
Suggests
- ext-pqcrypto: Better performance, higher assurance
- ext-sodium: Faster X-Wing KEM (only if ext-pqcrypto is not installed)
README
pqcrypto_compat defers to the pqcrypto extension if it's available, and provides a polyfill for environments where it is not available, ensuring the PHP ecosystem can effectively migrate to use post-quantum secure cryptographic algorithms.
Warning
This code has never been independently audited. Use at your own risk.
Installing
composer require paragonie/pqcrypto_compat
Optional, but recommended: Install the pqcrypto extension.
Usage
The recommended way to use this polyfill library is the Compat class.
Tip
If you aren't already using opcache and JIT, we highly recommend enabling those PHP features when using pqcrypto_compat without ext-pqcrypto. It makes a huge difference.
X-Wing Example
X-Wing is a hybrid KEM combining X25519 and ML-KEM-768. The X25519 implementation is provided by sodium_compat.
<?php declare(strict_types=1); use ParagonIE\PQCrypto\Compat; // Key generation [$decapsKey, $encapsKey] = Compat::xwing_keygen(); // Encapsulation ['sharedKey' => $ss, 'ciphertext' => $ct] = Compat::xwing_encaps($encapsKey); // Decapsulation $sharedKey = Compat::xwing_decaps($decapsKey, $ct); var_dump(hash_equals($ss, $sharedKey)); // bool(true)
ML-KEM-768 Example
<?php declare(strict_types=1); use ParagonIE\PQCrypto\Compat; // Key generation [$decapsKey, $encapsKey] = Compat::mlkem768_keygen(); $decapsKeyBytes = $decapsKey->bytes(); $encapsKeyBytes = $encapsKey->bytes(); // Encapsulation ['sharedKey' => $ss, 'ciphertext' => $ct] = Compat::mlkem768_encaps($encapsKey); // Send $ct to recipient that possesses $decapsKey $sharedKey = Compat::mlkem768_decaps($decapsKey, $ct); var_dump(hash_equals($ss, $sharedKey)); // bool(true)
ML-KEM-1024 Example
<?php declare(strict_types=1); use ParagonIE\PQCrypto\Compat; // Key generation [$decapsKey, $encapsKey] = Compat::mlkem1024_keygen(); $decapsKeyBytes = $decapsKey->bytes(); $encapsKeyBytes = $encapsKey->bytes(); // Encapsulation ['sharedKey' => $ss, 'ciphertext' => $ct] = Compat::mlkem1024_encaps($encapsKey); // Send $ct to recipient that possesses $decapsKey $sharedKey = Compat::mlkem768_decaps($decapsKey, $ct); var_dump(hash_equals($ss, $sharedKey)); // bool(true)
ML-DSA-44 Example
<?php declare(strict_types=1); use ParagonIE\PQCrypto\Compat; // Key generation ['signingKey' => $sk, 'verificationKey' => $vk] = Compat::mldsa44_keygen(); // Signing $message = 'message'; $signature = Compat::mldsa44_sign($sk, $message); $valid = Compat::mldsa44_verify($vk, $signature, $message); var_dump($valid); // bool(true)
ML-DSA-65 Example
<?php declare(strict_types=1); use ParagonIE\PQCrypto\Compat; // Key generation ['signingKey' => $sk, 'verificationKey' => $vk] = Compat::mldsa65_keygen(); // Signing $message = 'message'; $signature = Compat::mldsa65_sign($sk, $message); $valid = Compat::mldsa65_verify($vk, $signature, $message); var_dump($valid); // bool(true)
ML-DSA-87 Example
<?php declare(strict_types=1); use ParagonIE\PQCrypto\Compat; // Key generation ['signingKey' => $sk, 'verificationKey' => $vk] = Compat::mldsa87_keygen(); // Signing $message = 'message'; $signature = Compat::mldsa87_sign($sk, $message); $valid = Compat::mldsa87_verify($vk, $signature, $message); var_dump($valid); // bool(true)
Other Algorithms
We also include ML-KEM-512 for completeness, but do not recommend its usage.