Search by

trailofbits / wycheproof

tob-scott-a

Wycheproof test vectors for PHP — easy integration with PHPUnit

Package info

github.com/trailofbits/wycheproof-php

pkg:composer/trailofbits/wycheproof

Statistics

Installs: 409

Dependents: 1

Suggesters: 0

Stars: 2

v0.1.1 2026-03-29 03:09 UTC

This package is not auto-updated.

Last update: 2026-10-11 19:33:29 UTC


README

CI

Wycheproof is an extensive collection of test vectors designed to verify the correctness and test against known attacks for existing cryptographic algorithms. Originally developed by Google, Wycheproof is a community-managed project where contributors can add test vectors for specific cryptographic constructions.

Learn more about Wycheproof from the Testing Handbook.

This library provides PHPUnit data providers and traits for running the Wycheproof tests in PHP software.

Installation

composer require --dev trailofbits/wycheproof

Quick Start

Add a trait to your PHPUnit test class and use the provided data providers:

<?php
use PHPUnit\Framework\Attributes\DataProvider;
use PHPUnit\Framework\TestCase;
use TrailOfBits\Wycheproof\TestResult;
use TrailOfBits\Wycheproof\Traits\AeadTestVectors;

class AesGcmTest extends TestCase
{
    use AeadTestVectors;

    #[DataProvider('aesGcmVectors')]
    public function testAesGcmEncrypt(
        int $tcId,
        string $key,
        string $iv,
        string $aad,
        string $msg,
        string $ct,
        string $tag,
        TestResult $result,
        int $keySize,
        int $ivSize,
        int $tagSize,
        string $comment,
        array $flags,
    ): void {
        // All hex values are hex-encoded strings.
        // Decode them to binary before use:
        $keyBin = hex2bin($key);
        $ivBin = hex2bin($iv);

        if ($result->mustFail()) {
            // Expect decryption to fail
        } elseif ($result->mustPass()) {
            // Expect decryption to succeed and match $msg
        }
        // $result->shouldPass() is true for both Valid and Acceptable
    }
}

Available Traits

Trait Data Providers Algorithm
AeadTestVectors aesGcmVectors, chacha20Poly1305Vectors, xchacha20Poly1305Vectors, aesCcmVectors, aesEaxVectors, aesSivCmacVectors, aesGcmSivVectors AEAD ciphers
MacTestVectors hmacSha1Vectors, hmacSha256Vectors, hmacSha384Vectors, hmacSha512Vectors HMAC
HkdfTestVectors hkdfSha1Vectors, hkdfSha256Vectors, hkdfSha384Vectors, hkdfSha512Vectors HKDF
EcdsaTestVectors ecdsaSecp256r1Sha256Vectors, ecdsaSecp384r1Sha384Vectors, ecdsaSecp521r1Sha512Vectors, ecdsaSecp256k1Sha256Vectors ECDSA
EddsaTestVectors ed25519Vectors, ed448Vectors EdDSA
XdhTestVectors x25519Vectors, x448Vectors X25519/X448
RsaSignatureTestVectors rsaPkcs1v15Sha256_2048Vectors, rsaPkcs1v15Sha512_4096Vectors, rsaPssSha256Mgf1_2048Vectors RSA signatures
Pbkdf2TestVectors pbkdf2HmacSha1Vectors, pbkdf2HmacSha256Vectors, pbkdf2HmacSha384Vectors, pbkdf2HmacSha512Vectors PBKDF2

Using Providers Directly

If you prefer not to use traits, call the provider classes directly:

use TrailOfBits\Wycheproof\Provider\AeadProvider;
use TrailOfBits\Wycheproof\Provider\MacProvider;
use TrailOfBits\Wycheproof\Provider\EcdsaProvider;

// Named convenience methods
$vectors = AeadProvider::aesGcm();
$vectors = MacProvider::hmacSha256();

// Or load any test vector file by name
$vectors = AeadProvider::loadAead('aes_gcm');
$vectors = EcdsaProvider::loadEcdsa('ecdsa_secp256r1_sha256');

Generic Provider (ML-DSA, ML-KEM, AEGIS, etc.)

For algorithms not covered by the specialized providers, use GenericProvider:

use PHPUnit\Framework\Attributes\DataProvider;
use PHPUnit\Framework\TestCase;
use TrailOfBits\Wycheproof\Provider\GenericProvider;

class MlDsaTest extends TestCase
{
    /** @return array<string, array<string, mixed>> */
    public static function mlDsa44VerifyVectors(): array
    {
        return GenericProvider::load('mldsa_44_verify', ['parameterSet']);
    }

    #[DataProvider('mlDsa44VerifyVectors')]
    public function testMlDsa44Verify(
        int $tcId,
        string $comment,
        array $flags,
        string $pk,
        string $msg,
        string $sig,
        string $result,
        // ...plus any group fields you requested
    ): void {
        // Each row is an associative array with all test fields
        // plus any group-level fields you specified.
    }
}

GenericProvider::load() accepts any test vector file stem and an optional list of group-level field names to merge into each test row. The rows are associative arrays (not positional), so use named parameters or access by key.

Loading Raw Test Vectors

For full control, use TestVectorLoader directly:

use TrailOfBits\Wycheproof\TestVectorLoader;

// Load raw JSON as an associative array
$data = TestVectorLoader::load('aegis128');

// Flatten test groups into individual test rows
$rows = TestVectorLoader::flatten($data, ['keySize', 'ivSize', 'tagSize']);
foreach ($rows as $row) {
    // $row contains group-level fields + individual test fields
}

Test Vector Format

All cryptographic values (keys, IVs, messages, ciphertexts, signatures, etc.) are hex-encoded strings. Use hex2bin() to decode them to raw bytes before passing to PHP crypto functions.

Each test vector includes a result field:

  • "valid" — the operation should succeed and produce the expected output
  • "invalid" — the operation should fail (bad ciphertext, invalid signature, etc.)
  • "acceptable" — edge cases where both acceptance and rejection are reasonable

Overriding the Vector Directory

By default, test vectors are loaded from the c2sp/wycheproof Composer package. To use a custom directory:

use TrailOfBits\Wycheproof\TestVectorLoader;

TestVectorLoader::setVectorDir('/path/to/testvectors_v1');