# Contractless PHP Crypto Modules These native PHP modules provide the cryptography required by `php-contractless-rpc`: - Skein-256 hashing through PHP-Skein-Hash - Contractless-compatible Falcon-512 signing and verification through liboqs Contractless uses fixed 666-byte Falcon signatures and a specific FN-DSA raw message format. The included liboqs-php patch adds the SHAKE256 operation needed to reproduce that format exactly. ## Supported Environment The automated installer currently supports 64-bit Debian and Ubuntu systems. This includes Ubuntu running through WSL. The modules can also be compiled manually on other Linux distributions. Native modules are tied to the operating system, CPU architecture, and PHP extension API. They should normally be compiled on the machine where they will run. ## Debian And Ubuntu Requirements ```bash sudo apt update sudo apt install -y \ php-cli php-dev \ swig cmake ninja-build \ build-essential git pkg-config libssl-dev ``` ## Automated Debian And Ubuntu Build ```bash chmod +x build-linux.sh install-linux.sh ./build-linux.sh ``` This downloads and compiles: - A minimal liboqs build containing `Falcon-padded-512` - The patched liboqs-php extension - The PHP-Skein-Hash extension Building does not install or enable the modules. ## Automated Debian And Ubuntu Installation After a successful build: ```bash sudo ./install-linux.sh ``` The installer copies both modules into the active PHP extension directory, creates `contractless-crypto.ini`, enables it through `phpenmod`, and verifies that PHP can see both modules. Do not add either module directly to `php.ini`. The installer manages both module declarations through `contractless-crypto.ini`. Loading them through both locations causes duplicate-module warnings. Confirm the installation manually: ```bash php -m | grep -E '^(skein|oqsphp)$' ``` Expected output: ```text oqsphp skein ``` Apache or PHP-FPM may need to be restarted: ```bash sudo systemctl restart apache2 ``` or: ```bash sudo systemctl restart php8.3-fpm ``` Use the PHP version installed on the server in the service name. ## Manual Build On Other Linux Distributions Other distributions can use the same modules but may use different package names and PHP configuration locations. The following tools are required: - PHP CLI and the matching PHP development package - `phpize` and `php-config` - SWIG - CMake - Ninja - Git - A C and C++ compiler - Make - OpenSSL development headers - `pkg-config` The PHP development package must match the PHP installation that will load the modules. For example, an extension built for PHP 8.3 should not be loaded into PHP 8.4. ### Fedora, RHEL, Rocky Linux, And AlmaLinux Package names vary between system repositories and third-party PHP repositories, but a typical installation is: ```bash sudo dnf install \ php-cli php-devel \ swig cmake ninja-build \ gcc gcc-c++ make git pkgconf-pkg-config openssl-devel ``` ### Arch Linux ```bash sudo pacman -S --needed \ php swig cmake ninja \ base-devel git pkgconf openssl ``` ### Alpine Linux The exact PHP development package includes the installed PHP version on some Alpine releases: ```bash sudo apk add \ php php-dev \ swig cmake ninja \ build-base git pkgconf openssl-dev ``` Confirm the required PHP build commands exist: ```bash php --version phpize --version php-config --version swig -version ``` Confirm that the runtime and development tools use the same PHP module API: ```bash php -i | grep '^PHP API' php-config --phpapi phpize --version ``` The API numbers reported by all three commands must match. A module compiled with PHP 8.4 development tools cannot be loaded by PHP 8.3, and the reverse is also true. `build-linux.sh` stops with an error when it detects this mismatch. ### Build liboqs Choose a working directory: ```bash mkdir -p contractless-php-build cd contractless-php-build ``` Download and compile a minimal liboqs containing the fixed-size Falcon algorithm used by Contractless: ```bash git clone --depth 1 https://github.com/open-quantum-safe/liboqs.git cmake -S liboqs -B liboqs/build -GNinja \ -DBUILD_SHARED_LIBS=OFF \ -DOQS_BUILD_ONLY_LIB=ON \ -DOQS_MINIMAL_BUILD="SIG_falcon_padded_512" ninja -C liboqs/build ``` Do not substitute `Falcon-512`. Contractless requires `Falcon-padded-512`, which produces fixed 666-byte signatures. ### Build The Contractless liboqs-php Module Clone the PHP wrapper: ```bash git clone --depth 1 https://github.com/Muzosh/liboqs-php.git ``` Apply `oqsphp-contractless.patch` from this repository: ```bash cd liboqs-php git apply /full/path/to/Contractless-PHP-Modules/oqsphp-contractless.patch ``` Build the PHP extension against the liboqs copy compiled above: ```bash LIBOQS_ROOT="$(cd ../liboqs && pwd)" bash build.sh cd .. ``` The resulting module is: ```text liboqs-php/build/oqsphp.so ``` ### Build The Skein Module ```bash git clone --depth 1 https://github.com/jedisct1/PHP-Skein-Hash.git php-skein cd php-skein phpize ./configure make cd .. ``` The resulting module is: ```text php-skein/modules/skein.so ``` ### Install The Modules Manually Find the extension directory used by the active PHP installation: ```bash php-config --extension-dir ``` Copy both modules into that directory: ```bash sudo install -m 0755 \ liboqs-php/build/oqsphp.so \ "$(php-config --extension-dir)/oqsphp.so" sudo install -m 0755 \ php-skein/modules/skein.so \ "$(php-config --extension-dir)/skein.so" ``` Find the PHP configuration directories: ```bash php --ini ``` Create one dedicated extension configuration file containing: ```ini extension=skein.so extension=oqsphp.so ``` CLI PHP, Apache, and PHP-FPM can use different configuration directories. The modules must be enabled for every PHP runtime that uses `php-contractless-rpc`. Enable or link this dedicated file in each required runtime configuration directory. Do not also add these declarations directly to `php.ini`. Restart Apache or PHP-FPM after changing its configuration. Service names vary by distribution and installed PHP version. Verify the manual installation: ```bash php -m | grep -E '^(skein|oqsphp)$' ``` ## Compatibility Test The compatibility test proves that PHP and Contractless Rust produce matching Skein hashes and mutually valid Falcon signatures: ```bash cd interop cargo run --release cd .. php tests/native.php ``` The generated private key is a disposable test fixture. Never use it as an application wallet. ## Using The Modules Applications normally use these modules through `php-contractless-rpc` rather than calling them directly. Direct Skein hashing: ```php $digest = skein_hash($data, 256); ``` ## Direct Falcon Signing And Verification Contractless uses `Falcon-padded-512`. Do not substitute the variable-length `Falcon-512` algorithm. Falcon keys and signatures are binary data. Load and store them without text, hexadecimal, Base64, or character-encoding conversions unless the application explicitly performs and reverses that conversion. Contractless Falcon signatures use a SHAKE256 prefix derived from the public key, followed by the raw-message marker and the original message: ```text SHAKE256(public_key, 64 bytes) || 0x00 || 0x00 || original_message ``` ### Sign A Message ```php sign($signature, $adaptedMessage, $privateKey) !== 0) { throw new RuntimeException('Falcon signing failed.'); } if (strlen($signature) !== 666) { throw new RuntimeException('Invalid Contractless signature length.'); } file_put_contents('signature.bin', $signature); ``` ### Verify A Signature ```php verify($adaptedMessage, $signature, $publicKey) !== 0) { throw new RuntimeException('Falcon signature verification failed.'); } echo "Signature verified.\n"; ``` These examples expose the low-level module behavior for testing and debugging. Applications should normally use the `NativeCrypto` class provided by `php-contractless-rpc`, which applies the Contractless message framing automatically.