Security Complete Examples#

This page groups Security examples around common web application scenes: signed links, CSRF, purpose-bound account tokens and key rotation.

Generate and Verify a Signed URL#

<?php

declare(strict_types=1);

use Infocyph\Epicrypt\Security\SignedUrl;
use Infocyph\Epicrypt\Security\SignedUrlOptions;

$signedUrl = new SignedUrl('url-secret');
$options = new SignedUrlOptions(method: 'GET', allowedHosts: ['example.com']);
$link = $signedUrl->generate('https://example.com/download', ['file' => 'report.csv'], time() + 300, $options);
$linkValid = $signedUrl->verify($link, $options);
$verifyResult = $signedUrl->verifyResult($link, $options);

Issue and Verify a CSRF Token#

<?php

declare(strict_types=1);

use Infocyph\Epicrypt\Security\CsrfTokenManager;

$csrf = new CsrfTokenManager('csrf-secret', 3600);
$csrfToken = $csrf->issueToken('session-123');
$csrfValid = $csrf->verifyToken('session-123', $csrfToken);

Issue Purpose-Bound Account Tokens#

Use these classes for recovery, verification, remembered devices and one-off actions.

<?php

declare(strict_types=1);

use Infocyph\Epicrypt\Security\ActionToken;
use Infocyph\Epicrypt\Security\EmailVerificationToken;
use Infocyph\Epicrypt\Security\Enum\SecurityTokenPurpose;
use Infocyph\Epicrypt\Security\PasswordResetToken;
use Infocyph\Epicrypt\Security\RememberToken;

$reset = new PasswordResetToken('token-secret', 1800);
$resetToken = $reset->issue('user-1');
$resetValid = $reset->verify($resetToken, 'user-1');

$email = new EmailVerificationToken('token-secret', 86400);
$emailToken = $email->issue('user-1', '[email protected]');
$emailValid = $email->verify($emailToken, '[email protected]');

$remember = new RememberToken('token-secret', 1209600);
$rememberToken = $remember->issue('user-1', 'device-1');
$rememberValid = $remember->verify($rememberToken, 'user-1', 'device-1');

$action = new ActionToken('token-secret', 900);
$actionToken = $action->issue('user-1', 'delete-account', ['ip' => '203.0.113.10']);
$actionValid = $action->verify($actionToken, 'user-1', 'delete-account');
$csrfPurpose = SecurityTokenPurpose::CSRF->value;

Rotate Keys Safely#

Use this when signatures must be accepted during a key rollover window.

<?php

declare(strict_types=1);

use Infocyph\Epicrypt\Security\KeyRotationHelper;

$rotation = new KeyRotationHelper();
$keys = ['k1' => 'previous-key', 'k2' => 'active-key'];
$signature = $rotation->sign('payload', 'k2', $keys);
$validWithKid = $rotation->verify('payload', $signature, $keys, 'k2');
$validAgainstWholeSet = $rotation->verify('payload', $signature, $keys);
$verifyResult = $rotation->verifyResult('payload', $signature, $keys);

Use KeyRing Metadata#

Use this when key lifetimes or purpose scope must be enforced by the key set.

<?php

declare(strict_types=1);

use Infocyph\Epicrypt\Security\KeyRing;

$ring = new KeyRing([
    'k-current' => [
        'key' => 'active-key',
        'status' => KeyRing::STATUS_ACTIVE,
        'not_before' => time() - 60,
        'not_after' => time() + 86400,
        'purpose' => 'signed-url',
    ],
    'k-previous' => [
        'key' => 'fallback-key',
        'status' => KeyRing::STATUS_FALLBACK,
        'purpose' => 'signed-url',
    ],
], 'k-current');

$orderedForPurpose = $ring->orderedEntries('signed-url', time());