Skip to content
This repository has been archived by the owner on Dec 30, 2020. It is now read-only.

Commit

Permalink
Doc updated and methods added
Browse files Browse the repository at this point in the history
  • Loading branch information
Florent Morselli committed May 30, 2016
1 parent 507af97 commit d8c0188
Show file tree
Hide file tree
Showing 6 changed files with 215 additions and 28 deletions.
3 changes: 2 additions & 1 deletion doc/Keys.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ This page lists algorithms and supported key types.
* `RS256`, `RS384`, `RS512`, `PS256`, `PS384` and `PS512`: `RSA` type,
* `HS256`, `HS384` and `HS512`: `oct` type,
* `none`: `none` type,
* `Ed25519`: `OKP` type,
* `Ed25519`, `Ed448`: `OKP` type.

# Key encryption

Expand All @@ -19,3 +19,4 @@ This page lists algorithms and supported key types.
* `PBES2-HS256+A128KW`, `PBES2-HS384+A192KW` and `PBES2-HS512+A256KW`: `oct` type,
* `A256KW`, `A384KW` and `A512KW`: `oct` type,
* `A256GCMKW`, `A384GCMKW` and `A512GCMKW`: `oct` type.
* `X25519`, `X448`: `OKP` type.
7 changes: 7 additions & 0 deletions doc/Use.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,13 @@ Before to start, you need to know object types provided by this library and the
* [Encrypt a message](operation/Encrypt.md)
* [Decrypt a JWE](operation/Decrypt.md)

# JWT Creator and JWTLoader

In general, you will need to create and load JWS or encrypted JWS (JWS as payload of a JWE) in compact JSON serialization mode.
To ease the creation and loading of such data, the library provides two classes that have convenient methods.

Read the [dedicated page](operation/JWTCreator_And_JWTLoader.md) to know how to instantiate and use these classes.

# PSR-3 Messages

