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

V2.0.x #83

Merged
merged 54 commits into from
Jan 31, 2016
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
54 commits
Select commit Hold shift + click to select a range
7a58b62
WIP
Jan 26, 2016
be79950
Bugs fixed
Jan 26, 2016
de999d3
Verifier updated
Jan 26, 2016
0e1d669
Applied fixes from StyleCI
Jan 26, 2016
45cd5b4
Merge pull request #76 from Spomky-Labs/analysis-ze70m4
Spomky Jan 26, 2016
7f25869
Some tests updated
Jan 26, 2016
78a4ce1
Examples updated
Jan 27, 2016
2559486
Merge remote-tracking branch 'origin/v2.0.x' into v2.0.x
Jan 27, 2016
c248378
Some tests fixed
Jan 27, 2016
59a3d44
Some tests fixed
Jan 27, 2016
b06cabe
All tests fixed
Jan 28, 2016
11273c6
Delete HasPayloadConverter.php
Spomky Jan 28, 2016
f488cd4
Update .scrutinizer.yml
Spomky Jan 28, 2016
c41274c
Applied fixes from StyleCI
Jan 28, 2016
29f8a50
Merge pull request #77 from Spomky-Labs/analysis-8jLDnr
Spomky Jan 28, 2016
f68836f
Update Loader.php
Spomky Jan 28, 2016
ce8a641
Delete z
Spomky Jan 28, 2016
359f30b
Scrutinizer Auto-Fixes
scrutinizer-auto-fixer Jan 28, 2016
fd9dbee
Merge pull request #78 from Spomky-Labs/scrutinizer-patch-1
Spomky Jan 28, 2016
92da15e
Update README.md
Spomky Jan 28, 2016
da4f235
Update Loader.php
Spomky Jan 28, 2016
9318b46
Update Encrypter.php
Spomky Jan 28, 2016
44658cb
Update Signature.php
Spomky Jan 28, 2016
7a364a5
Update Signature.php
Spomky Jan 28, 2016
a302c6a
Update README.md
Spomky Jan 28, 2016
8492207
Applied fixes from StyleCI
Jan 28, 2016
15bc11d
Merge pull request #79 from Spomky-Labs/analysis-zGDgvO
Spomky Jan 28, 2016
beb4293
Update phpunit.xml.dist
Spomky Jan 28, 2016
c7c6d18
Update .scrutinizer.yml
Spomky Jan 28, 2016
6644e2f
Code optimization
Jan 28, 2016
1446f5d
Code optimization
Jan 28, 2016
5740fbc
Code optimization
Jan 28, 2016
b316258
Code optimization
Jan 28, 2016
24925ee
Code optimization
Jan 28, 2016
1498022
Code optimization
Jan 28, 2016
dc4bfae
Code optimization
Jan 28, 2016
f44d095
Update Use.md
Spomky Jan 29, 2016
2b2b8e5
Tests added
Jan 29, 2016
21aa402
StringUtil used
Jan 29, 2016
08a44b9
Update HMAC.php
Spomky Jan 29, 2016
c50b734
Applied fixes from StyleCI
Jan 29, 2016
94c9504
Merge pull request #80 from Spomky-Labs/analysis-z3wGL1
Spomky Jan 29, 2016
c407925
Tests added and bugs fixed
Jan 29, 2016
99e97aa
Examples fixed
Jan 29, 2016
b6acc27
Tests added and example updated
Jan 30, 2016
26bd76c
Tests added
Jan 31, 2016
3729e43
Tests added
Jan 31, 2016
03259ab
Tests added
Jan 31, 2016
ec9700b
Tests added
Jan 31, 2016
ae27d3b
Tests added
Jan 31, 2016
9fa7fea
Applied fixes from StyleCI
Jan 31, 2016
8e74ea6
Merge pull request #82 from Spomky-Labs/analysis-zYj29v
Spomky Jan 31, 2016
23a51c0
Bugs fixed
Jan 31, 2016
6e3adab
Bugs fixed
Jan 31, 2016
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Bugs fixed
  • Loading branch information
