paragonie / paserk
PHP implementation of PASERK (Platform Agnostic SERialized Keys), a PASETO extension.
Installs: 79 983
Dependents: 2
Suggesters: 4
Security: 0
Stars: 12
Watchers: 7
Forks: 1
Open Issues: 0
Requires
- php: ^8.1
- ext-gmp: *
- ext-json: *
- ext-openssl: *
- paragonie/easy-ecc: ^1.1
- paragonie/hidden-string: ^1|^2
- paragonie/paseto: ^3.1
Requires (Dev)
- phpunit/phpunit: ^9
- vimeo/psalm: ^4
README
Platform Agnostic SERialized Keys. Requires PHP 7.1 or newer.
PASERK Specification
The PASERK Specification can be found in this repository.
Installing
composer require paragonie/paserk
PASERK Library Versions
- PASERK PHP Version 2
- Requires PHP 8.1+
- PASETO versions:
v3
,v4
- This means only the corresponding
k3
andk4
modes are implemented.
- This means only the corresponding
- PASERK PHP Version 1
- Requires PHP 7.1+
- PASETO versions:
v1
,v2
,v3
,v4
- This provides a stable reference implementation for the PASERK specification.
Documentation
See this directory for the documentation.
Example: Public-key Encryption
Wrapping
<?php use ParagonIE\Paseto\Builder; use ParagonIE\Paseto\Keys\SymmetricKey; use ParagonIE\Paseto\Protocol\Version4; use ParagonIE\Paserk\Operations\Key\SealingPublicKey; use ParagonIE\Paserk\Types\Seal; $version = new Version4(); // First, you need a sealing keypair. // $sealingSecret = ParagonIE\Paserk\Operations\Key\SealingSecretKey::generate(); // $sealingPublic = $sealingSecret->getPublicKey(); // var_dump($sealingSecret->encode(), $sealingPublic->encode()); $sealingPublic = SealingPublicKey::fromEncodedString( "vdd1m2Eri8ggYYR5YtnmEninoiCxH1eguGNKe4pes3g", $version ); $sealer = new Seal($sealingPublic); // Generate a random one-time key, which will be encrypted with the public key: $key = SymmetricKey::generate($version); // Seal means "public key encryption": $paserk = $sealer->encode($key); // Now let's associate this PASERK with a PASETO that uses the local key: $paseto = Builder::getLocal($key, $version) ->with('test', 'readme') ->withExpiration( (new DateTime('NOW')) ->add(new DateInterval('P01D')) ) ->withFooterArray(['kid' => $sealer->id($key)]) ->toString(); var_dump($paserk, $paseto);
Unwrapping
<?php use ParagonIE\Paseto\Protocol\Version4; use ParagonIE\Paserk\Operations\Key\SealingSecretKey; use ParagonIE\Paserk\Types\Lid; use ParagonIE\Paserk\Types\Seal; use ParagonIE\Paseto\Parser as PasetoParser; use ParagonIE\Paseto\ProtocolCollection; $version = new Version4(); // From previous example: $paserk = "k4.seal.F2qE4x0JfqT7JYhOB7S12SikvLaRuEpxRkgxxHfh4hVpE1JfwIDnreuhs9v5gjoBl3WTVjdIz6NkwQdqRoS2EDc3yGvdf_Da4K1xUSJ8IVTn4HQeol5ruYwjQlA_Ph4N"; $paseto = "v4.local.hYG-BfpTTM3bb-xZ-q5-w77XGayS4WA8kA5R5ZL85u3nzgrWba5NdqgIouFn71CJyGAff1eloirzz3sWRdVXnDeSIYxXDIerNkbLI5ALn24JehhSLKrv8R2-yhfo_XZF9XEASXtwrOyMNjeEAan5kqO6Dg.eyJraWQiOiJrNC5saWQueDAycGJDRmhxU1Q4endnbEJyR3VqWE9LYU5kRkJjY1dsTFFRN0pzcGlZM18ifQ"; // Keys for unsealing: $sealingSecret = SealingSecretKey::fromEncodedString( "j043XiZTuGLleB0kAy8f3Tz-lEePK_ynEWPp4OyB-lS913WbYSuLyCBhhHli2eYSeKeiILEfV6C4Y0p7il6zeA", $version ); $sealingPublic = $sealingSecret->getPublicKey(); // Unwrap the sytmmetric key for `v4.local.` tokens. $sealer = new Seal($sealingPublic, $sealingSecret); $unwrapped = $sealer->decode($paserk); // Parse the PASETO $parsed = PasetoParser::getLocal($unwrapped, ProtocolCollection::v4()) ->parse($paseto); // Get the claims from the parsed and validated token: var_dump($parsed->getClaims()); /* array(2) { ["test"]=> string(6) "readme" ["exp"]=> string(25) "2038-01-19T03:14:08+00:00" } */ // Observe the Key ID is the same as the value stored in the footer. var_dump(Lid::encode($version, $paserk)); var_dump($parsed->getFooterArray()['kid']); /* string(51) "k4.lid.x02pbCFhqST8zwglBrGujXOKaNdFBccWlLQQ7JspiY3_" string(51) "k4.lid.x02pbCFhqST8zwglBrGujXOKaNdFBccWlLQQ7JspiY3_" */