Completed
Push — develop ( b5844e...e46df6 )
by Florent
02:33
created

SignerTest::testCreateFlattenedJWSUsingFactory()   B

Complexity

Conditions 1
Paths 1

Size

Total Lines 25
Code Lines 19

Duplication

Lines 0
Ratio 0 %

Importance

Changes 4
Bugs 1 Features 1
Metric Value
c 4
b 1
f 1
dl 0
loc 25
rs 8.8571
cc 1
eloc 19
nc 1
nop 0
1
<?php
2
3
/*
4
 * The MIT License (MIT)
5
 *
6
 * Copyright (c) 2014-2016 Spomky-Labs
7
 *
8
 * This software may be modified and distributed under the terms
9
 * of the MIT license.  See the LICENSE file for details.
10
 */
11
12
use Jose\Factory\JWSFactory;
13
use Jose\Factory\SignerFactory;
14
use Jose\Factory\VerifierFactory;
15
use Jose\Loader;
16
use Jose\Object\JWK;
17
use Jose\Object\JWKSet;
18
use Jose\Object\JWSInterface;
19
use Jose\Test\TestCase;
20
21
/**
22
 * @group Signer
23
 * @group Functional
24
 */
25
class SignerTest extends TestCase
26
{
27
    /**
28
     * @expectedException \InvalidArgumentException
29
     * @expectedExceptionMessage No payload.
30
     */
31
    public function testNoPayload()
32
    {
33
        $signer = SignerFactory::createSigner([], $this->getLogger());
34
35
        $jws = JWSFactory::createJWSWithDetachedPayload($this->getKey3(), $payload);
36
        $jws = $jws->addSignature($this->getKey1(), []);
37
38
        $signer->sign($jws);
39
    }
40
41
    /**
42
     * @expectedException \InvalidArgumentException
43
     * @expectedExceptionMessage No "alg" parameter set in the header.
44
     */
45
    public function testAlgParameterIsMissing()
46
    {
47
        $signer = SignerFactory::createSigner([], $this->getLogger());
48
49
        $jws = JWSFactory::createJWS($this->getKey3());
50
        $jws = $jws->addSignature($this->getKey1(), []);
51
52
        $signer->sign($jws);
53
    }
54
55
    /**
56
     * @expectedException \InvalidArgumentException
57
     * @expectedExceptionMessage The algorithm "foo" is not supported.
58
     */
59
    public function testAlgParameterIsNotSupported()
60
    {
61
        $signer = SignerFactory::createSigner([], $this->getLogger());
62
63
        $jws = JWSFactory::createJWS($this->getKey3());
64
        $jws = $jws->addSignature(
65
            $this->getKey1(),
66
            ['alg' => 'foo']
67
        );
68
69
        $signer->sign($jws);
70
    }
71
72
    public function testSignAndLoadCompact()
73
    {
74
        $signer = SignerFactory::createSigner(['HS512', 'RS512'], $this->getLogger());
75
76
        $jws = JWSFactory::createJWS($this->getKey3());
77
        $jws = $jws->addSignature(
78
            $this->getKey1(),
79
            ['alg' => 'HS512']
80
        );
81
        $jws = $jws->addSignature(
82
            $this->getKey2(),
83
            ['alg' => 'RS512']
84
        );
85
86
        $signer->sign($jws);
87
88
        $this->assertEquals(2, $jws->countSignatures());
89
90
        $loaded = Loader::load($jws->toJSON());
91
92
        $this->assertInstanceOf(JWSInterface::class, $loaded);
93
        $this->assertTrue(is_array($loaded->getPayload()));
94
        $this->assertEquals('HS512', $loaded->getSignature(0)->getProtectedHeader('alg'));
95
        $this->assertEquals('RS512', $loaded->getSignature(1)->getProtectedHeader('alg'));
96
    }
97
98
    public function testSignMultipleInstructionWithCompactRepresentation()
99
    {
100
        $signer = SignerFactory::createSigner(['HS512', 'RS512'], $this->getLogger());
101
102
        $jws = JWSFactory::createJWS('Live long and Prosper.');
103
        $jws = $jws->addSignature(
104
            $this->getKey1(),
105
            ['alg' => 'HS512']
106
        );
107
        $jws = $jws->addSignature(
108
            $this->getKey2(),
109
            ['alg' => 'RS512']
110
        );
111
112
        $signer->sign($jws);
113
114
        $this->assertEquals(2, $jws->countSignatures());
115
        $this->assertEquals('eyJhbGciOiJIUzUxMiJ9.TGl2ZSBsb25nIGFuZCBQcm9zcGVyLg.TjxvVLKLc1kU5XW1NjZlI6_kQHjeU2orTWBZ7p0KuRzq_9lyPWR04PAUpbYkaLJLsmIJ8Fxi8Gsrc0khPtFxfQ', $jws->toCompactJSON(0));
116
        $this->assertEquals('eyJhbGciOiJSUzUxMiJ9.TGl2ZSBsb25nIGFuZCBQcm9zcGVyLg.cR-npy2oEi275rpeTAKooLRzOhIOFMewpzE38CLx4_CtdkN4Y7EUlca9ryV6yGMH8SswUqosMnmUU8XYg7xkuNAc6mCODJVF2exfb_Mulmr9YolQrLFrFRsMk1rztXMinCMQeCe5ue3Ck4E4aJlIkjf-d0DJktoIhH6d2gZ-iJeLQ32wcBhPcEbj2gr7K_wYKlEXhKFwG59OE-hIi9IHXEKvK-2V5vzZLVC80G4aWYd3D-2eX3LF1K69NP04jGcu1D4l9UV8zTz1gOWe697iZG0JyKhSccUaHZ0TfEa8cT0tm6xTz6tpUGSDdvPQU8JCU8GTOsi9ifxTsI-GlWE3YA', $jws->toCompactJSON(1));
117
    }
118
119
    public function testCreateCompactJWSUsingFactory()
120
    {
121
        $jws0 = JWSFactory::createJWSToCompactJSON('Live long and Prosper.', $this->getKey1(), ['alg' => 'HS512']);
122
        $jws1 = JWSFactory::createJWSToCompactJSON('Live long and Prosper.', $this->getKey2(), ['alg' => 'RS512']);
123
        $jws2 = JWSFactory::createJWSWithDetachedPayloadToCompactJSON('Live long and Prosper.', $this->getKey1(), $encoded_payload_2, ['alg' => 'HS512']);
124
        $jws3 = JWSFactory::createJWSWithDetachedPayloadToCompactJSON('Live long and Prosper.', $this->getKey2(), $encoded_payload_3, ['alg' => 'RS512']);
125
126
        $this->assertEquals('eyJhbGciOiJIUzUxMiJ9.TGl2ZSBsb25nIGFuZCBQcm9zcGVyLg.TjxvVLKLc1kU5XW1NjZlI6_kQHjeU2orTWBZ7p0KuRzq_9lyPWR04PAUpbYkaLJLsmIJ8Fxi8Gsrc0khPtFxfQ', $jws0);
127
        $this->assertEquals('eyJhbGciOiJSUzUxMiJ9.TGl2ZSBsb25nIGFuZCBQcm9zcGVyLg.cR-npy2oEi275rpeTAKooLRzOhIOFMewpzE38CLx4_CtdkN4Y7EUlca9ryV6yGMH8SswUqosMnmUU8XYg7xkuNAc6mCODJVF2exfb_Mulmr9YolQrLFrFRsMk1rztXMinCMQeCe5ue3Ck4E4aJlIkjf-d0DJktoIhH6d2gZ-iJeLQ32wcBhPcEbj2gr7K_wYKlEXhKFwG59OE-hIi9IHXEKvK-2V5vzZLVC80G4aWYd3D-2eX3LF1K69NP04jGcu1D4l9UV8zTz1gOWe697iZG0JyKhSccUaHZ0TfEa8cT0tm6xTz6tpUGSDdvPQU8JCU8GTOsi9ifxTsI-GlWE3YA', $jws1);
128
        $this->assertEquals('eyJhbGciOiJIUzUxMiJ9..TjxvVLKLc1kU5XW1NjZlI6_kQHjeU2orTWBZ7p0KuRzq_9lyPWR04PAUpbYkaLJLsmIJ8Fxi8Gsrc0khPtFxfQ', $jws2);
129
        $this->assertEquals('eyJhbGciOiJSUzUxMiJ9..cR-npy2oEi275rpeTAKooLRzOhIOFMewpzE38CLx4_CtdkN4Y7EUlca9ryV6yGMH8SswUqosMnmUU8XYg7xkuNAc6mCODJVF2exfb_Mulmr9YolQrLFrFRsMk1rztXMinCMQeCe5ue3Ck4E4aJlIkjf-d0DJktoIhH6d2gZ-iJeLQ32wcBhPcEbj2gr7K_wYKlEXhKFwG59OE-hIi9IHXEKvK-2V5vzZLVC80G4aWYd3D-2eX3LF1K69NP04jGcu1D4l9UV8zTz1gOWe697iZG0JyKhSccUaHZ0TfEa8cT0tm6xTz6tpUGSDdvPQU8JCU8GTOsi9ifxTsI-GlWE3YA', $jws3);
130
131
        $this->assertEquals('TGl2ZSBsb25nIGFuZCBQcm9zcGVyLg', $encoded_payload_2);
132
        $this->assertEquals('TGl2ZSBsb25nIGFuZCBQcm9zcGVyLg', $encoded_payload_3);
133
134
        $loaded_0 = Loader::loadAndVerifySignatureUsingKey($jws0, $this->getKey1(), ['HS512']);
135
        $loaded_1 = Loader::loadAndVerifySignatureUsingKey($jws1, $this->getKey2(), ['RS512']);
136
        $loaded_2 = Loader::loadAndVerifySignatureUsingKeyAndDetachedPayload($jws2, $this->getKey1(), ['HS512'], 'TGl2ZSBsb25nIGFuZCBQcm9zcGVyLg');
137
        $loaded_3 = Loader::loadAndVerifySignatureUsingKeyAndDetachedPayload($jws3, $this->getKey2(), ['RS512'], 'TGl2ZSBsb25nIGFuZCBQcm9zcGVyLg');
138
139
        $this->assertInstanceOf(JWSInterface::class, $loaded_0);
140
        $this->assertInstanceOf(JWSInterface::class, $loaded_1);
141
        $this->assertInstanceOf(JWSInterface::class, $loaded_2);
142
        $this->assertInstanceOf(JWSInterface::class, $loaded_3);
143
    }
144
145
    public function testSignMultipleInstructionWithFlattenedRepresentation()
146
    {
147
        $signer = SignerFactory::createSigner(['HS512', 'RS512'], $this->getLogger());
148
149
        $jws = JWSFactory::createJWS('Live long and Prosper.');
150
        $jws = $jws->addSignature(
151
            $this->getKey1(),
152
            ['alg' => 'HS512']
153
        );
154
        $jws = $jws->addSignature(
155
            $this->getKey2(),
156
            ['alg' => 'RS512']
157
        );
158
159
        $signer->sign($jws);
160
161
        $this->assertEquals(2, $jws->countSignatures());
162
        $this->assertEquals('{"payload":"TGl2ZSBsb25nIGFuZCBQcm9zcGVyLg","protected":"eyJhbGciOiJIUzUxMiJ9","signature":"TjxvVLKLc1kU5XW1NjZlI6_kQHjeU2orTWBZ7p0KuRzq_9lyPWR04PAUpbYkaLJLsmIJ8Fxi8Gsrc0khPtFxfQ"}', $jws->toFlattenedJSON(0));
163
        $this->assertEquals('{"payload":"TGl2ZSBsb25nIGFuZCBQcm9zcGVyLg","protected":"eyJhbGciOiJSUzUxMiJ9","signature":"cR-npy2oEi275rpeTAKooLRzOhIOFMewpzE38CLx4_CtdkN4Y7EUlca9ryV6yGMH8SswUqosMnmUU8XYg7xkuNAc6mCODJVF2exfb_Mulmr9YolQrLFrFRsMk1rztXMinCMQeCe5ue3Ck4E4aJlIkjf-d0DJktoIhH6d2gZ-iJeLQ32wcBhPcEbj2gr7K_wYKlEXhKFwG59OE-hIi9IHXEKvK-2V5vzZLVC80G4aWYd3D-2eX3LF1K69NP04jGcu1D4l9UV8zTz1gOWe697iZG0JyKhSccUaHZ0TfEa8cT0tm6xTz6tpUGSDdvPQU8JCU8GTOsi9ifxTsI-GlWE3YA"}', $jws->toFlattenedJSON(1));
164
    }
165
166
    public function testCreateFlattenedJWSUsingFactory()
167
    {
168
        $jws0 = JWSFactory::createJWSToFlattenedJSON('Live long and Prosper.', $this->getKey1(), ['alg' => 'HS512'], ['foo' => 'bar']);
169
        $jws1 = JWSFactory::createJWSToFlattenedJSON('Live long and Prosper.', $this->getKey2(), ['alg' => 'RS512'], ['plic' => 'ploc']);
170
        $jws2 = JWSFactory::createJWSWithDetachedPayloadToFlattenedJSON('Live long and Prosper.', $this->getKey1(), $encoded_payload_2, ['alg' => 'HS512'], ['foo' => 'bar']);
171
        $jws3 = JWSFactory::createJWSWithDetachedPayloadToFlattenedJSON('Live long and Prosper.', $this->getKey2(), $encoded_payload_3, ['alg' => 'RS512'], ['plic' => 'ploc']);
172
173
        $this->assertEquals('{"payload":"TGl2ZSBsb25nIGFuZCBQcm9zcGVyLg","protected":"eyJhbGciOiJIUzUxMiJ9","header":{"foo":"bar"},"signature":"TjxvVLKLc1kU5XW1NjZlI6_kQHjeU2orTWBZ7p0KuRzq_9lyPWR04PAUpbYkaLJLsmIJ8Fxi8Gsrc0khPtFxfQ"}', $jws0);
174
        $this->assertEquals('{"payload":"TGl2ZSBsb25nIGFuZCBQcm9zcGVyLg","protected":"eyJhbGciOiJSUzUxMiJ9","header":{"plic":"ploc"},"signature":"cR-npy2oEi275rpeTAKooLRzOhIOFMewpzE38CLx4_CtdkN4Y7EUlca9ryV6yGMH8SswUqosMnmUU8XYg7xkuNAc6mCODJVF2exfb_Mulmr9YolQrLFrFRsMk1rztXMinCMQeCe5ue3Ck4E4aJlIkjf-d0DJktoIhH6d2gZ-iJeLQ32wcBhPcEbj2gr7K_wYKlEXhKFwG59OE-hIi9IHXEKvK-2V5vzZLVC80G4aWYd3D-2eX3LF1K69NP04jGcu1D4l9UV8zTz1gOWe697iZG0JyKhSccUaHZ0TfEa8cT0tm6xTz6tpUGSDdvPQU8JCU8GTOsi9ifxTsI-GlWE3YA"}', $jws1);
175
        $this->assertEquals('{"protected":"eyJhbGciOiJIUzUxMiJ9","header":{"foo":"bar"},"signature":"TjxvVLKLc1kU5XW1NjZlI6_kQHjeU2orTWBZ7p0KuRzq_9lyPWR04PAUpbYkaLJLsmIJ8Fxi8Gsrc0khPtFxfQ"}', $jws2);
176
        $this->assertEquals('{"protected":"eyJhbGciOiJSUzUxMiJ9","header":{"plic":"ploc"},"signature":"cR-npy2oEi275rpeTAKooLRzOhIOFMewpzE38CLx4_CtdkN4Y7EUlca9ryV6yGMH8SswUqosMnmUU8XYg7xkuNAc6mCODJVF2exfb_Mulmr9YolQrLFrFRsMk1rztXMinCMQeCe5ue3Ck4E4aJlIkjf-d0DJktoIhH6d2gZ-iJeLQ32wcBhPcEbj2gr7K_wYKlEXhKFwG59OE-hIi9IHXEKvK-2V5vzZLVC80G4aWYd3D-2eX3LF1K69NP04jGcu1D4l9UV8zTz1gOWe697iZG0JyKhSccUaHZ0TfEa8cT0tm6xTz6tpUGSDdvPQU8JCU8GTOsi9ifxTsI-GlWE3YA"}', $jws3);
177
178
        $this->assertEquals('TGl2ZSBsb25nIGFuZCBQcm9zcGVyLg', $encoded_payload_2);
179
        $this->assertEquals('TGl2ZSBsb25nIGFuZCBQcm9zcGVyLg', $encoded_payload_3);
180
181
        $loaded_0 = Loader::loadAndVerifySignatureUsingKey($jws0, $this->getKey1(), ['HS512']);
182
        $loaded_1 = Loader::loadAndVerifySignatureUsingKey($jws1, $this->getKey2(), ['RS512']);
183
        $loaded_2 = Loader::loadAndVerifySignatureUsingKeyAndDetachedPayload($jws2, $this->getKey1(), ['HS512'], 'TGl2ZSBsb25nIGFuZCBQcm9zcGVyLg');
184
        $loaded_3 = Loader::loadAndVerifySignatureUsingKeyAndDetachedPayload($jws3, $this->getKey2(), ['RS512'], 'TGl2ZSBsb25nIGFuZCBQcm9zcGVyLg');
185
186
        $this->assertInstanceOf(JWSInterface::class, $loaded_0);
187
        $this->assertInstanceOf(JWSInterface::class, $loaded_1);
188
        $this->assertInstanceOf(JWSInterface::class, $loaded_2);
189
        $this->assertInstanceOf(JWSInterface::class, $loaded_3);
190
    }
191
192
    /**
193
     * @expectedException \InvalidArgumentException
194
     * @expectedExceptionMessage The algorithm "RS512" is not allowed with this key.
195
     */
196
    public function testAlgorithmNotAllowedForTheKey()
197
    {
198
        $signer = SignerFactory::createSigner([], $this->getLogger());
199
200
        $jws = JWSFactory::createJWS('Live long and Prosper.');
201
        $jws = $jws->addSignature(
202
            $this->getKey5(),
203
            ['alg' => 'RS512']
204
        );
205
206
        $signer->sign($jws);
207
    }
208
209
    /**
210
     * @expectedException \InvalidArgumentException
211
     * @expectedExceptionMessage Key cannot be used to sign
212
     */
213
    public function testOperationNotAllowedForTheKey()
214
    {
215
        $signer = SignerFactory::createSigner(['PS512'], $this->getLogger());
216
217
        $jws = JWSFactory::createJWS('Live long and Prosper.');
218
        $jws = $jws->addSignature(
219
            $this->getKey4(),
220
            ['alg' => 'PS512']
221
        );
222
223
        $signer->sign($jws);
224
    }
225
226
    public function testSignAndLoadFlattened()
227
    {
228
        $signer = SignerFactory::createSigner(['HS512'], $this->getLogger());
229
230
        $jws = JWSFactory::createJWS(['baz', 'ban']);
231
        $jws = $jws->addSignature(
232
            $this->getKey1(),
233
            ['alg' => 'HS512'],
234
            ['foo' => 'bar']
235
        );
236
237
        $signer->sign($jws);
238
239
        $loaded = Loader::load($jws->toJSON());
240
241
        $this->assertEquals(1, $loaded->countSignatures());
242
        $this->assertInstanceOf(JWSInterface::class, $loaded);
243
        $this->assertTrue(is_array($loaded->getPayload()));
244
        $this->assertEquals('HS512', $loaded->getSignature(0)->getProtectedHeader('alg'));
245
    }
246
247
    public function testSignAndLoad()
248
    {
249
        $signer = SignerFactory::createSigner(['HS512', 'RS512'], $this->getLogger());
250
        $verifier = VerifierFactory::createVerifier(['HS512', 'RS512'], $this->getLogger());
251
252
        $jws = JWSFactory::createJWS('Live long and Prosper.');
253
        $jws = $jws->addSignature(
254
            $this->getKey1(),
255
            ['alg' => 'HS512'],
256
            ['foo' => 'bar']
257
        );
258
        $jws = $jws->addSignature(
259
            $this->getKey2(),
260
            ['alg' => 'RS512']
261
        );
262
263
        $signer->sign($jws);
264
265
        $loaded = Loader::load($jws->toJSON());
266
267
        $this->assertEquals(2, $loaded->countSignatures());
268
        $this->assertInstanceOf(JWSInterface::class, $loaded);
269
        $this->assertEquals('Live long and Prosper.', $loaded->getPayload());
270
        $verifier->verifyWithKeySet($loaded, $this->getSymmetricKeySet());
271
        $verifier->verifyWithKeySet($loaded, $this->getPublicKeySet());
272
273
        $this->assertEquals('HS512', $loaded->getSignature(0)->getProtectedHeader('alg'));
274
        $this->assertEquals('RS512', $loaded->getSignature(1)->getProtectedHeader('alg'));
275
    }
276
277
    /**
278
     * @expectedException \InvalidArgumentException
279
     * @expectedExceptionMessage  Unable to verify the JWS.
280
     */
281
    public function testSignAndLoadWithWrongKeys()
282
    {
283
        $signer = SignerFactory::createSigner(['RS512'], $this->getLogger());
284
        $verifier = VerifierFactory::createVerifier(['RS512'], $this->getLogger());
285
286
        $jws = JWSFactory::createJWS('Live long and Prosper.');
287
        $jws = $jws->addSignature(
288
            $this->getKey2(),
289
            ['alg' => 'RS512']
290
        );
291
292
        $signer->sign($jws);
293
294
        $loaded = Loader::load($jws->toJSON());
295
296
        $this->assertEquals(1, $loaded->countSignatures());
297
        $this->assertInstanceOf(JWSInterface::class, $loaded);
298
        $this->assertEquals('Live long and Prosper.', $loaded->getPayload());
299
300
        $verifier->verifyWithKeySet($loaded, $this->getSymmetricKeySet());
301
    }
302
303
    /**
304
     * @expectedException \InvalidArgumentException
305
     * @expectedExceptionMessage The algorithm "RS512" is not supported or does not implement SignatureInterface.
306
     */
307
    public function testSignAndLoadWithUnsupportedAlgorithm()
308
    {
309
        $signer = SignerFactory::createSigner(['RS512'], $this->getLogger());
310
        $verifier = VerifierFactory::createVerifier(['HS512'], $this->getLogger());
311
312
        $jws = JWSFactory::createJWS('Live long and Prosper.');
313
        $jws = $jws->addSignature(
314
            $this->getKey2(),
315
            ['alg' => 'RS512']
316
        );
317
318
        $signer->sign($jws);
319
320
        $loaded = Loader::load($jws->toJSON());
321
322
        $this->assertEquals(1, $loaded->countSignatures());
323
        $this->assertInstanceOf(JWSInterface::class, $loaded);
324
        $this->assertEquals('Live long and Prosper.', $loaded->getPayload());
325
326
        $verifier->verifyWithKeySet($loaded, $this->getSymmetricKeySet());
327
    }
328
329
    /**
330
     * @expectedException \InvalidArgumentException
331
     * @expectedExceptionMessage The JWS does not contain any signature.
332
     */
333
    public function testSignAndLoadWithJWSWithoutSignatures()
334
    {
335
        $verifier = VerifierFactory::createVerifier(['RS512'], $this->getLogger());
336
        $payload = "It\xe2\x80\x99s a dangerous business, Frodo, going out your door. You step onto the road, and if you don't keep your feet, there\xe2\x80\x99s no knowing where you might be swept off to.";
337
        $jws = '{"payload":"SXTigJlzIGEgZGFuZ2Vyb3VzIGJ1c2luZXNzLCBGcm9kbywgZ29pbmcgb3V0IHlvdXIgZG9vci4gWW91IHN0ZXAgb250byB0aGUgcm9hZCwgYW5kIGlmIHlvdSBkb24ndCBrZWVwIHlvdXIgZmVldCwgdGhlcmXigJlzIG5vIGtub3dpbmcgd2hlcmUgeW91IG1pZ2h0IGJlIHN3ZXB0IG9mZiB0by4","signatures":[]}';
338
339
        $loaded = Loader::load($jws);
340
341
        $this->assertEquals(0, $loaded->countSignatures());
342
        $this->assertInstanceOf(JWSInterface::class, $loaded);
343
        $this->assertEquals($payload, $loaded->getPayload());
344
345
        $verifier->verifyWithKeySet($loaded, $this->getSymmetricKeySet());
346
    }
347
348
    /**
349
     * @expectedException \InvalidArgumentException
350
     * @expectedExceptionMessage No "alg" parameter set in the header.
351
     */
352
    public function testSignAndLoadWithoutAlgParameterInTheHeader()
353
    {
354
        $verifier = VerifierFactory::createVerifier(['RS512'], $this->getLogger());
355
        $payload = "It\xe2\x80\x99s a dangerous business, Frodo, going out your door. You step onto the road, and if you don't keep your feet, there\xe2\x80\x99s no knowing where you might be swept off to.";
356
        $jws = 'eyJraWQiOiJiaWxiby5iYWdnaW5zQGhvYmJpdG9uLmV4YW1wbGUifQ.SXTigJlzIGEgZGFuZ2Vyb3VzIGJ1c2luZXNzLCBGcm9kbywgZ29pbmcgb3V0IHlvdXIgZG9vci4gWW91IHN0ZXAgb250byB0aGUgcm9hZCwgYW5kIGlmIHlvdSBkb24ndCBrZWVwIHlvdXIgZmVldCwgdGhlcmXigJlzIG5vIGtub3dpbmcgd2hlcmUgeW91IG1pZ2h0IGJlIHN3ZXB0IG9mZiB0by4.MRjdkly7_-oTPTS3AXP41iQIGKa80A0ZmTuV5MEaHoxnW2e5CZ5NlKtainoFmKZopdHM1O2U4mwzJdQx996ivp83xuglII7PNDi84wnB-BDkoBwA78185hX-Es4JIwmDLJK3lfWRa-XtL0RnltuYv746iYTh_qHRD68BNt1uSNCrUCTJDt5aAE6x8wW1Kt9eRo4QPocSadnHXFxnt8Is9UzpERV0ePPQdLuW3IS_de3xyIrDaLGdjluPxUAhb6L2aXic1U12podGU0KLUQSE_oI-ZnmKJ3F4uOZDnd6QZWJushZ41Axf_fcIe8u9ipH84ogoree7vjbU5y18kDquDg';
357
358
        $loaded = Loader::load($jws);
359
360
        $this->assertEquals(1, $loaded->countSignatures());
361
        $this->assertInstanceOf(JWSInterface::class, $loaded);
362
        $this->assertEquals($payload, $loaded->getPayload());
363
364
        $verifier->verifyWithKeySet($loaded, $this->getSymmetricKeySet());
365
    }
366
367
    public function testSignAndLoadJWKSet()
368
    {
369
        $signer = SignerFactory::createSigner(['HS512', 'RS512'], $this->getLogger());
370
        $verifier = VerifierFactory::createVerifier(['HS512', 'RS512']);
371
372
        $jws = JWSFactory::createJWS($this->getKeyset());
373
        $jws = $jws->addSignature(
374
            $this->getKey1(),
375
            ['alg' => 'HS512'],
376
            ['foo' => 'bar']
377
        );
378
        $jws = $jws->addSignature(
379
            $this->getKey2(),
380
            ['alg' => 'RS512']
381
        );
382
383
        $signer->sign($jws);
384
385
        $loaded = Loader::load($jws->toJSON());
386
        $this->assertEquals(2, $loaded->countSignatures());
387
        $this->assertInstanceOf(JWSInterface::class, $loaded);
388
        $this->assertEquals($this->getKeyset(), new JWKSet($loaded->getPayload()));
389
        $verifier->verifyWithKeySet($loaded, $this->getSymmetricKeySet());
390
        $verifier->verifyWithKeySet($loaded, $this->getPublicKeySet());
391
392
        $this->assertEquals('HS512', $loaded->getSignature(0)->getProtectedHeader('alg'));
393
        $this->assertEquals('RS512', $loaded->getSignature(1)->getProtectedHeader('alg'));
394
    }
395
396
    /**
397
     * @expectedException \InvalidArgumentException
398
     * @expectedExceptionMessage There is no key in the key set.
399
     */
400
    public function testKeySetIsEmpty()
401
    {
402
        $signer = SignerFactory::createSigner(['HS512', 'RS512'], $this->getLogger());
403
        $verifier = VerifierFactory::createVerifier(['HS512', 'RS512']);
404
405
        $jws = JWSFactory::createJWS($this->getKeyset());
406
        $jws = $jws->addSignature(
407
            $this->getKey1(),
408
            ['alg' => 'HS512'],
409
            ['foo' => 'bar']
410
        );
411
        $jws = $jws->addSignature(
412
            $this->getKey2(),
413
            ['alg' => 'RS512']
414
        );
415
416
        $signer->sign($jws);
417
418
        $loaded = Loader::load($jws->toJSON());
419
        $this->assertEquals(2, $loaded->countSignatures());
420
        $this->assertInstanceOf(JWSInterface::class, $loaded);
421
        $this->assertEquals($this->getKeyset(), new JWKSet($loaded->getPayload()));
422
        $verifier->verifyWithKeySet($loaded, new JWKSet());
423
        $verifier->verifyWithKey($loaded, new JWK(['kty' => 'EC']));
424
    }
425
426
    /**
427
     * @return \Jose\Object\JWKInterface
428
     */
429
    protected function getKey1()
430
    {
431
        $key = new JWK([
432
            'kty' => 'oct',
433
            'k'   => 'AyM1SysPpbyDfgZld3umj1qzKObwVMkoqQ-EstJQLr_T-1qS0gZH75aKtMN3Yj0iPS4hcgUuTwjAzZr1Z9CAow',
434
        ]);
435
436
        return $key;
437
    }
438
439
    /**
440
     * @return \Jose\Object\JWKInterface
441
     */
442
    protected function getKey2()
443
    {
444
        $key = new JWK([
445
            'kty'     => 'RSA',
446
            'use'     => 'sig',
447
            'key_ops' => ['sign'],
448
            'n'       => 'ofgWCuLjybRlzo0tZWJjNiuSfb4p4fAkd_wWJcyQoTbji9k0l8W26mPddxHmfHQp-Vaw-4qPCJrcS2mJPMEzP1Pt0Bm4d4QlL-yRT-SFd2lZS-pCgNMsD1W_YpRPEwOWvG6b32690r2jZ47soMZo9wGzjb_7OMg0LOL-bSf63kpaSHSXndS5z5rexMdbBYUsLA9e-KXBdQOS-UTo7WTBEMa2R2CapHg665xsmtdVMTBQY4uDZlxvb3qCo5ZwKh9kG4LT6_I5IhlJH7aGhyxXFvUK-DWNmoudF8NAco9_h9iaGNj8q2ethFkMLs91kzk2PAcDTW9gb54h4FRWyuXpoQ',
449
            'e'       => 'AQAB',
450
            'd'       => 'Eq5xpGnNCivDflJsRQBXHx1hdR1k6Ulwe2JZD50LpXyWPEAeP88vLNO97IjlA7_GQ5sLKMgvfTeXZx9SE-7YwVol2NXOoAJe46sui395IW_GO-pWJ1O0BkTGoVEn2bKVRUCgu-GjBVaYLU6f3l9kJfFNS3E0QbVdxzubSu3Mkqzjkn439X0M_V51gfpRLI9JYanrC4D4qAdGcopV_0ZHHzQlBjudU2QvXt4ehNYTCBr6XCLQUShb1juUO1ZdiYoFaFQT5Tw8bGUl_x_jTj3ccPDVZFD9pIuhLhBOneufuBiB4cS98l2SR_RQyGWSeWjnczT0QU91p1DhOVRuOopznQ',
451
            'p'       => '4BzEEOtIpmVdVEZNCqS7baC4crd0pqnRH_5IB3jw3bcxGn6QLvnEtfdUdiYrqBdss1l58BQ3KhooKeQTa9AB0Hw_Py5PJdTJNPY8cQn7ouZ2KKDcmnPGBY5t7yLc1QlQ5xHdwW1VhvKn-nXqhJTBgIPgtldC-KDV5z-y2XDwGUc',
452
            'q'       => 'uQPEfgmVtjL0Uyyx88GZFF1fOunH3-7cepKmtH4pxhtCoHqpWmT8YAmZxaewHgHAjLYsp1ZSe7zFYHj7C6ul7TjeLQeZD_YwD66t62wDmpe_HlB-TnBA-njbglfIsRLtXlnDzQkv5dTltRJ11BKBBypeeF6689rjcJIDEz9RWdc',
453
            'dp'      => 'BwKfV3Akq5_MFZDFZCnW-wzl-CCo83WoZvnLQwCTeDv8uzluRSnm71I3QCLdhrqE2e9YkxvuxdBfpT_PI7Yz-FOKnu1R6HsJeDCjn12Sk3vmAktV2zb34MCdy7cpdTh_YVr7tss2u6vneTwrA86rZtu5Mbr1C1XsmvkxHQAdYo0',
454
            'dq'      => 'h_96-mK1R_7glhsum81dZxjTnYynPbZpHziZjeeHcXYsXaaMwkOlODsWa7I9xXDoRwbKgB719rrmI2oKr6N3Do9U0ajaHF-NKJnwgjMd2w9cjz3_-kyNlxAr2v4IKhGNpmM5iIgOS1VZnOZ68m6_pbLBSp3nssTdlqvd0tIiTHU',
455
            'qi'      => 'IYd7DHOhrWvxkwPQsRM2tOgrjbcrfvtQJipd-DlcxyVuuM9sQLdgjVk2oy26F0EmpScGLq2MowX7fhd_QJQ3ydy5cY7YIBi87w93IKLEdfnbJtoOPLUW0ITrJReOgo1cq9SbsxYawBgfp_gh6A5603k2-ZQwVK0JKSHuLFkuQ3U',
456
        ]);
457
458
        return $key;
459
    }
460
461
    /**
462
     * @return \Jose\Object\JWKInterface
463
     */
464
    protected function getKey3()
465
    {
466
        $key = new JWK([
467
            'kty'     => 'EC',
468
            'crv'     => 'P-256',
469
            'use'     => 'sig',
470
            'key_ops' => ['sign'],
471
            'x'       => 'f83OJ3D2xF1Bg8vub9tLe1gHMzV76e8Tus9uPHvRVEU',
472
            'y'       => 'x_FEzRu9m36HLN_tue659LNpXW6pCyStikYjKIWI5a0',
473
            'd'       => 'jpsQnnGQmL-YBIffH1136cspYG6-0iY7X1fCE9-E9LI',
474
        ]);
475
476
        return $key;
477
    }
478
479
    /**
480
     * @return \Jose\Object\JWKInterface
481
     */
482
    protected function getKey4()
483
    {
484
        $key = new JWK([
485
            'kty'     => 'RSA',
486
            'alg'     => 'PS512',
487
            'key_ops' => ['encrypt', 'decrypt'],
488
            'n'       => 'ofgWCuLjybRlzo0tZWJjNiuSfb4p4fAkd_wWJcyQoTbji9k0l8W26mPddxHmfHQp-Vaw-4qPCJrcS2mJPMEzP1Pt0Bm4d4QlL-yRT-SFd2lZS-pCgNMsD1W_YpRPEwOWvG6b32690r2jZ47soMZo9wGzjb_7OMg0LOL-bSf63kpaSHSXndS5z5rexMdbBYUsLA9e-KXBdQOS-UTo7WTBEMa2R2CapHg665xsmtdVMTBQY4uDZlxvb3qCo5ZwKh9kG4LT6_I5IhlJH7aGhyxXFvUK-DWNmoudF8NAco9_h9iaGNj8q2ethFkMLs91kzk2PAcDTW9gb54h4FRWyuXpoQ',
489
            'e'       => 'AQAB',
490
            'd'       => 'Eq5xpGnNCivDflJsRQBXHx1hdR1k6Ulwe2JZD50LpXyWPEAeP88vLNO97IjlA7_GQ5sLKMgvfTeXZx9SE-7YwVol2NXOoAJe46sui395IW_GO-pWJ1O0BkTGoVEn2bKVRUCgu-GjBVaYLU6f3l9kJfFNS3E0QbVdxzubSu3Mkqzjkn439X0M_V51gfpRLI9JYanrC4D4qAdGcopV_0ZHHzQlBjudU2QvXt4ehNYTCBr6XCLQUShb1juUO1ZdiYoFaFQT5Tw8bGUl_x_jTj3ccPDVZFD9pIuhLhBOneufuBiB4cS98l2SR_RQyGWSeWjnczT0QU91p1DhOVRuOopznQ',
491
            'p'       => '4BzEEOtIpmVdVEZNCqS7baC4crd0pqnRH_5IB3jw3bcxGn6QLvnEtfdUdiYrqBdss1l58BQ3KhooKeQTa9AB0Hw_Py5PJdTJNPY8cQn7ouZ2KKDcmnPGBY5t7yLc1QlQ5xHdwW1VhvKn-nXqhJTBgIPgtldC-KDV5z-y2XDwGUc',
492
            'q'       => 'uQPEfgmVtjL0Uyyx88GZFF1fOunH3-7cepKmtH4pxhtCoHqpWmT8YAmZxaewHgHAjLYsp1ZSe7zFYHj7C6ul7TjeLQeZD_YwD66t62wDmpe_HlB-TnBA-njbglfIsRLtXlnDzQkv5dTltRJ11BKBBypeeF6689rjcJIDEz9RWdc',
493
            'dp'      => 'BwKfV3Akq5_MFZDFZCnW-wzl-CCo83WoZvnLQwCTeDv8uzluRSnm71I3QCLdhrqE2e9YkxvuxdBfpT_PI7Yz-FOKnu1R6HsJeDCjn12Sk3vmAktV2zb34MCdy7cpdTh_YVr7tss2u6vneTwrA86rZtu5Mbr1C1XsmvkxHQAdYo0',
494
            'dq'      => 'h_96-mK1R_7glhsum81dZxjTnYynPbZpHziZjeeHcXYsXaaMwkOlODsWa7I9xXDoRwbKgB719rrmI2oKr6N3Do9U0ajaHF-NKJnwgjMd2w9cjz3_-kyNlxAr2v4IKhGNpmM5iIgOS1VZnOZ68m6_pbLBSp3nssTdlqvd0tIiTHU',
495
            'qi'      => 'IYd7DHOhrWvxkwPQsRM2tOgrjbcrfvtQJipd-DlcxyVuuM9sQLdgjVk2oy26F0EmpScGLq2MowX7fhd_QJQ3ydy5cY7YIBi87w93IKLEdfnbJtoOPLUW0ITrJReOgo1cq9SbsxYawBgfp_gh6A5603k2-ZQwVK0JKSHuLFkuQ3U',
496
        ]);
497
498
        return $key;
499
    }
500
501
    /**
502
     * @return \Jose\Object\JWKInterface
503
     */
504
    protected function getKey5()
505
    {
506
        $key = new JWK([
507
            'kty'     => 'RSA',
508
            'alg'     => 'PS512',
509
            'use'     => 'sig',
510
            'n'       => 'ofgWCuLjybRlzo0tZWJjNiuSfb4p4fAkd_wWJcyQoTbji9k0l8W26mPddxHmfHQp-Vaw-4qPCJrcS2mJPMEzP1Pt0Bm4d4QlL-yRT-SFd2lZS-pCgNMsD1W_YpRPEwOWvG6b32690r2jZ47soMZo9wGzjb_7OMg0LOL-bSf63kpaSHSXndS5z5rexMdbBYUsLA9e-KXBdQOS-UTo7WTBEMa2R2CapHg665xsmtdVMTBQY4uDZlxvb3qCo5ZwKh9kG4LT6_I5IhlJH7aGhyxXFvUK-DWNmoudF8NAco9_h9iaGNj8q2ethFkMLs91kzk2PAcDTW9gb54h4FRWyuXpoQ',
511
            'e'       => 'AQAB',
512
            'd'       => 'Eq5xpGnNCivDflJsRQBXHx1hdR1k6Ulwe2JZD50LpXyWPEAeP88vLNO97IjlA7_GQ5sLKMgvfTeXZx9SE-7YwVol2NXOoAJe46sui395IW_GO-pWJ1O0BkTGoVEn2bKVRUCgu-GjBVaYLU6f3l9kJfFNS3E0QbVdxzubSu3Mkqzjkn439X0M_V51gfpRLI9JYanrC4D4qAdGcopV_0ZHHzQlBjudU2QvXt4ehNYTCBr6XCLQUShb1juUO1ZdiYoFaFQT5Tw8bGUl_x_jTj3ccPDVZFD9pIuhLhBOneufuBiB4cS98l2SR_RQyGWSeWjnczT0QU91p1DhOVRuOopznQ',
513
            'p'       => '4BzEEOtIpmVdVEZNCqS7baC4crd0pqnRH_5IB3jw3bcxGn6QLvnEtfdUdiYrqBdss1l58BQ3KhooKeQTa9AB0Hw_Py5PJdTJNPY8cQn7ouZ2KKDcmnPGBY5t7yLc1QlQ5xHdwW1VhvKn-nXqhJTBgIPgtldC-KDV5z-y2XDwGUc',
514
            'q'       => 'uQPEfgmVtjL0Uyyx88GZFF1fOunH3-7cepKmtH4pxhtCoHqpWmT8YAmZxaewHgHAjLYsp1ZSe7zFYHj7C6ul7TjeLQeZD_YwD66t62wDmpe_HlB-TnBA-njbglfIsRLtXlnDzQkv5dTltRJ11BKBBypeeF6689rjcJIDEz9RWdc',
515
            'dp'      => 'BwKfV3Akq5_MFZDFZCnW-wzl-CCo83WoZvnLQwCTeDv8uzluRSnm71I3QCLdhrqE2e9YkxvuxdBfpT_PI7Yz-FOKnu1R6HsJeDCjn12Sk3vmAktV2zb34MCdy7cpdTh_YVr7tss2u6vneTwrA86rZtu5Mbr1C1XsmvkxHQAdYo0',
516
            'dq'      => 'h_96-mK1R_7glhsum81dZxjTnYynPbZpHziZjeeHcXYsXaaMwkOlODsWa7I9xXDoRwbKgB719rrmI2oKr6N3Do9U0ajaHF-NKJnwgjMd2w9cjz3_-kyNlxAr2v4IKhGNpmM5iIgOS1VZnOZ68m6_pbLBSp3nssTdlqvd0tIiTHU',
517
            'qi'      => 'IYd7DHOhrWvxkwPQsRM2tOgrjbcrfvtQJipd-DlcxyVuuM9sQLdgjVk2oy26F0EmpScGLq2MowX7fhd_QJQ3ydy5cY7YIBi87w93IKLEdfnbJtoOPLUW0ITrJReOgo1cq9SbsxYawBgfp_gh6A5603k2-ZQwVK0JKSHuLFkuQ3U',
518
        ]);
519
520
        return $key;
521
    }
522
523
    /**
524
     * @return \Jose\Object\JWKSetInterface
525
     */
526
    protected function getKeyset()
527
    {
528
        $keyset = new JWKSet();
529
        $keyset = $keyset->addKey($this->getKey1());
530
        $keyset = $keyset->addKey($this->getKey2());
531
532
        return $keyset;
533
    }
534
}
535