Contractless-PHP-Modules/tests/native.php

55 lines
1.8 KiB
PHP
Raw Permalink Normal View History

<?php
declare(strict_types=1);
$fixtures = dirname(__DIR__) . '/interop/fixtures';
2026-07-25 19:53:41 +00:00
$fixtureFiles = [
'message.bin',
'public-key.bin',
'private-key.bin',
'rust-signature.bin',
'rust-skein256.bin',
];
foreach ($fixtureFiles as $fixtureFile) {
if (!is_file("$fixtures/$fixtureFile")) {
throw new RuntimeException(
'Interop fixtures are missing. Run cargo run --release inside interop first.',
);
}
}
$message = file_get_contents("$fixtures/message.bin");
$publicKey = file_get_contents("$fixtures/public-key.bin");
$privateKey = file_get_contents("$fixtures/private-key.bin");
$rustSignature = file_get_contents("$fixtures/rust-signature.bin");
$rustSkein = file_get_contents("$fixtures/rust-skein256.bin");
if (!function_exists('skein_hash') || !function_exists('contractless_shake256')) {
throw new RuntimeException('The Contractless PHP crypto modules are not loaded.');
}
if (!class_exists('OQS_SIGNATURE')) {
throw new RuntimeException('The liboqs-php module is not loaded.');
}
$phpSkein = skein_hash($message, 256);
if (!is_string($phpSkein) || !hash_equals($rustSkein, $phpSkein)) {
throw new RuntimeException('PHP Skein-256 does not match Contractless Rust.');
}
$falcon = new OQS_SIGNATURE('Falcon-padded-512');
$adapted = contractless_shake256($publicKey, 64) . "\0\0" . $message;
if ($falcon->verify($adapted, $rustSignature, $publicKey) !== 0) {
throw new RuntimeException('PHP/liboqs did not verify the Contractless Rust signature.');
}
$phpSignature = '';
if ($falcon->sign($phpSignature, $adapted, $privateKey) !== 0
|| strlen($phpSignature) !== 666
|| $falcon->verify($adapted, $phpSignature, $publicKey) !== 0
) {
throw new RuntimeException('PHP/liboqs Falcon signing failed.');
}
echo "Native Skein and Falcon interoperability tests passed.\n";