NovinkaZverejnili sme 50+ Laravel balíkov ako open source
Custom AI apps, agents and automation — Roundly ConsultingRoundly
Všetky balíky

Crypto::fake() neexistuje a nie je potrebné: fasáda nevolá databázu, frontu, udalosti, poštu ani HTTP. Okrem náhodnosti a loaderov kľúčov je každé volanie čistá funkcia svojich argumentov, takže ho v testoch spúšťajte naozaj — a pri náhodnom výstupe overujte tvar, nie hodnotu.

Loadery kľúčov čítajú vašu konfiguráciu alebo disk a fromStorageOrGenerate() pri prvom štarte zapisuje. Všetko ide cez Storage a config() Laravelu, takže Storage::fake('local') a config([...]) vo vašich testoch už pokryjú fromStorageOrGenerate() aj loadery *FromConfig.

Testovacie kľúče a OTP vektory

Menný priestor Testing dáva vašej suite pripravený kľúčový materiál a známe OTP vektory namiesto ručne vyrábaných. Je súčasťou src/, no neimportuje žiadny symbol PHPUnit ani Pest:

use RoundlyConsulting\Crypto\Testing\TestKeys;
use RoundlyConsulting\Crypto\Testing\TestOtp;

$secret = TestKeys::hmacSecret();      // a fixed, valid 64-byte secret (every HS tier)
$rsa    = TestKeys::rsa();             // ephemeral 2048-bit private key
$ec     = TestKeys::ec('P-384');       // ephemeral EC private key

if (TestKeys::supportsEd25519()) {
    $okp = TestKeys::ed25519();        // guard on hosts without ext-sodium
}

$code = TestOtp::codeAt(time());       // a valid TOTP code for TestOtp::SECRET

TestKeys::hmacSecret() je pevný platný 64-bajtový tajný kľúč — dosť dlhý pre každú úroveň HS vrátane HS512 — a TestOtp::SECRET pevný base32 tajný kľúč; továrne RSA, EC a Ed25519 pri každom volaní vytvoria nové dočasné kľúče. Nikdy ich nepoužívajte v produkcii.

Jednorazové reťazce certifikátov

TestCertificates vytvára skutočne prepojené reťazce — so zapísaním vlastného dočasného openssl.cnf s potrebnými sekciami — takže žiadna suite nemusí ručne vyrábať CSR a rozšírenia CA. Kľúče CA sú EC P-256; list môže byť EC alebo RSA:

use RoundlyConsulting\Crypto\Testing\TestCertificates;

$ca = TestCertificates::chain();                  // leaf → intermediate → root, genuinely linked
$ca->leafKey;                                     // the leaf's PRIVATE key — sign your test token with it
$ca->x5c();                                       // ready to drop into a JWS `x5c` header
$ca->pinnedFingerprints();                        // the [intermediate, root] slice a pinning verifier compares
$ca->pemBundle();

$rogue = TestCertificates::rogueLeaf($ca);        // same subject, a different CA — breaks isLinked()
$self  = TestCertificates::selfSigned(['app.test']);

ext-openssl vždy nastaví notBefore na čas podpisu, preto scenáre expirovaného či ešte neplatného certifikátu vytvoríte vyhodnotením v inom okamihu, nie antedatovaním certifikátu:

$leaf = $ca->leaf();

$leaf->isExpiredAt($leaf->notAfter()->addDay());        // expired
$leaf->isNotYetValidAt($leaf->notBefore()->subDay());   // not yet valid
CarbonImmutable::setTestNow($leaf->notAfter()->addYear());

Listy s rozšíreniami

TestLeafOptions doplní list o surové rozšírenia, OID rozšíreného použitia kľúča, SAN typu directoryName, prázdny subjekt alebo OU — takže otestujete vlastné čítanie rozšírenia cez Certificate::extension() a DerDecoder:

use RoundlyConsulting\Crypto\Testing\TestCertificates;
use RoundlyConsulting\Crypto\Testing\TestLeafOptions;

$nonce = random_bytes(32);

$chain = TestCertificates::chain(length: 2, leafOptions: new TestLeafOptions(
    rawExtensions: ['1.2.840.113635.100.8.2' => "\x30\x24\xA1\x22\x04\x20".$nonce],
    subjectOrganizationalUnit: 'Authenticator Attestation',
));

$chain->leaf()->extension('1.2.840.113635.100.8.2')->der;   // exactly the bytes above

Voliteľné Pest expectations

Päť Pest expectations je v súbore, ktorý sa nenačítava automaticky. Pripojte ho cez require vo vlastnom tests/Pest.php — je chránený podmienkou function_exists('expect'), takže sa za behu aplikácie nikdy nenačíta:

// tests/Pest.php
require dirname(__DIR__).'/vendor/roundly-consulting/crypto-for-laravel/src/Testing/pest-expectations.php';

expect($token)->toBeValidJws($verifier, Algorithm::RS256);
expect($code)->toBeValidTotp($secret);
expect($ca->chain)->toBeLinked();                     // the math, not trust
expect($ca->leaf())->toBeSignedBy($ca->chain->get(1));  // the intermediate signed the leaf
expect($ca->chain->get(1))->toBeSignedBy($ca->root());
expect($jwk)->toHaveThumbprint('NzbLsXh8uDCcd-6MNwXF4W_7noWXFZAfHkxZsRGC9Xs');

Kompletný test

use RoundlyConsulting\Crypto\Jose\Jws;
use RoundlyConsulting\Crypto\Signature\Algorithm;
use RoundlyConsulting\Crypto\Signature\Es;
use RoundlyConsulting\Crypto\Signature\Key\EcKey;
use RoundlyConsulting\Crypto\Testing\TestKeys;
use RoundlyConsulting\Crypto\Testing\TestOtp;

it('issues a verifiable ES256 token', function () {
    $key = TestKeys::ec();                                  // ephemeral P-256 private key
    $token = (new Jws)->sign([], ['sub' => 'alice'], new Es($key));

    expect($token)->toBeValidJws(new Es(EcKey::public($key->publicPem())), Algorithm::ES256);
});

it('accepts the current TOTP code', function () {
    expect(TestOtp::codeAt(time()))->toBeValidTotp(TestOtp::SECRET);
});

Pripnutie času

Totp a Claims::assertTemporal() čítajú aktuálny čas cez CarbonImmutable::now(), preto ho pripnite pomocníkom Laravelu:

use Illuminate\Support\Carbon;

Carbon::setTestNow('2026-07-10 12:00:00');
// … assert TOTP codes / token expiry deterministically …
Carbon::setTestNow();   // clear

Vlastná suite balíka

Balík svoje správanie pripína zafixovanými testovacími vektormi z RFC, korpusmi Project Wycheproof a fuzz testami na každom vstupe, ktorý môže ovplyvniť útočník. Z klonu repozitára ich spustíte takto:

composer test
CRYPTO_FUZZ_ITERATIONS=100000 composer test   # a longer fuzz run

Prejavte lásku k open source

Tento balík je zadarmo pod licenciou MIT. Ak vám šetrí čas, jednorazový príspevok alebo členstvo na Patreone nám pomôže ho ďalej udržiavať, testovať a dokumentovať.

Ďalšie spôsoby podpory vrátane kryptomien

Odoslaním daru súhlasíte s našimi podmienkami prijímania darov.

Chcete to zabudovať do svojho produktu?

Naše balíky integrujeme do zákazkových Laravel a AI riešení. Napíšte nám, na čom pracujete, a ozveme sa do 48 hodín.