JWT : allow to encrypt the payload
git-svn-id: https://svn.fournier38.fr/svn/ProgSVN/trunk@5782 bf3deb0d-5f1a-0410-827f-c0cc1f45334c
This commit is contained in:
@@ -133,4 +133,44 @@ class test_jwt extends PHPUnit_Framework_TestCase
|
|||||||
"eyJwYXlsb2FkIjoidmFsdWUifQ",
|
"eyJwYXlsb2FkIjoidmFsdWUifQ",
|
||||||
"key to use");
|
"key to use");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///////////////////////////////
|
||||||
|
// ENCRYPT THE PAYLOAD //
|
||||||
|
///////////////////////////////
|
||||||
|
/** Check the length of the otken with cipher
|
||||||
|
*/
|
||||||
|
public function testEncrypt1 ()
|
||||||
|
{
|
||||||
|
$jwt = new jwt ();
|
||||||
|
$key = $jwt->createKey ();
|
||||||
|
$res = $jwt->encode (
|
||||||
|
["email" => "toto@example.com", "password" => "ToTo"],
|
||||||
|
$key, "HS256", "123456789012345678901234");
|
||||||
|
$this->assertSame (strlen ($res), 156);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Check if the encrypt/decrypt process return the same result
|
||||||
|
*/
|
||||||
|
public function testEncrypyt2 ()
|
||||||
|
{
|
||||||
|
$jwt = new jwt ();
|
||||||
|
$key = $jwt->createKey ();
|
||||||
|
$payload = (object)["email" => "toto@example.com", "password" => "ToTo"];
|
||||||
|
$token = $jwt->encode ($payload, $key, "HS256", "123456789012345678901234");
|
||||||
|
$res = $jwt->decode ($token, $key, null, "123456789012345678901234");
|
||||||
|
$this->assertSame ($res, $payload);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Check if the encrypted part is well unreadable
|
||||||
|
*/
|
||||||
|
public function testEncrypt3 ()
|
||||||
|
{
|
||||||
|
$jwt = new jwt ();
|
||||||
|
$key = $jwt->createKey ();
|
||||||
|
$payload = (object)["email" => "toto@example.com", "password" => "ToTo"];
|
||||||
|
$token = $jwt->encode ($payload, $key, "HS256", "123456789012345678901234");
|
||||||
|
list ($header, $payload, $signature) = explode (".", $token);
|
||||||
|
$res = strpos (base64_decode ($payload), "email");
|
||||||
|
$this->assertSame ($res, false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
84
jwt.php
84
jwt.php
@@ -26,9 +26,11 @@ class jwt
|
|||||||
* @param string|null $alg The algorithm to use to sign the token (default
|
* @param string|null $alg The algorithm to use to sign the token (default
|
||||||
* is HS256)
|
* is HS256)
|
||||||
* Allowed algorithms : HS256, HS512, HS384
|
* Allowed algorithms : HS256, HS512, HS384
|
||||||
|
* @param string|null $ckey The cipher key to encrypt the payload (24 chars
|
||||||
|
* length)
|
||||||
* @return string The Token
|
* @return string The Token
|
||||||
*/
|
*/
|
||||||
public function encode ($payload, $key, $alg = "HS256")
|
public function encode ($payload, $key, $alg = "HS256", $ckey = null)
|
||||||
// {{{
|
// {{{
|
||||||
{
|
{
|
||||||
if (! key_exists ($alg, $this->supportedAlgs))
|
if (! key_exists ($alg, $this->supportedAlgs))
|
||||||
@@ -37,7 +39,10 @@ class jwt
|
|||||||
$header = array ("typ" => "JWT", "alg" => $alg);
|
$header = array ("typ" => "JWT", "alg" => $alg);
|
||||||
$segments = array ();
|
$segments = array ();
|
||||||
$segments[] = $this->urlsafeB64Encode ($this->jsonEncode ($header));
|
$segments[] = $this->urlsafeB64Encode ($this->jsonEncode ($header));
|
||||||
$segments[] = $this->urlsafeB64Encode ($this->jsonEncode ($payload));
|
$payload = $this->jsonEncode ($payload);
|
||||||
|
if ($ckey)
|
||||||
|
$payload = $this->encrypt ($payload, $ckey);
|
||||||
|
$segments[] = $this->urlsafeB64Encode ($payload);
|
||||||
$toBeSigned = implode ('.', $segments);
|
$toBeSigned = implode ('.', $segments);
|
||||||
$signature = $this->sign ($toBeSigned, $key, $alg);
|
$signature = $this->sign ($toBeSigned, $key, $alg);
|
||||||
$segments[] = $this->urlsafeB64Encode ($signature);
|
$segments[] = $this->urlsafeB64Encode ($signature);
|
||||||
@@ -50,11 +55,13 @@ class jwt
|
|||||||
* @param string $key The key used to sign the message
|
* @param string $key The key used to sign the message
|
||||||
* @param array|null $allowedAlg List of allowed algorithms. If null, all the
|
* @param array|null $allowedAlg List of allowed algorithms. If null, all the
|
||||||
* algorithms defined in $this->supportedAlgs are allowed
|
* algorithms defined in $this->supportedAlgs are allowed
|
||||||
|
* @param string|null $ckey The cipher key to decrypt the payload (24 chars
|
||||||
|
* length)
|
||||||
* @return array the decoded payload
|
* @return array the decoded payload
|
||||||
* @throw Exception if the key is not able to verify the token with the
|
* @throw Exception if the key is not able to verify the token with the
|
||||||
* provided password
|
* provided password
|
||||||
*/
|
*/
|
||||||
public function decode ($jwt, $key, $allowedAlg = null)
|
public function decode ($jwt, $key, $allowedAlg = null, $ckey = null)
|
||||||
// {{{
|
// {{{
|
||||||
{
|
{
|
||||||
if ($allowedAlg === null)
|
if ($allowedAlg === null)
|
||||||
@@ -68,7 +75,10 @@ class jwt
|
|||||||
403);
|
403);
|
||||||
list ($headerb64, $payloadb64, $signb64) = $tks;
|
list ($headerb64, $payloadb64, $signb64) = $tks;
|
||||||
$header = $this->jsonDecode ($this->urlsafeB64Decode ($headerb64));
|
$header = $this->jsonDecode ($this->urlsafeB64Decode ($headerb64));
|
||||||
$payload = $this->jsonDecode ($this->urlsafeB64Decode ($payloadb64));
|
$payload = $this->urlsafeB64Decode ($payloadb64);
|
||||||
|
if ($ckey)
|
||||||
|
$payload = $this->decrypt ($payload, $ckey);
|
||||||
|
$payload = $this->jsonDecode ($payload);
|
||||||
$signature = $this->urlsafeB64Decode ($signb64);
|
$signature = $this->urlsafeB64Decode ($signb64);
|
||||||
if ($header === null)
|
if ($header === null)
|
||||||
throw new \Exception (dgettext ("domframework",
|
throw new \Exception (dgettext ("domframework",
|
||||||
@@ -134,6 +144,72 @@ class jwt
|
|||||||
}
|
}
|
||||||
// }}}
|
// }}}
|
||||||
|
|
||||||
|
/** Encrypt the payload to not be readable by anybody
|
||||||
|
* @param string $payload The payload to encrypt
|
||||||
|
* @param string $ckey The 24 chars for the cipher key
|
||||||
|
* @param string|null $cipherMethod DES-EDE3-CBC by default
|
||||||
|
* @return base64 encrypted payload
|
||||||
|
*/
|
||||||
|
private function encrypt ($payload, $ckey, $cipherMethod = "des-ede3-cbc")
|
||||||
|
// {{{
|
||||||
|
{
|
||||||
|
if (! in_array ($cipherMethod, openssl_get_cipher_methods()))
|
||||||
|
throw new \Exception (dgettext ("domframework",
|
||||||
|
"Invalid cipher provided to encrypt method : ".
|
||||||
|
"doesn't exists in OpenSSL"), 500);
|
||||||
|
if (! is_string ($payload))
|
||||||
|
throw new \Exception (dgettext ("domframework",
|
||||||
|
"Invalid payload provided to encrypt method : ".
|
||||||
|
"Not a string"), 500);
|
||||||
|
if (strlen ($ckey) !== 24)
|
||||||
|
throw new \Exception (dgettext ("domframework",
|
||||||
|
"Invalid cipherKey provided to encrypt method :" .
|
||||||
|
" length different of 24 chars"), 500);
|
||||||
|
// Must be the same as decrypt
|
||||||
|
$options = true;
|
||||||
|
$ivlen = openssl_cipher_iv_length ($cipherMethod);
|
||||||
|
$iv = openssl_random_pseudo_bytes ($ivlen);
|
||||||
|
$ciphertext = openssl_encrypt ($payload, $cipherMethod, $ckey, $options,
|
||||||
|
$iv);
|
||||||
|
if ($ciphertext === false)
|
||||||
|
throw new \Exception (dgettext ("domframework",
|
||||||
|
"Can not encrypt the payload"), 500);
|
||||||
|
$ciphertext = $iv . $ciphertext;
|
||||||
|
return ($ciphertext);
|
||||||
|
}
|
||||||
|
// }}}
|
||||||
|
|
||||||
|
/** Decrypt the payload
|
||||||
|
* @param string $ciphertext The payload to decrypt
|
||||||
|
* @param string $ckey The 24 chars for the cipher key
|
||||||
|
* @param string|null $cipherMethod DES-EDE3-CBC by default
|
||||||
|
* @return decrypted payload
|
||||||
|
*/
|
||||||
|
private function decrypt ($ciphertext, $ckey, $cipherMethod = "des-ede3-cbc")
|
||||||
|
// {{{
|
||||||
|
{
|
||||||
|
if (! is_string ($ciphertext))
|
||||||
|
throw new \Exception (dgettext ("domframework",
|
||||||
|
"Invalid ciphertext provided to decrypt method : not a string"), 500);
|
||||||
|
if (trim ($ciphertext) === "")
|
||||||
|
throw new \Exception (dgettext ("domframework",
|
||||||
|
"Invalid ciphertext provided to decrypt method : empty string"), 500);
|
||||||
|
if (strlen ($ckey) !== 24)
|
||||||
|
throw new \Exception (dgettext ("domframework",
|
||||||
|
"Invalid cipherKey provided to decrypt method :" .
|
||||||
|
" length different of 24 chars"), 500);
|
||||||
|
$ivlen = openssl_cipher_iv_length ($cipherMethod);
|
||||||
|
$iv = substr ($ciphertext, 0, $ivlen);
|
||||||
|
if (strlen ($iv) != $ivlen)
|
||||||
|
throw new \Exception (dgettext ("domframework",
|
||||||
|
"Can not decrypt the payload : invalid salt"), 500);
|
||||||
|
// Must be the same as encrypt
|
||||||
|
$options = true;
|
||||||
|
$ciphertext = substr ($ciphertext, $ivlen);
|
||||||
|
return openssl_decrypt ($ciphertext, $cipherMethod, $ckey, $options, $iv);
|
||||||
|
}
|
||||||
|
// }}}
|
||||||
|
|
||||||
/** Sign the requested string with the provided key and based on the algorithm
|
/** Sign the requested string with the provided key and based on the algorithm
|
||||||
* @param string $input The string to sign
|
* @param string $input The string to sign
|
||||||
* @param string $key The key to use
|
* @param string $key The key to use
|
||||||
|
|||||||
Reference in New Issue
Block a user