Florent Morselli committed Jan 31, 2016
commit 23a51c0e041c4eb42b93aa423dc63ffd4abb8392
107 changes: 88 additions & 19 deletions doc/Use.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,6 @@ Before to start, you need to know object types provided by this library and the
* [The keys (JWK)](object/jwk.md)
* [The key sets (JWKSet)](object/jwkset.md)

To create these objects, this library provides factories.

* [JWS Factory](factory/jws.md)
* [JWE Factory](factory/jwe.md)
* [JWK Factory](factory/jwe.md)

Please note that there is no factory for the `JWKSet` object (a factory is useless as the object can be instatiate directly).

# The operations

## How To Add A Signature?
Expand Down Expand Up @@ -58,14 +50,14 @@ $key2 = KeyFactory::createFromValues([
$signer = SignerFactory::createSigner(['HS512', 'RS512']);

// We add the first signature using our RSA key and algorithm RS512
$jws = $signer->addSignature(
$signer->addSignature(
$jws,
$key1,
['alg' => 'RS512']
);

// We add the second signature using our shared key and algorithm HS512
$jws = $signer->addSignature(
$signer->addSignature(
$jws,
$key2,
['alg' => 'HS512']
Expand All @@ -75,7 +67,7 @@ $jws = $signer->addSignature(
// We can convert each signature into compact or flattened JSON.
// We can convert the JWS into JSON with all signatures
$jws->toCompactJSON(0); // We convert the first signature (#0) into compact JSON
$jws->toCompactJSON(1); // We convert the second signature (#1) into flattened JSON
$jws->toFlattenedJSON(1); // We convert the second signature (#1) into flattened JSON
$jws->toJSON(); // We convert all signatures into JSON
```

Expand Down Expand Up @@ -115,7 +107,7 @@ $jws = JWSFactory::createJWSWithDetachedPayload(

// We add a signature using our RSA key and algorithm RS512
// Please note that the method is now 'addSignatureWithDetachedPayload' and the third argument is the detached payload
$jws = $signer->addSignatureWithDetachedPayload(
$signer->addSignatureWithDetachedPayload(
$jws,
$key1,
$detached_payload,
Expand All @@ -131,17 +123,74 @@ $jws = $signer->addSignatureWithDetachedPayload(

## How To Add A Recipient (= encrypt)?

**To be written**
To add a recipient on a `JWE` object, you will need to create:

* the `JWE` object itself,
* a key (`JWK` object),
* an `Encrypter` object with algorithm you want to use.

Example
-------

```php
use Jose\Factory\JWEFactory;
use Jose\Factory\KeyFactory;
use Jose\Factory\EncrypterFactory;

// We create our JWE object with claims
$jws = JWEFactory::createJWE(
'My very important information',
[
'enc' => 'A256CBC-HS512',
'zip' => 'DEF',
]
);

// We load two keys
$key1 = KeyFactory::createFromFile('/path/to/my/RSA/public.key');

// We create our Encrypter service and we declare the algorithms we want to use ('A256CBC-HS512' and 'RSA-OAEP-256')
$encrypter = EncrypterFactory::createEncrypter(['A256CBC-HS512', 'RSA-OAEP-256']);

// We add a recipient using our RSA key and algorithm RSA-OAEP-256
$encrypter->addRecipient(
$jwe, // The JWE object
$key1, // The recipient's key
null, // The sender key (needed using EC based algorithms)
['alg' => 'RSA-OAEP-256'] // The recipient' headers (we only declare the algorithm used for key encryption)
);


// Now our JWE object contains the encrypted payload and 1 recipient.
// We can convert each recipient into compact or flattened JSON.
// We can convert the JWE into JSON with all signatures
$jwe->toCompactJSON(0); // We convert the recipient (#0) into compact JSON
$jwe->toFlattenedJSON(1); // We convert the recipient (#0) into flattened JSON
$jwe->toJSON(); // We convert all recipients into JSON
```

### Additional Authenticated Data

This library supports Additional Authenticated Data (AAD).

```php

$jws = JWEFactory::createJWE(
'My very important information',
[
'enc' => 'A256CBC-HS512',
'zip' => 'DEF',
],
[
'shared unprotected header' => 'value',
],
'This is an AAD'
);
```

### Important note
Please note that when a JWE object contains an AAD or unprotected headers (shared or per recipient), the JWE cannot be
converted into compact JSON.

### Multiple recipients support

With this library, you can create encrypt an input using multiple recipients.
In this case, the Key Management Mode is determined according to the used algorithms.
Expand Down Expand Up @@ -181,11 +230,31 @@ And a compatibility table between Key Management Modes:

*: Compatibility is possible only if the algorithm for the first recipient is a `Direct Key Agreement` or a `Direct Encryption` algorithm and there is no other recipient using the same algorithms, otherwise it is not possible

### Important note
## How To Load?

Please note that if a recipient contains unprotected headers or the `JWE` contains unprotected shared headers, it cannot be converted into Compact JSON Serialization mode.
This library provides a simple JWT loader. This loader will return a JWS or JWE object depending on the input.
The loader is able to load compact JSON, flattened JSON or JSON representation.

## How To Load?
```php
use Jose\Loader;

$input = 'eyJhbGciOiJSUzI1NiJ9.eyJuYmYiOjE0NTE0NjkwMTcsImlhdCI6MTQ1MTQ2OTAxNywiZXhwIjoxNDUxNDcyNjE3LCJpc3MiOiJNZSIsImF1ZCI6IllvdSIsInN1YiI6Ik15IGZyaWVuZCJ9.mplHfnyXzUdlEkPmykForVM0FstqgiihfDRTd2Zd09j6CZzANBJbZNbisLerjO3lR9waRlYvhnZu_ewIAahDwmVTfpSeKKABbAyoTHXTH2WLgMPLtOAsoausUf584eAAj_kyldIOV8a83Qz1NztZHVD3DbGTiCN0BOj-qnc65yQmEDEYK5cxG1xC22YK5aohZ3xm8ixwNZpxYr8cNOkauASYjPGODbHqY_gjQ-aKA21kxbYgwM6mDYSc3QRej1_3m6bD3jKPsK4jv3yzosVMEXOparf4sEb8q_zCPMDJAJgZZ8VICwJdgYnJkQuIutS-w3_iT-riKl8fkgmJezQVkg';

// We load the input
$jwt = Loader::load($input);

// The variable $result a valid JWSInterface object.
```

At this stage, no verification or decryption has been performed.

* If the loaded input is a JWS, you MUST verify it
* If the loaded input is a JWE, you MUST decrypt it.

## How to verify a JWS?

** To be written **

**To be written**
## How to decrypt a JWE?

** To be written **
2 changes: 1 addition & 1 deletion examples/Encrypt1.php
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@
);

// Lastly, we add a recipient for our message.
$jwe = $encrypter->addRecipient($jwe, $key);
$encrypter->addRecipient($jwe, $key);

// Now the variable $jwe contains our JWE with one recipient
// Please read example Load3.php to know how to load this string and to decrypt the content.
Expand Down
1 change: 0 additions & 1 deletion examples/Load1.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@
use Jose\Factory\JWKFactory;
use Jose\Factory\VerifierFactory;
use Jose\Loader;
use Jose\Object\JWKSet;

// In this example, our input is a JWS string in compact serialization format
// See Signature1.php to know to generate such string
Expand Down
2 changes: 1 addition & 1 deletion examples/Signature1.php
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@
);

// Lastly, we sign our claims with our key and we add protected headers.
$jws = $signer->addSignature(
$signer->addSignature(
$jws,
$key,
[
Expand Down
2 changes: 1 addition & 1 deletion examples/Signature2.php
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@
// Lastly, we sign our claims (first argument) with our instructions (only one instruction).
// We want a JWS in flattened serialization mode (compact serialization mode cannot be used as an unprotected header is set)
// We also want to detach the payload. The result will not contain the payload. The payload will be set into the last argument
$jws = $signer->addSignatureWithDetachedPayload(
$signer->addSignatureWithDetachedPayload(
$jws,
$key,
$detached_payload,
Expand Down
39 changes: 37 additions & 2 deletions src/Decrypter.php
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,12 @@ public function decryptUsingKey(JWEInterface &$jwe, JWKInterface $jwk)
*/
public function decryptUsingKeySet(JWEInterface &$jwe, JWKSetInterface $jwk_set)
{
foreach ($jwe->getRecipients() as $recipient) {
$this->checkJWKSet($jwk_set);
$this->checkPayload($jwe);
$this->checkRecipients($jwe);

for ($i = 0; $i < $jwe->countRecipients(); $i++) {
$recipient = $jwe->getRecipient($i);
$complete_headers = array_merge(
$jwe->getSharedProtectedHeaders(),
$jwe->getSharedHeaders(),
Expand All @@ -94,7 +99,7 @@ public function decryptUsingKeySet(JWEInterface &$jwe, JWKSetInterface $jwk_set)
if (true === $this->decryptPayload($jwe, $cek, $content_encryption_algorithm, $complete_headers)) {
$this->getCheckerManager()->checkJWT($jwe);

return true;
return $i;
};
}
} catch (\Exception $e) {
Expand All @@ -107,6 +112,36 @@ public function decryptUsingKeySet(JWEInterface &$jwe, JWKSetInterface $jwk_set)
return false;
}

/**
* @param \Jose\Object\JWEInterface $jwe
*/
private function checkRecipients(JWEInterface $jwe)
{
if (0 === $jwe->countRecipients()) {
throw new \InvalidArgumentException('The JWE does not contain any recipient.');
}
}

/**
* @param \Jose\Object\JWEInterface $jwe
*/
private function checkPayload(JWEInterface $jwe)
{
if (null !== $jwe->getPayload()) {
throw new \InvalidArgumentException('The JWE is already decrypted.');
}
}

/**
* @param \Jose\Object\JWKSetInterface $jwk_set
*/
private function checkJWKSet(JWKSetInterface $jwk_set)
{
if (0 === count($jwk_set)) {
throw new \InvalidArgumentException('No key in the key set.');
}
}

/**
* @param \Jose\Algorithm\JWAInterface $key_encryption_algorithm
* @param \Jose\Algorithm\ContentEncryptionAlgorithmInterface $content_encryption_algorithm
Expand Down
4 changes: 2 additions & 2 deletions src/DecrypterInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,15 +24,15 @@ interface DecrypterInterface
* @param \Jose\Object\JWEInterface $input A JWE object to decrypt
* @param \Jose\Object\JWKInterface $jwk The key used to decrypt the input
*
* @return bool Returns true if the JWE has been populated with decrypted values, else false.
* @return false|int Return false if the JWE has not been decrypted, else an integer that represents the ID of the decrypted recipient
*/
public function decryptUsingKey(JWEInterface &$input, JWKInterface $jwk);

/**
* @param \Jose\Object\JWEInterface $input A JWE object to decrypt
* @param \Jose\Object\JWKSetInterface $jwk_set The key set used to decrypt the input
*
* @return bool Returns true if the JWE has been populated with decrypted values, else false.
* @return false|int Return false if the JWE has not been decrypted, else an integer that represents the ID of the decrypted recipient
*/
public function decryptUsingKeySet(JWEInterface &$input, JWKSetInterface $jwk_set);
}
11 changes: 2 additions & 9 deletions src/Encrypter.php
Original file line number Diff line number Diff line change
Expand Up @@ -51,14 +51,9 @@ public function __construct(
}

/**
* @param \Jose\Object\JWEInterface $jwe
* @param \Jose\Object\JWKInterface $recipient_key
* @param \Jose\Object\JWKInterface|null $sender_key
* @param array $recipient_headers
*
* @return \Jose\Object\JWEInterface
* {@inheritdoc}
*/
public function addRecipient(JWEInterface $jwe, JWKInterface $recipient_key, JWKInterface $sender_key = null, array $recipient_headers = [])
public function addRecipient(JWEInterface &$jwe, JWKInterface $recipient_key, JWKInterface $sender_key = null, array $recipient_headers = [])
{
$complete_headers = array_merge(
$jwe->getSharedProtectedHeaders(),
Expand Down Expand Up @@ -153,8 +148,6 @@ public function addRecipient(JWEInterface $jwe, JWKInterface $recipient_key, JWK

$jwe = $jwe->addRecipient($recipient);
}

return $jwe;
}

/**
Expand Down
4 changes: 1 addition & 3 deletions src/EncrypterInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,6 @@ interface EncrypterInterface
* @param \Jose\Object\JWKInterface $recipient_key
* @param \Jose\Object\JWKInterface|null $sender_key
* @param array $recipient_headers
*
* @return \Jose\Object\JWEInterface
*/
public function addRecipient(JWEInterface $jwe, JWKInterface $recipient_key, JWKInterface $sender_key = null, array $recipient_headers = []);
public function addRecipient(JWEInterface &$jwe, JWKInterface $recipient_key, JWKInterface $sender_key = null, array $recipient_headers = []);
}
8 changes: 3 additions & 5 deletions src/Signer.php
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ public function __construct(JWAManagerInterface $jwa_manager)
/**
* {@inheritdoc}
*/
public function addSignatureWithDetachedPayload(JWSInterface $jws, JWKInterface $key, $detached_payload, array $protected_headers = [], array $headers = [])
public function addSignatureWithDetachedPayload(JWSInterface &$jws, JWKInterface $key, $detached_payload, array $protected_headers = [], array $headers = [])
{
$signature = new Signature();
if (!empty($protected_headers)) {
Expand All @@ -55,21 +55,19 @@ public function addSignatureWithDetachedPayload(JWSInterface $jws, JWKInterface
$signature = $signature->withSignature($value);

$jws = $jws->addSignature($signature);

return $jws;
}

/**
* {@inheritdoc}
*/
public function addSignature(JWSInterface $jws, JWKInterface $key, array $protected_headers = [], array $headers = [])
public function addSignature(JWSInterface &$jws, JWKInterface $key, array $protected_headers = [], array $headers = [])
{
if (null === $jws->getEncodedPayload()) {
throw new \InvalidArgumentException('No payload.');
}
$this->checkKeyUsage($key, 'signature');

return $this->addSignatureWithDetachedPayload($jws, $key, $jws->getEncodedPayload(), $protected_headers, $headers);
$this->addSignatureWithDetachedPayload($jws, $key, $jws->getEncodedPayload(), $protected_headers, $headers);
}

/**
Expand Down
8 changes: 2 additions & 6 deletions src/SignerInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -25,18 +25,14 @@ interface SignerInterface
* @param null|string $detached_payload
* @param array $protected_headers
* @param array $headers
*
* @return \Jose\Object\JWSInterface
*/
public function addSignatureWithDetachedPayload(JWSInterface $jws, JWKInterface $key, $detached_payload, array $protected_headers = [], array $headers = []);
public function addSignatureWithDetachedPayload(JWSInterface &$jws, JWKInterface $key, $detached_payload, array $protected_headers = [], array $headers = []);

/**
* @param \Jose\Object\JWSInterface $jws
* @param \Jose\Object\JWKInterface $key
* @param array $protected_headers
* @param array $headers
*
* @return \Jose\Object\JWSInterface
*/
public function addSignature(JWSInterface $jws, JWKInterface $key, array $protected_headers = [], array $headers = []);
public function addSignature(JWSInterface &$jws, JWKInterface $key, array $protected_headers = [], array $headers = []);
}
Loading