Recommend this page to a friend! |
Download |
Info | Example | Files | Install with Composer | Download | Reputation | Support forum | Blog | Links |
Ratings | Unique User Downloads | Download Rankings | ||||
Not yet rated by the users | Total: 69 | All time: 10,305 This week: 571 |
Version | License | PHP version | Categories | |||
paseto 1.0.0 | MIT/X Consortium ... | 5 | PHP 5, Cryptography |
Description | Author | |
This package can be used to Sign, encrypt and decrypt data with Platform-Agnostic Security Tokens protocol. Innovation Award
|
The first thing you should know about Paseto is that it tries to accomplish type-safety by wrapping cryptographic keys inside of objects. For example:
<?php
use ParagonIE\Paseto\Keys\{
AsymmetricSecretKey,
SymmetricKey
};
$privateKey = new AsymmetricSecretKey(sodium_crypto_sign_keypair());
$publicKey = $privateKey->getPublicKey();
$sharedKey = new SymmetricKey(random_bytes(32));
You can access the key's internal strings by invoking $key->raw()
.
No version of the protocol will let you misuse a key by accident.
This will generate a TypeError
:
<?php
use ParagonIE\Paseto\Protocol\Version2;
use ParagonIE\Paseto\Keys\SymmetricKey;
/
* @var SymmetricKey $sharedKey
*/
$token = Version2::sign('some arbitrary data', $sharedKey);
The simplest use-case is to use shared-key authentication to achieve tamper-resistant tokens:
<?php
use ParagonIE\Paseto\Builder;
use ParagonIE\Paseto\Purpose;
use ParagonIE\Paseto\Keys\SymmetricKey;
use ParagonIE\Paseto\Protocol\Version2;
/
* @var SymmetricKey $sharedKey
*/
$token = Builder::getLocal($sharedKey, new Version2());
$token = (new Builder())
->setKey($sharedKey)
->setVersion(new Version2())
->setPurpose(Purpose::local())
// Set it to expire in one day
->setExpiration(
(new DateTime())->add(new DateInterval('P01D'))
)
// Store arbitrary data
->setClaims([
'example' => 'Hello world',
'security' => 'Now as easy as PIE'
]);
echo $token; // Converts automatically to a string
First, you need to define your Parser
rules.
<?php
use ParagonIE\Paseto\Exception\PasetoException;
use ParagonIE\Paseto\Keys\SymmetricKey;
use ParagonIE\Paseto\Parser;
use ParagonIE\Paseto\Purpose;
use ParagonIE\Paseto\Rules\{
IssuedBy,
NotExpired
};
use ParagonIE\Paseto\ProtocolCollection;
/
* @var string $providedToken
* @var SymmetricKey $sharedKey
*/
$parser = Parser::getLocal($sharedKey, ProtocolCollection::v2());
// This is the same as:
$parser = (new Parser())
->setKey($sharedKey)
// Adding rules to be checked against the token
->addRule(new NotExpired)
->addRule(new IssuedBy('issuer defined during creation'))
->setPurpose(Purpose::local())
// Only allow version 2
->setAllowedVersions(ProtocolCollection::v2());
try {
$token = $parser->parse($providedToken);
} catch (PasetoException $ex) {
/Handle invalid token cases here./
}
var_dump($token instanceof \ParagonIE\Paseto\JsonToken);
// bool(true)
Unlike JWT, we don't force you to use JSON. You can store arbitrary binary data in a Paseto, by invoking the Protocol classes directly. This is an advanced usage, of course.
<?php
use ParagonIE\Paseto\Keys\SymmetricKey;
use ParagonIE\Paseto\Protocol\{Version1, Version2};
$key = new SymmetricKey('YELLOW SUBMARINE, BLACK WIZARDRY');
$message = 'This is a signed, non-JSON message.';
$footer = 'key-id:gandalf0';
# Version 1:
$v1Token = Version1::encrypt($message, $key);
var_dump((string) $v1Token);
// string(163) "v1.local.B0VgDOyAtKza1ZCsPzlwQZGTfrpbo1vgzUwCvyxLiSM-gw3TC_KtMqX8woy8BuuE9-pRQNmnTGAru5OmVLzPDnDBHXbd8Sz5rssiTz5TZKLqSyYHsgBzfc53PqsTxLvw09QAy5KBSpKErPX_EfF0Od6-Ig"
var_dump(Version1::decrypt($v1Token, $key));
// string(35) "This is a signed, non-JSON message."
$v1Token = Version1::encrypt($message, $key, $footer);
var_dump((string) $v1Token);
// string(184) "v1.local.vu2ZV_apVDvIhExdenX6rm5w13E3LraRbgN9tabtspSR6KQQt5XdGY5Hho64VRj6Pa6gd-5w5XwmRZbnrxfSVYyvXrVfyDJC7pqQDgae8-MHDg5rZul7kFiH6ExXWx-1hJupWSkRnfQy168PzwS14xiTgw.a2V5LWlkOmdhbmRhbGYw"
var_dump(Version1::decrypt($v1Token, $key, $footer));
// string(35) "This is a signed, non-JSON message."
# Version 2:
$v2Token = Version2::encrypt($message, $key);
var_dump((string) $v2Token);
// string(109) "v2.local.0qOisotef_M2W1gK0b6SiUrO4fkPb24Se0eNJAkALmDvS3IlVu-72birx07hIqU4MYtrCrTJTTElYaWxOyz5Wx8wXh8cQUOF6wOo"
var_dump(Version2::decrypt($v2Token, $key));
// string(35) "This is a signed, non-JSON message."
$v2Token = Version2::encrypt($message, $key, $footer);
var_dump((string) $v2Token);
// string(130) "v2.local.b6ClQBYz-s8k7CC-dEYz2sf3zQFqES4xNUP6K-lzQTRnxVlZFxNnT5I6ouSwYe1d-t9OTnjM9d46MEt__GJvHbNO1wwIfnf1Ear-.a2V5LWlkOmdhbmRhbGYw"
var_dump(Version2::decrypt($v2Token, $key, $footer));
// string(35) "This is a signed, non-JSON message."
Paseto is everything you love about JOSE (JWT, JWE, JWS) without any of the many design deficits that plague the JOSE standards.
What follows is a reference implementation. Requires PHP 7 or newer.
Paseto (Platform-Agnostic SEcurity TOkens) is a specification and reference implementation for secure stateless tokens.
Unlike JSON Web Tokens (JWT), which gives developers more than enough rope with which to hang themselves, Paseto only allows secure operations. JWT gives you "algorithm agility", Paseto gives you "versioned protocols". It's incredibly unlikely that you'll be able to use Paseto in an insecure way.
> Caution: Neither JWT nor Paseto were designed for > stateless session management. > Paseto is suitable for tamper-proof cookies, but cannot prevent replay attacks > by itself.
v2.local.QAxIpVe-ECVNI1z4xQbm_qQYomyT3h8FtV8bxkz8pBJWkT8f7HtlOpbroPDEZUKop_vaglyp76CzYy375cHmKCW8e1CCkV0Lflu4GTDyXMqQdpZMM1E6OaoQW27gaRSvWBrR3IgbFIa0AkuUFw.UGFyYWdvbiBJbml0aWF0aXZlIEVudGVycHJpc2Vz
This decodes to:
Payload (hex-encoded):
400c48a557be10254d235cf8c506e6fea418a26c93de1f05b55f1bc64cfca412
56913f1fec7b653a96eba0f0c46542a8a7fbda825ca9efa0b3632dfbe5c1e628
25bc7b5082915d0b7e5bb81930f25cca9076964c33513a39aa105b6ee06914af
581ad1dc881b1486b4024b9417
* Nonce: `400c48a557be10254d235cf8c506e6fea418a26c93de1f05`
* Authentication tag: `6914af581ad1dc881b1486b4024b9417`
Decrypted Payload:
{
"data": "this is a signed message",
"exp": "2039-01-01T00:00:00+00:00"
}
* Key used in this example (hex-encoded):
707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f
Footer:
Paragon Initiative Enterprises
v2.public.eyJleHAiOiIyMDM5LTAxLTAxVDAwOjAwOjAwKzAwOjAwIiwiZGF0YSI6InRoaXMgaXMgYSBzaWduZWQgbWVzc2FnZSJ91gC7-jCWsN3mv4uJaZxZp0btLJgcyVwL-svJD7f4IHyGteKe3HTLjHYTGHI1MtCqJ-ESDLNoE7otkIzamFskCA
This decodes to:
Payload:
{
"data": "this is a signed message",
"exp": "2039-01-01T00:00:00+00:00"
}
Signature (hex-encoded):
d600bbfa3096b0dde6bf8b89699c59a746ed2c981cc95c0bfacbc90fb7f8207c
86b5e29edc74cb8c761318723532d0aa27e1120cb36813ba2d908cda985b2408
Public key (hex-encoded):
11324397f535562178d53ff538e49d5a162242970556b4edd950c87c7d86648a
To learn what each version means, please see this page in the documentation.
An example JWT (taken from JWT.io) might look like this:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ
This decodes to:
Header:
{
"alg": "HS256",
"typ": "JWT"
}
Body:
{
"sub": "1234567890",
"name": "John Doe",
"admin": true
}
Signature:
TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ
As you can see, with JWT, you get to specify an alg
header. There are a lot of options to
choose from (including none
).
There have been ways to exploit JWT libraries by replacing RS256 with HS256 and using the known public key as the HMAC-SHA256 key, thereby allowing arbitrary token forgery.
With Paseto, your options are version
and a purpose
. There are two possible
values for purpose
:
Paseto only allows you to use authenticated modes.
Regardless of the purpose selected, the header (and an optional footer, which is always cleartext but base64url-encoded) is included in the signature or authentication tag.
See the documentation.
The section dedicated to this PHP implementation may be more relevant.
The curation of other implementations has been moved to paseto.io. See https://github.com/paragonie/paseto-io for the website source code.
If your company uses this library in their products or services, you may be interested in purchasing a support contract from Paragon Initiative Enterprises.
Files (69) |
File | Role | Description | ||
---|---|---|---|---|
docs (1 file, 4 directories) | ||||
src (11 files, 6 directories) | ||||
tests (9 files) | ||||
.travis.yml | Data | Auxiliary data | ||
composer.json | Data | Auxiliary data | ||
LICENSE | Lic. | License text | ||
phpunit.xml.dist | Data | Auxiliary data | ||
psalm.xml | Data | Auxiliary data | ||
README.md | Doc. | Documentation |
Files (69) | / | docs |
File | Role | Description | ||
---|---|---|---|---|
01-Protocol-Versions (4 files) | ||||
02-PHP-Library (1 file) | ||||
03-Implementation-Guide (3 files) | ||||
RFC (6 files) | ||||
README.md | Doc. | Documentation |
Files (69) | / | docs | / | 01-Protocol-Versions |
File | Role | Description |
---|---|---|
Common.md | Data | Auxiliary data |
README.md | Doc. | Documentation |
Version1.md | Data | Auxiliary data |
Version2.md | Data | Auxiliary data |
Files (69) | / | docs | / | 03-Implementation-Guide |
File | Role | Description |
---|---|---|
01-Payload-Processing.md | Data | Auxiliary data |
02-Validators.md | Data | Auxiliary data |
README.md | Doc. | Documentation |
Files (69) | / | docs | / | RFC |
File | Role | Description |
---|---|---|
build.sh | Data | Auxiliary data |
draft-paragon-paseto-rfc-00.txt | Doc. | Documentation |
draft-paragon-paseto-rfc-01.txt | Doc. | Documentation |
GNUmakefile | Data | Auxiliary data |
paseto.md | Data | Auxiliary data |
README.md | Doc. | Documentation |
Files (69) | / | src |
File | Role | Description | ||
---|---|---|---|---|
Exception (8 files) | ||||
Keys (3 files, 2 directories) | ||||
Parsing (2 files) | ||||
Protocol (2 files) | ||||
Rules (6 files) | ||||
Traits (1 file) | ||||
Builder.php | Class | Class source | ||
JsonToken.php | Class | Class source | ||
KeyInterface.php | Class | Class source | ||
Parser.php | Class | Class source | ||
ProtocolCollection.php | Class | Class source | ||
ProtocolInterface.php | Class | Class source | ||
Purpose.php | Class | Class source | ||
ReceivingKey.php | Class | Class source | ||
SendingKey.php | Class | Class source | ||
Util.php | Class | Class source | ||
ValidationRuleInterface.php | Class | Class source |
Files (69) | / | src | / | Exception |
File | Role | Description |
---|---|---|
EncodingException.php | Class | Class source |
InvalidKeyException.php | Class | Class source |
InvalidPurposeException.php | Class | Class source |
InvalidVersionException.php | Class | Class source |
NotFoundException.php | Class | Class source |
PasetoException.php | Class | Class source |
RuleViolation.php | Class | Class source |
SecurityException.php | Class | Class source |
Files (69) | / | src | / | Keys |
File | Role | Description | ||
---|---|---|---|---|
Version1 (3 files) | ||||
Version2 (3 files) | ||||
AsymmetricPublicKey.php | Class | Class source | ||
AsymmetricSecretKey.php | Class | Class source | ||
SymmetricKey.php | Class | Class source |
Files (69) | / | src | / | Keys | / | Version1 |
File | Role | Description |
---|---|---|
AsymmetricPublicKey.php | Class | Class source |
AsymmetricSecretKey.php | Class | Class source |
SymmetricKey.php | Class | Class source |
Files (69) | / | src | / | Keys | / | Version2 |
File | Role | Description |
---|---|---|
AsymmetricPublicKey.php | Class | Class source |
AsymmetricSecretKey.php | Class | Class source |
SymmetricKey.php | Class | Class source |
Files (69) | / | src | / | Parsing |
File | Role | Description |
---|---|---|
Header.php | Class | Class source |
PasetoMessage.php | Class | Class source |
Files (69) | / | src | / | Protocol |
File | Role | Description |
---|---|---|
Version1.php | Class | Class source |
Version2.php | Class | Class source |
Files (69) | / | src | / | Rules |
File | Role | Description |
---|---|---|
ForAudience.php | Class | Class source |
IdentifiedBy.php | Class | Class source |
IssuedBy.php | Class | Class source |
NotExpired.php | Class | Class source |
Subject.php | Class | Class source |
ValidAt.php | Class | Class source |
Files (69) | / | tests |
File | Role | Description |
---|---|---|
JsonTokenTest.php | Class | Class source |
NonceFixer.php | Class | Class source |
ParserTest.php | Class | Class source |
ReadmeTest.php | Class | Class source |
UtilTest.php | Class | Class source |
Version1Test.php | Class | Class source |
Version1VectorTest.php | Class | Class source |
Version2Test.php | Class | Class source |
Version2VectorTest.php | Class | Class source |
The PHP Classes site has supported package installation using the Composer tool since 2013, as you may verify by reading this instructions page. |
Install with Composer |
Version Control | Unique User Downloads | Download Rankings | |||||||||||||||
100% |
|
|
Applications that use this package |
If you know an application of this package, send a message to the author to add a link here.