abmmhasan / safeguard
Modern cryptography, token, password and data-protection toolkit for PHP.
Requires
- php: >=8.4
- ext-hash: *
- ext-json: *
- ext-openssl: *
- ext-sodium: *
- infocyph/pathwise: ^3.0
- phpseclib/phpseclib: ^3.0
- psr/clock: ^1.0
- psr/http-client: ^1.0
- psr/http-factory: ^1.0
- psr/simple-cache: ^3.0
Requires (Dev)
- infocyph/phpforge: dev-main@dev
- nyholm/psr7: ^1.8
- php-http/mock-client: ^1.6
README
Epicrypt is a capability-first PHP security toolkit.
It provides focused security building blocks for:
- Certificate / PKI / key exchange
- Crypto primitives
- Token security (JWT, payload, opaque)
- Password and secret protection
- Integrity verification
- Secure generation
- Data protection workflows
- Security utilities (signed URL, CSRF, reset/action tokens)
Installation
composer require infocyph/epicrypt
Requirements
- PHP
>=8.4 ext-sodium,ext-openssl,ext-json,ext-hash
Usage Examples
Encrypt and decrypt a string
<?php declare(strict_types=1); use Infocyph\Epicrypt\DataProtection\ProtectionOptions; use Infocyph\Epicrypt\DataProtection\StringProtector; use Infocyph\Epicrypt\Generate\KeyMaterial\KeyMaterialGenerator; $key = (new KeyMaterialGenerator())->forAead(); $options = new ProtectionOptions('application-secret'); $protector = StringProtector::create(); $ciphertext = $protector->protect('secret-value', $key, $options); $plaintext = $protector->unprotect($ciphertext, $key, $options);
Encrypt and decrypt a file
<?php declare(strict_types=1); use Infocyph\Epicrypt\DataProtection\FileProtector; use Infocyph\Epicrypt\DataProtection\ProtectionOptions; use Infocyph\Epicrypt\Generate\KeyMaterial\KeyMaterialGenerator; $key = (new KeyMaterialGenerator())->forSecretStream(); $options = new ProtectionOptions('file-backup'); $files = new FileProtector(); $files->protect('/data/plain.txt', '/data/plain.txt.ep2', $key, $options); $files->unprotect('/data/plain.txt.ep2', '/data/plain.out.txt', $key, $options);
Rotate keys with a key ring
<?php declare(strict_types=1); use Infocyph\Epicrypt\DataProtection\ProtectionOptions; use Infocyph\Epicrypt\DataProtection\StringProtector; use Infocyph\Epicrypt\Security\KeyPurpose; use Infocyph\Epicrypt\Security\KeyRing; use Infocyph\Epicrypt\Security\KeyRingEntry; use Infocyph\Epicrypt\Security\KeyStatus; $ring = new KeyRing([ new KeyRingEntry('2026-01', $oldKey, KeyStatus::FALLBACK, KeyPurpose::DATA_PROTECTION, 'xchacha20-poly1305-ietf'), new KeyRingEntry('2026-05', $newKey, KeyStatus::ACTIVE, KeyPurpose::DATA_PROTECTION, 'xchacha20-poly1305-ietf'), ]); $options = new ProtectionOptions('rotating-data'); $protector = StringProtector::create(); $ciphertext = $protector->protectWithKeyRing('rotating-data', $ring, $options); $result = $protector->unprotectWithKeyRing($ciphertext, $ring, $options);
Hash, verify and rehash password
<?php declare(strict_types=1); use Infocyph\Epicrypt\Password\PasswordHasher; $hasher = new PasswordHasher(); $hash = $hasher->hashPassword('MyStrongPassword!2026'); $isValid = $hasher->verifyPassword('MyStrongPassword!2026', $hash); $rehash = $hasher->verifyAndRehash('MyStrongPassword!2026', $hash);
Issue and verify CSRF token
<?php declare(strict_types=1); use Infocyph\Epicrypt\Security\CsrfTokenManager; $csrf = new CsrfTokenManager('csrf-secret'); $token = $csrf->issueToken('session-1'); $ok = $csrf->verifyToken('session-1', $token);
Generate and verify signed URL
<?php declare(strict_types=1); use Infocyph\Epicrypt\Security\SignedUrl; $signed = new SignedUrl('url-secret'); $url = $signed->generate('https://example.com/download', ['file' => 'report.pdf'], time() + 300); $ok = $signed->verify($url);
Issue and verify JWT (HS512)
<?php declare(strict_types=1); use Infocyph\Epicrypt\Token\Jwt\JwtClaims; use Infocyph\Epicrypt\Token\Jwt\JwtPolicy; use Infocyph\Epicrypt\Token\Jwt\SymmetricJwt; $key = SymmetricJwt::generateBinaryKey(); $claims = JwtClaims::issue( 'issuer-service', 'user-1', ['api'], 600, ['client_id' => 'web-client', 'scope' => 'profile:read'], ); $token = SymmetricJwt::issuer($key, 'at+jwt')->issue($claims); $verifier = SymmetricJwt::verifier($key, JwtPolicy::oauthAccessToken('issuer-service', 'api')); $ok = $verifier->verify($token);
Issue and rotate an OAuth refresh token
<?php declare(strict_types=1); use Infocyph\Epicrypt\Token\Opaque\RefreshTokenGrant; use Infocyph\Epicrypt\Token\Opaque\RefreshTokenManager; // Implement RefreshTokenStoreInterface with one durable database transaction. $refreshTokens = new RefreshTokenManager($refreshTokenStore); $refreshToken = $refreshTokens->issue(new RefreshTokenGrant( id: 'authorization-grant-42', subject: 'user-1', clientId: 'web-client', audiences: ['api'], scopes: ['profile:read', 'orders:read'], expiresAt: time() + 90 * 24 * 60 * 60, )); $rotation = $refreshTokens->rotate( $presentedRefreshToken, 'web-client', requestedScopes: ['profile:read'], ); if (!$rotation->rotated) { throw new RuntimeException('Map every failure status to invalid_grant.'); } $replacementRefreshToken = $rotation->token;
The complete OAuth lifecycle connects initial issuance, API verification, DPoP, rotation and revocation. The token storage guide defines the required schema and atomic transaction. Raw refresh tokens must never be stored.
Generate certificate with SAN
<?php declare(strict_types=1); use Infocyph\Epicrypt\Certificate\CertificateOptions; use Infocyph\Epicrypt\Certificate\Enum\OpenSslRsaBits; use Infocyph\Epicrypt\Certificate\KeyPairGenerator; use Infocyph\Epicrypt\Certificate\OpenSSL\CertificateBuilder; $pair = KeyPairGenerator::openSsl(bits: OpenSslRsaBits::BITS_3072)->generate(); $dn = ['commonName' => 'service.example.test']; $options = new CertificateOptions( sanDns: ['service.example.test', 'api.example.test'], ); $certPem = (new CertificateBuilder())->selfSign($dn, $pair['private'], options: $options);
Security
Do not disclose suspected vulnerabilities in a public issue, discussion or pull request. Review the security policy, then use GitHub private vulnerability reporting to contact the maintainers confidentially.
Epicrypt is protected by PHPForge, an automated quality and security gate covering tests, static and taint analysis, dependency auditing, architecture checks, and release readiness. Automated controls reduce risk but do not replace responsible disclosure or manual review.
Made with ❤️ for the PHP communityMIT Licensed
Documentation • Security • Code of Conduct • Contributing
🗂️ Bug • Feature • Documentation • Question • CI failure
🔀 General • Bug fix • Feature • Refactor • Performance • Security & reliability • Documentation • Maintenance