This library aims to provide an implementation of:
- JWS JSON Web Signature (RFC 7515),
- JWT JSON Web Token (RFC 7519),
- JWE JSON Web Encryption (RFC 7516),
- JWA JSON Web Algorithms (RFC 7518).
- JWK JSON Web Key (RFC 7517).
Tests vectors from RFC 7520 are fully implemented and all test pass.
This library supports JSON Web Key Thumbprint (RFC 7638).
The RFC7797 (SON Web Signature (JWS) Unencoded Payload Option) is not yet supported.
- Plain text
- Array
- JWTInterface object
- jwk+json content type (JWKInterface object)
- jwkset+json content type (JWKSetInterface object)
- Detached content
- JSON Compact Serialization Overview (JWS/JWE creation and loading)
- JSON Flattened Serialization Overview (JWS/JWE creation and loading)
- JSON General Serialization Overview (JWS/JWE creation and loading)
- Deflate —DEF—
- GZip —GZ— (this compression method is not described in the specification)
- ZLib —ZLIB— (this compression method is not described in the specification)
- None keys (
none
) - Symmetric keys (
oct
) - Asymmetric keys based on RSA keys (
RSA
) - Asymmetric keys based on Elliptic Curves (
EC
) - Asymmetric keys based on Octet Key Pair (
OKP
)
JWK objects support JSON Web Key Thumbprint (RFC 7638).
JWKSet is fully supported.
- HS256, HS384, HS512
- ES256, ES384, ES512 (third party library needed)
- RS256, RS384, RS512
- PS256, PS384, PS512
- none (Please note that this is not a secured algorithm. DO NOT USE IT PRODUCTION!)
- Ed25519 (third party extension needed)
- Ed25519ph
- Ed448
- Ed448ph
- dir
- RSA1_5
- RSA-OAEP
- RSA-OAEP-256
- ECDH-ES (third party library needed)
- ECDH-ES+A128KW (third party library needed)
- ECDH-ES+A192KW (third party library needed)
- ECDH-ES+A256KW (third party library needed)
- A128KW
- A192KW
- A256KW
- PBES2-HS256+A128KW
- PBES2-HS384+A192KW
- PBES2-HS512+A256KW
- A128GCMKW (third party extension recommended)
- A192GCMKW (third party extension recommended)
- A256GCMKW (third party extension recommended)
- X25519
- X448
- A128CBC-HS256
- A192CBC-HS384
- A256CBC-HS512
- A128GCM (third party extension recommended)
- A192GCM (third party extension recommended)
- A256GCM (third party extension recommended)
The release process is described here.
This library needs at least:
Please consider the following optional requirements:
- For AES-GCM based algorithms (
AxxxGCM
andAxxxGCMKW
): PHP Crypto Extension (at leastv0.2.1
) is highly recommended as encryption/decryption is faster than the pure PHP implementation. - For ECC based algorithms: PHP ECC (
v0.3
only andfgrosse/phpasn1
versiondev-compat/php5-5 as v1.3.1
). - For Ed25519 algorithm: php-ed25519-ext required
Please read performance test results concerning the ECC based algorithms. As the time needed to perform operation is very long compared to the other algorithms, we do not recommend their use.
It has been successfully tested using PHP 5.5.9
, PHP 5.6
and PHP 7
and HHVM
with all algorithms.
We also track bugs and code quality using Scrutinizer-CI and Sensio Insight.
Coding Standards are verified by StyleCI.
Code coverage is analyzed by Coveralls.io.
The preferred way to install this library is to rely on Composer:
composer require spomky-labs/jose
By default, tests and documentation files are not included. If you want to test this project or read the documentation, please add the option --prefer-source
.
composer require spomky-labs/jose --prefer-source
The easiest way to create a JWS with single signature or JWE with single recipient is to use our factories.
use Jose\Factory\JWKFactory;
use Jose\Factory\JWSFactory;
// We create our payload
$payload = [
'exp' => time()+3600, // Expiration claim (expires in 3600 seconds)
'iat' => time(), // Issued At claim
'nbf' => time(), // Not Before claim
'aud' => 'My client', // Audience claim
'iss' => 'My Server', // Issuer claim
'sub' => 'My User', // Subject claim
'root'=> true, // Custom claim
];
// We create our header
$header = [
'cty' => 'JWT',
'alg' => 'RS512',
];
// We load our private key used to sign
$jwk = JWKFactory::createFromKeyFile(/path/to/my/private.rsa.encrypted.key', 'Secret');
// We create our JWS
$jws = JWSFactory::createJWSToCompactJSON($payload, $jwk, $header);
use Jose\Factory\JWKFactory;
use Jose\Factory\JWEFactory;
// In this example, the payload will be the JWS created above
// We create our header
$header = [
'alg' => 'RSA1_5',
'enc' => 'A256GCM',
];
// We load the public key of the recipient
$jwk = JWKFactory::createFromKeyFile(/path/to/my/public.rsa.key');
// We create our JWE
$jwe = JWEFactory::createJWEToCompactJSON($jws, $jwk, $header);
Have a look at How to use to know how to load your JWT and discover all possibilities provided by this library.
Take a look on the test results performed by Travis-CI. We added some tests to verify the performance of each algorithm.
Please note that the time per signature will be different on your platform.
The conclusions reached regarding these results are:
- Signature operations:
- The HMAC signature performances are very good.
- The RSA signature performances are good.
- The ECC signature performances are very bad. This is due to the use of a pure PHP library.
- Key Encryption operations:
- The algorithms based on RSA are very good.
- The AES GCM Key Wrapping algorithms are very good if the extension is installed, else performances are bad.
- The AES Key Wrapping algorithms are good.
- The PBES2-* algorithms performances bad, except if you use small salt and low count which is not what you intent to do.
- The ECC encryption performances are very bad. This is due to the use of a pure PHP library.
- Content Encryption operations:
- All A128CBC-* algorithms are very good.
- A128GCM-* algorithms are very good if the extension is installed, else performances are bad.
To conclude, if you use shared keys, you will prefer HMAC signature algorithms and AES/AES GCM key wrapping algorithms. If you use public/private key pairs, you will prefer RSA algorithms for signature and key encryption.
At this moment, we do not recommend the use of ECC algorithms.
Hereafter a table with all signature/verification test results.
Algorithm | Signature | Verification |
---|---|---|
none | 0.002120 msec | 0.002561 msec |
HS256 | 0.063560 msec | 0.011048 msec |
HS384 | 0.008521 msec | 0.013590 msec |
HS512 | 0.009749 msec | 0.011101 msec |
RS256 | 3.185160 msec | 0.408080 msec |
RS384 | 2.673111 msec | 0.392590 msec |
RS512 | 2.616920 msec | 0.387020 msec |
PS256 | 2.711060 msec | 0.338850 msec |
PS384 | 2.658789 msec | 0.305960 msec |
PS512 | 2.691140 msec | 0.352941 msec |
ES256 | 119.703550 msec | 335.086281 msec |
ES384 | 201.914010 msec | 571.660171 msec |
ES512 | 316.626689 msec | 895.848720 msec |
Ed25519 | 0.042379 msec | 0.109930 msec |
Not tested as there is no ciphering process with this algorithm.
Algorithm | Key Agreement |
---|---|
ECDH-ES (P-256) | 196.068900 msec |
ECDH-ES (P-384) | N/A |
ECDH-ES (P-521) | 568.323238 msec |
Algorithm | Wrapping | Unwrapping |
---|---|---|
ECDH-ES+A128KW (P-256) | 201.839530 msec | 210.227959 msec |
ECDH-ES+A128KW (P-384) | N/A | N/A |
ECDH-ES+A128KW (P-521) | 577.361839 msec | 580.698538 msec |
ECDH-ES+A192KW (P-256) | 221.429391 msec | 227.398269 msec |
ECDH-ES+A192KW (P-384) | N/A | N/A |
ECDH-ES+A192KW (P-521) | 591.375620 msec | 591.996751 msec |
ECDH-ES+A256KW (P-256) | 204.114299 msec | 220.426919 msec |
ECDH-ES+A256KW (P-384) | N/A | N/A |
ECDH-ES+A256KW (P-521) | 596.029930 msec | 572.769132 msec |
Algorithm | Wrapping | Unwrapping |
---|---|---|
A128KW | 2.684588 msec | 2.543530 msec |
A192KW | 2.597601 msec | 2.532120 msec |
A256KW | 2.644479 msec | 2.608180 msec |
A128GCMKW | 0.022180 msec | 0.015359 msec |
A128GCMKW(1) | 9.724200 msec | 8.727851 msec |
A192GCMKW | 0.020292 msec | 0.014329 msec |
A192GCMKW(1) | 9.288480 msec | 9.948759 msec |
A256GCMKW | 0.020370 msec | 0.014551 msec |
A256GCMKW(1) | 9.685671 msec | 8.994040 msec |
PBES2-HS256+A128KW(2) | 12.351940 msec | 12.727599 msec |
PBES2-HS384+A192KW(2) | 15.622742 msec | 16.451840 msec |
PBES2-HS512+A256KW(2) | 15.600979 msec | 15.592752 msec |
- (1) Tests using the PHP/Openssl method instead of the PHP Crypto extension
- (2) Tests using default salt length (512 bits) and counts (4096) values
Algorithm | Encryption | Decryption |
---|---|---|
RSA 1_5 | 1.056662 msec | 2.835732 msec |
RSA-OAEP | 0.314999 msec | 2.594349 msec |
RSA-OAEP-256 | 0.320430 msec | 2.721188 msec |
Algorithm | Encryption | Decryption |
---|---|---|
A128CBC-HS256 | 0.070095 msec | 0.034094 msec |
A192CBC-HS384 | 0.031948 msec | 0.025988 msec |
A256CBC-HS512 | 0.025034 msec | 0.012875 msec |
A128GCM | 0.070095 msec | 0.034094 msec |
A128GCM(1) | 67.502975 msec | 57.278872 msec |
A192GCM | 0.070095 msec | 0.034094 msec |
A192GCM(1) | 64.872026 msec | 64.872026 msec |
A256GCM | 0.070095 msec | 0.034094 msec |
A256GCM(1) | 61.682940 msec | 57.463884 msec |
- (1) Tests using the PHP/Openssl method instead of the PHP Crypto extension
Requests for new features, bug fixed and all other ideas to make this library useful are welcome. Please follow these best practices.
This software is release under MIT licence.