The `Signer`, `Verifier`, `Encrypter` and `Decrypter` classes are able to send debug messages compliant with the [PSR-3 Specification](http://www.php-fig.org/psr/psr-3/).
Expand Down
148 changes: 148 additions & 0 deletions doc/operation/JWTCreator_And_JWTLoader.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,148 @@
JWT Creator and JWT Loader
=====================

Because you mainly need to deal with JWS and encrypted JWS (as a payload of a JWE) in Compact JSON serialization mode, these two components are made for you.

# JWT Creator

The JWT Creator is available through the `Jose\JWTCreator` class.
This component just needs a [Signer](Sign.md) to be instantiated.

```php
use Jose\JWTCreator;

$jwt_creator = new JWTCreator($signer); // The variable $signer must be a valid Jose\SignerInterface object
```

Then, you will be able to create JWS objects using one single line:

```php
$jws = $jwt_creator->sign(
$payload, // The payload to sign
$headers, // The protected headers (must contain at least the "alg" parameter)
$signature_key // The key used to sign (depends on the "alg" parameter)
);
```

## Encryption Support

If you need to create JWE, then you have to enable the encryption support using a valid Encrypter object.

```php
$jwt_creator->enableEncryptionSupport($encrypter); // The variable $encrypter must be a valid Jose\EncrypterInterface object
```

Now you can create JWE as easily as a JWS:

```php
$jwe = $jwt_creator->encrypt(
$payload, // The payload to encrypt
$headers, // The shared protected headers (must contain at least the "alg" and "enc" parameters)
$encryption_key // The key used to encrypt (depends on the "alg" parameter)
);
```

If you want to sign and encrypt at once, then use the following convenient method: `signAndEncrypt`.

```php
$jwe = $jwt_creator->signAndEncrypt(
$payload, // The payload to encrypt
$signature_headers, // The protected headers (must contain at least the "alg" parameter)
$signature_key, // The key used to sign (depends on the "alg" parameter)
$encryption_headers, // The shared protected headers (must contain at least the "alg" and "enc" parameters)
$encryption_key // The key used to encrypt (depends on the "alg" parameter)
);
```

## Other Methods

You also may need to know supported algorithms or if encryption is supported:

* `getSupportedSignatureAlgorithms()`: returns the supported signature algorithms.
* `getSupportedKeyEncryptionAlgorithms()`: returns the supported key encryption algorithms.
* `getSupportedContentEncryptionAlgorithms()`: returns the supported content encryption algorithms.
* `getSupportedCompressionMethods()`: returns the supported compression methods.
* `isEncryptionSupportEnabled()`: returns `true` if the encryption support is enabled or not.


# JWT Loader

The JWT Loader is available through the `Jose\JWTLoader` class.
This component just needs a [Verifier](Verify.md) to be instantiated.

```php
use Jose\JWTLoader;

$jwt_loader = new JWTLoader($verifier); // The variable $verifier must be a valid Jose\VerifierInterface object
```

Then, you will be able to load JWS objects using one single line:

```php
$jws = $jwt_loader->load(
$input, // The JWS string you want to load
);
```


If the method succeeded, the `$jws` variable will contain a valid `Jose\JWSInterface` object.
*Note that the method `load` will always return a JWS or an exception will be thrown.*

The resulting JWS is not yet verified. You MUST check the signature and claims (if available):

```php
$index = $jwt_loader->verify(
$jws, // The JWS object
$key_set // A Jose\JWKSetInterface object that contains public keys
);
```

The variable `$index` contains the index of the verified signature

If the JWS you want to verify has a detached payload, then set the detached payload as the third argument:

```php
$index = $jwt_loader->verify(
$jws, // The JWS object
$key_set // A Jose\JWKSetInterface object that contains public keys
$detached_payload // The detached payload
);
```

## Decryption Support

If you need to load an encrypted JWS (JWS as payload of a JWE), then you have to enable the decryption support using a valid Decrypter object.

```php
$jwt_loader->enableDecryptionSupport($decrypter); // The variable $decrypter must be a valid Jose\DecrypterInterface object
```

The method to call is the same as previously shown, but you have to set a JWKSet object as second argument.
This JWKSet object mut contain private keys or shared keys used to decrypt the input.

```php
$jws = $jwt_loader->load(
$input, // The JWS or JWE string you want to load
$jwk_set // The JWKSet object
);
```

If an encrypted JWS is expected, then you can set the third argument as `true`:

```php
$jws = $jwt_loader->load(
$input, // The JWE string you want to load
$jwk_set, // The JWKSet object
true // The input must be an encrypted JWS (JWS as payload of a JWE) else an exception will be thrown
);
```

## Other Methods

You also may need to know supported algorithms or if decryption is supported:

* `getSupportedSignatureAlgorithms()`: returns the supported signature algorithms.
* `getSupportedKeyEncryptionAlgorithms()`: returns the supported key decryption algorithms.
* `getSupportedContentEncryptionAlgorithms()`: returns the supported content decryption algorithms.
* `getSupportedCompressionMethods()`: returns the supported compression methods.
* `isDecryptionSupportEnabled()`: returns `true` if the decryption support is enabled or not.
33 changes: 29 additions & 4 deletions src/JWTCreator.php
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ public function sign($payload, array $signature_protected_headers, JWKInterface
*/
public function encrypt($payload, array $encryption_protected_headers, JWKInterface $encryption_key)
{
Assertion::notNull($this->encrypter, 'The encryption support is not enabled');
Assertion::true($this->isEncryptionSupportEnabled(), 'The encryption support is not enabled');

$jwe = JWEFactory::createJWE($payload, $encryption_protected_headers);
$jwe = $jwe->addRecipientInformation($encryption_key);
Expand All @@ -81,6 +81,23 @@ public function encrypt($payload, array $encryption_protected_headers, JWKInterf
return $jwe->toCompactJSON(0);
}

/**
* @param mixed $payload
* @param array $signature_protected_headers
* @param \Jose\Object\JWKInterface $signature_key
* @param array $encryption_protected_headers
* @param \Jose\Object\JWKInterface $encryption_key
*
* @return string
*/
public function signAndEncrypt($payload, array $signature_protected_headers, JWKInterface $signature_key, array $encryption_protected_headers, JWKInterface $encryption_key)
{
$jws = $this->sign($payload, $signature_protected_headers, $signature_key);
$jwe = $this->encrypt($jws, $encryption_protected_headers, $encryption_key);

return $jwe;
}

/**
* @return string[]
*/
Expand All @@ -94,22 +111,30 @@ public function getSupportedSignatureAlgorithms()
*/
public function getSupportedKeyEncryptionAlgorithms()
{
return null === $this->encrypter ? [] : $this->encrypter->getSupportedKeyEncryptionAlgorithms();
return false === $this->isEncryptionSupportEnabled() ? [] : $this->encrypter->getSupportedKeyEncryptionAlgorithms();
}

/**
* @return string[]
*/
public function getSupportedContentEncryptionAlgorithms()
{
return null === $this->encrypter ? [] : $this->encrypter->getSupportedContentEncryptionAlgorithms();
return false === $this->isEncryptionSupportEnabled() ? [] : $this->encrypter->getSupportedContentEncryptionAlgorithms();
}

/**
* @return string[]
*/
public function getSupportedCompressionMethods()
{
return null === $this->encrypter ? [] : $this->encrypter->getSupportedCompressionMethods();
return false === $this->isEncryptionSupportEnabled() ? [] : $this->encrypter->getSupportedCompressionMethods();
}

/**
* @return bool
*/
public function isEncryptionSupportEnabled()
{
return null !== $this->encrypter;
}
}
48 changes: 27 additions & 21 deletions src/JWTLoader.php
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ public function __construct(CheckerManagerInterface $checker_manager, VerifierIn
/**
* @param \Jose\DecrypterInterface $decrypter
*/
public function enableEncryptionSupport(DecrypterInterface $decrypter)
public function enableDecryptionSupport(DecrypterInterface $decrypter)
{
$this->decrypter = $decrypter;
}
Expand All @@ -73,28 +73,36 @@ public function getSupportedSignatureAlgorithms()
return $this->verifier->getSupportedSignatureAlgorithms();
}

/**
* @return bool
*/
public function isDecryptionSupportEnabled()
{
return null !== $this->decrypter;
}

/**
* @return string[]
*/
public function getSupportedKeyEncryptionAlgorithms()
{
return null === $this->decrypter ? [] : $this->decrypter->getSupportedKeyEncryptionAlgorithms();
return false === $this->isDecryptionSupportEnabled() ? [] : $this->decrypter->getSupportedKeyEncryptionAlgorithms();
}

/**
* @return string[]
*/
public function getSupportedContentEncryptionAlgorithms()
{
return null === $this->decrypter ? [] : $this->decrypter->getSupportedContentEncryptionAlgorithms();
return false === $this->isDecryptionSupportEnabled() ? [] : $this->decrypter->getSupportedContentEncryptionAlgorithms();
}

/**
* @return string[]
*/
public function getSupportedCompressionMethods()
{
return null === $this->decrypter ? [] : $this->decrypter->getSupportedCompressionMethods();
return false === $this->isDecryptionSupportEnabled() ? [] : $this->decrypter->getSupportedCompressionMethods();
}

/**
Expand All @@ -111,7 +119,7 @@ public function load($assertion, JWKSetInterface $encryption_key_set = null, $is
$jwt = $this->loader->load($assertion);
if ($jwt instanceof JWEInterface) {
Assertion::notNull($encryption_key_set, 'Encryption key set is not available.');
Assertion::true($this->isEncryptionSupportEnabled(), 'Encryption support is not enabled.');
Assertion::true($this->isDecryptionSupportEnabled(), 'Encryption support is not enabled.');
Assertion::inArray($jwt->getSharedProtectedHeader('alg'), $this->getSupportedKeyEncryptionAlgorithms(), sprintf('The key encryption algorithm "%s" is not allowed.', $jwt->getSharedProtectedHeader('alg')));
Assertion::inArray($jwt->getSharedProtectedHeader('enc'), $this->getSupportedContentEncryptionAlgorithms(), sprintf('The content encryption algorithm "%s" is not allowed or not supported.', $jwt->getSharedProtectedHeader('enc')));
$jwt = $this->decryptAssertion($jwt, $encryption_key_set);
Expand All @@ -123,11 +131,22 @@ public function load($assertion, JWKSetInterface $encryption_key_set = null, $is
}

/**
* @return bool
* @param \Jose\Object\JWSInterface $jws
* @param \Jose\Object\JWKSetInterface $signature_key_set
* @param string|null $detached_payload
*
* @return int
*/
private function isEncryptionSupportEnabled()
public function verify(JWSInterface $jws, JWKSetInterface $signature_key_set, $detached_payload = null)
{
return null !== $this->decrypter;
Assertion::inArray($jws->getSignature(0)->getProtectedHeader('alg'), $this->getSupportedSignatureAlgorithms(), sprintf('The signature algorithm "%s" is not supported or not allowed.', $jws->getSignature(0)->getProtectedHeader('alg')));

$index = null;
$this->verifier->verifyWithKeySet($jws, $signature_key_set, $detached_payload, $index);
Assertion::notNull($index, 'JWS signature(s) verification failed.');
$this->checker_manager->checkJWS($jws, $index);

return $index;
}

/**
Expand All @@ -145,17 +164,4 @@ private function decryptAssertion(JWEInterface $jwe, JWKSetInterface $encryption

return $jws;
}

/**
* @param \Jose\Object\JWSInterface $jws
* @param \Jose\Object\JWKSetInterface $signature_key_set
*/
public function verifySignature(JWSInterface $jws, JWKSetInterface $signature_key_set)
{
Assertion::inArray($jws->getSignature(0)->getProtectedHeader('alg'), $this->getSupportedSignatureAlgorithms(), sprintf('The signature algorithm "%s" is not supported or not allowed.', $jws->getSignature(0)->getProtectedHeader('alg')));

$index = null;
$this->verifier->verifyWithKeySet($jws, $signature_key_set, null, $index);
$this->checker_manager->checkJWS($jws, $index);
}
}
4 changes: 2 additions & 2 deletions tests/Functional/LoaderAndCreatorTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ public function testSignAndLoadUsingJWTCreatorAndJWTLoader()
Verifier::createVerifier(['HS512', 'RS512']),
$this->getLogger()
);
$jwt_loader->enableEncryptionSupport(Decrypter::createDecrypter(['A256GCMKW'], ['A128CBC-HS256'], ['DEF']));
$jwt_loader->enableDecryptionSupport(Decrypter::createDecrypter(['A256GCMKW'], ['A128CBC-HS256'], ['DEF']));

$jws = $jwt_creator->sign(
'Live long and Prosper.',
Expand Down Expand Up @@ -79,6 +79,6 @@ public function testSignAndLoadUsingJWTCreatorAndJWTLoader()
$key_set,
true
);
$jwt_loader->verifySignature($loaded_jwe, $key_set, ['HS512']);
$jwt_loader->verify($loaded_jwe, $key_set);
}
}

0 comments on commit d8c0188

Please sign in to comment.