Failed Conditions
Push — v7 ( 5d1eb6...6055df )
by Florent
02:59
created

JWE::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 12
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 12
rs 9.4285
c 0
b 0
f 0
cc 1
eloc 10
nc 1
nop 9

How to fix   Many Parameters   

Many Parameters

Methods with many parameters are not only hard to understand, but their parameters also often become inconsistent when you need more, or different data.

There are several approaches to avoid long parameter lists:

1
<?php
2
3
declare(strict_types=1);
4
5
/*
6
 * The MIT License (MIT)
7
 *
8
 * Copyright (c) 2014-2017 Spomky-Labs
9
 *
10
 * This software may be modified and distributed under the terms
11
 * of the MIT license.  See the LICENSE file for details.
12
 */
13
14
namespace Jose\Component\Encryption;
15
16
use Assert\Assertion;
17
use Base64Url\Base64Url;
18
use Jose\Component\Core\JWK;
19
use Jose\Component\Core\JWTInterface;
20
21
/**
22
 * Class JWE.
23
 */
24
final class JWE implements JWTInterface
25
{
26
    /**
27
     * @var Recipient[]
28
     */
29
    private $recipients = [];
30
31
    /**
32
     * @var string|null
33
     */
34
    private $ciphertext = null;
35
36
    /**
37
     * @var string|null
38
     */
39
    private $iv = null;
40
41
    /**
42
     * @var string|null
43
     */
44
    private $aad = null;
45
46
    /**
47
     * @var string|null
48
     */
49
    private $tag = null;
50
51
    /**
52
     * @var array
53
     */
54
    private $shared_headers = [];
55
56
    /**
57
     * @var array
58
     */
59
    private $shared_protected_headers = [];
60
61
    /**
62
     * @var string|null
63
     */
64
    private $encoded_shared_protected_headers = null;
65
66
    /**
67
     * @var mixed|null
68
     */
69
    private $payload = null;
70
71
    /**
72
     * JWE constructor.
73
     * @param null|string $ciphertext
74
     * @param null|string $iv
75
     * @param null|string $aad
76
     * @param null|string $tag
77
     * @param array $shared_headers
78
     * @param array $shared_protected_headers
79
     * @param null|string $encoded_shared_protected_headers
80
     * @param mixed|null $payload
81
     * @param array $recipients
82
     */
83
    private function __construct(?string $ciphertext = null, ?string $iv = null, ?string $aad = null, ?string $tag = null, array $shared_headers = [], array $shared_protected_headers = [], ?string $encoded_shared_protected_headers = null,  $payload = null, array $recipients = [])
84
    {
85
        $this->ciphertext = $ciphertext;
86
        $this->iv = $iv;
87
        $this->aad = $aad;
88
        $this->tag = $tag;
89
        $this->shared_headers = $shared_headers;
90
        $this->shared_protected_headers = $shared_protected_headers;
91
        $this->encoded_shared_protected_headers = $encoded_shared_protected_headers;
92
        $this->payload = $payload;
93
        $this->recipients = $recipients;
94
    }
95
96
    /**
97
     * @return JWE
98
     */
99
    public static function createEmpty(): JWE
100
    {
101
        return new self();
102
    }
103
104
    /**
105
     * @param $payload
106
     * @param array $shared_protected_headers
107
     * @param null|string $aad
108
     * @param array $shared_headers
109
     *
110
     * @return JWE
111
     */
112
    public static function create($payload, array $shared_protected_headers = [], array $shared_headers = [], ?string $aad = null): JWE
113
    {
114
        return new self(null, null, $aad, null, $shared_headers, $shared_protected_headers, null, $payload);
115
    }
116
117
    /**
118
     * @param null|string $ciphertext
119
     * @param null|string $iv
120
     * @param null|string $aad
121
     * @param null|string $tag
122
     * @param array $shared_headers
123
     * @param array $shared_protected_headers
124
     * @param null|string $encoded_shared_protected_headers
125
     * @param array $recipients
126
     *
127
     * @return JWE
128
     */
129
    public static function createFromLoadedData(?string $ciphertext = null, ?string $iv = null, ?string $aad = null, ?string $tag = null, array $shared_headers = [], array $shared_protected_headers = [], ?string $encoded_shared_protected_headers = null,  array $recipients = []): JWE
130
    {
131
        return new self($ciphertext, $iv, $aad, $tag, $shared_headers, $shared_protected_headers, $encoded_shared_protected_headers, null, $recipients);
132
    }
133
134
    /**
135
     * {@inheritdoc}
136
     */
137
    public function getPayload()
138
    {
139
        return $this->payload;
140
    }
141
142
    /**
143
     * @param mixed $payload
144
     *
145
     * @return JWE
146
     */
147
    public function withPayload($payload): JWE
148
    {
149
        $jwt = clone $this;
150
        $jwt->payload = $payload;
151
152
        return $jwt;
153
    }
154
155
    /**
156
     * {@inheritdoc}
157
     */
158
    public function getClaim(string $key)
159
    {
160
        if ($this->hasClaim($key)) {
161
            return $this->payload[$key];
162
        }
163
        throw new \InvalidArgumentException(sprintf('The payload does not contain claim "%s".', $key));
164
    }
165
166
    /**
167
     * {@inheritdoc}
168
     */
169
    public function getClaims(): array
170
    {
171
        if (!$this->hasClaims()) {
172
            throw new \InvalidArgumentException('The payload does not contain claims.');
173
        }
174
175
        return $this->payload;
176
    }
177
178
    /**
179
     * {@inheritdoc}
180
     */
181
    public function hasClaim(string $key): bool
182
    {
183
        return $this->hasClaims() && array_key_exists($key, $this->payload);
184
    }
185
186
    /**
187
     * {@inheritdoc}
188
     */
189
    public function hasClaims(): bool
190
    {
191
        return is_array($this->payload);
192
    }
193
194
    /**
195
     * Returns the number of recipients associated with the JWS.
196
     *
197
     * @return int
198
     */
199
    public function countRecipients(): int
200
    {
201
        return count($this->recipients);
202
    }
203
204
    /**
205
     * @return bool
206
     */
207
    public function isEncrypted(): bool
208
    {
209
        return null !== $this->getCiphertext();
210
    }
211
212
    /**
213
     * @param JWK   $recipient_key
214
     * @param array $recipient_headers
215
     *
216
     * @return JWE
217
     */
218
    public function addRecipientInformation(JWK $recipient_key, array $recipient_headers = []): JWE
219
    {
220
        Assertion::true(null === $this->getCiphertext(), 'The JWE is encrypted. No additional recipient allowed.');
221
        $jwe = clone $this;
222
        $jwe->recipients[] = Recipient::createRecipient($recipient_key, $recipient_headers);
223
224
        return $jwe;
225
    }
226
227
    /**
228
     * @param string|null $encrypted_key
229
     * @param array       $recipient_headers
230
     *
231
     * @return JWE
232
     */
233
    public function addRecipientWithEncryptedKey(?string $encrypted_key, array $recipient_headers): JWE
234
    {
235
        $jwe = clone $this;
236
        $jwe->recipients[] = Recipient::createRecipientFromLoadedJWE($recipient_headers, $encrypted_key);
237
238
        return $jwe;
239
    }
240
241
    /**
242
     * Returns the recipients associated with the JWS.
243
     *
244
     * @return Recipient[]
245
     */
246
    public function getRecipients(): array
247
    {
248
        return $this->recipients;
249
    }
250
251
    /**
252
     * @param int $id
253
     *
254
     * @return Recipient
255
     */
256
    public function &getRecipient(int $id): Recipient
257
    {
258
        Assertion::keyExists($this->recipients, $id, 'The recipient does not exist.');
259
260
        return $this->recipients[$id];
261
    }
262
263
    /**
264
     * @return string|null The cyphertext
265
     */
266
    public function getCiphertext(): ?string
267
    {
268
        return $this->ciphertext;
269
    }
270
271
    /**
272
     * @param string $ciphertext
273
     *
274
     * @return JWE
275
     */
276
    public function withCiphertext(string $ciphertext): JWE
277
    {
278
        $jwe = clone $this;
279
        $jwe->ciphertext = $ciphertext;
280
281
        return $jwe;
282
    }
283
284
    /**
285
     * @return string|null
286
     */
287
    public function getAAD(): ?string
288
    {
289
        return $this->aad;
290
    }
291
292
    /**
293
     * @param string $aad
294
     *
295
     * @return JWE
296
     */
297
    public function withAAD(string $aad): JWE
298
    {
299
        $jwe = clone $this;
300
        $jwe->aad = $aad;
301
302
        return $jwe;
303
    }
304
305
    /**
306
     * @return string|null
307
     */
308
    public function getIV(): ?string
309
    {
310
        return $this->iv;
311
    }
312
313
    /**
314
     * @param string $iv
315
     *
316
     * @return JWE
317
     */
318
    public function withIV(string $iv): JWE
319
    {
320
        $jwe = clone $this;
321
        $jwe->iv = $iv;
322
323
        return $jwe;
324
    }
325
326
    /**
327
     * @return string|null
328
     */
329
    public function getTag(): ?string
330
    {
331
        return $this->tag;
332
    }
333
334
    /**
335
     * @param string $tag
336
     *
337
     * @return JWE
338
     */
339
    public function withTag(string $tag): JWE
340
    {
341
        $jwe = clone $this;
342
        $jwe->tag = $tag;
343
344
        return $jwe;
345
    }
346
347
    /**
348
     * @return string
349
     */
350
    public function getEncodedSharedProtectedHeaders(): string
351
    {
352
        return $this->encoded_shared_protected_headers ?? '';
353
    }
354
355
    /**
356
     * @param string $encoded_shared_protected_headers
357
     *
358
     * @return JWE
359
     */
360
    public function withEncodedSharedProtectedHeaders(string $encoded_shared_protected_headers): JWE
361
    {
362
        $jwe = clone $this;
363
        $jwe->encoded_shared_protected_headers = $encoded_shared_protected_headers;
364
365
        return $jwe;
366
    }
367
368
    /**
369
     * @return array
370
     */
371
    public function getSharedProtectedHeaders(): array
372
    {
373
        return $this->shared_protected_headers;
374
    }
375
376
    /**
377
     * @param array $shared_protected_headers
378
     *
379
     * @return JWE
380
     */
381
    public function withSharedProtectedHeaders(array $shared_protected_headers): JWE
382
    {
383
        $jwe = clone $this;
384
        $jwe->shared_protected_headers = $shared_protected_headers;
385
386
        return $jwe;
387
    }
388
389
    /**
390
     * @param string     $key
391
     * @param mixed|null $value
392
     *
393
     * @return JWE
394
     */
395
    public function withSharedProtectedHeader(string $key, $value): JWE
396
    {
397
        $jwe = clone $this;
398
        $jwe->shared_protected_headers[$key] = $value;
399
400
        return $jwe;
401
    }
402
403
    /**
404
     * @param string $key The key
405
     *
406
     * @return mixed|null Header value
407
     */
408
    public function getSharedProtectedHeader(string $key)
409
    {
410
        if ($this->hasSharedProtectedHeader($key)) {
411
            return $this->shared_protected_headers[$key];
412
        }
413
        throw new \InvalidArgumentException(sprintf('The shared protected header "%s" does not exist.', $key));
414
    }
415
416
    /**
417
     * @param string $key The key
418
     *
419
     * @return bool
420
     */
421
    public function hasSharedProtectedHeader(string $key): bool
422
    {
423
        return array_key_exists($key, $this->shared_protected_headers);
424
    }
425
426
    /**
427
     * @param array $shared_headers
428
     *
429
     * @return JWE
430
     */
431
    public function withSharedHeaders(array $shared_headers): JWE
432
    {
433
        $jwe = clone $this;
434
        $jwe->shared_headers = $shared_headers;
435
436
        return $jwe;
437
    }
438
439
    /**
440
     * @param string     $key
441
     * @param mixed|null $value
442
     *
443
     * @return JWE
444
     */
445
    public function withSharedHeader(string $key, $value): JWE
446
    {
447
        $jwe = clone $this;
448
        $jwe->shared_headers[$key] = $value;
449
450
        return $jwe;
451
    }
452
453
    /**
454
     * @return array
455
     */
456
    public function getSharedHeaders(): array
457
    {
458
        return $this->shared_headers;
459
    }
460
461
    /**
462
     * @param string $key The key
463
     *
464
     * @return mixed|null Header value
465
     */
466
    public function getSharedHeader(string $key)
467
    {
468
        if ($this->hasSharedHeader($key)) {
469
            return $this->shared_headers[$key];
470
        }
471
        throw new \InvalidArgumentException(sprintf('The shared header "%s" does not exist.', $key));
472
    }
473
474
    /**
475
     * @param string $key The key
476
     *
477
     * @return bool
478
     */
479
    public function hasSharedHeader(string $key): bool
480
    {
481
        return array_key_exists($key, $this->shared_headers);
482
    }
483
484
    /**
485
     * @param int $id
486
     *
487
     * @return string
488
     */
489
    public function toCompactJSON(int $id): string
490
    {
491
        $recipient = $this->getRecipient($id);
492
493
        $this->checkHasNoAAD();
494
        $this->checkHasSharedProtectedHeaders();
495
        $this->checkRecipientHasNoHeaders($id);
496
497
        return sprintf(
498
            '%s.%s.%s.%s.%s',
499
            $this->getEncodedSharedProtectedHeaders(),
500
            Base64Url::encode(null === $recipient->getEncryptedKey() ? '' : $recipient->getEncryptedKey()),
501
            Base64Url::encode(null === $this->getIV() ? '' : $this->getIV()),
502
            Base64Url::encode($this->getCiphertext()),
503
            Base64Url::encode(null === $this->getTag() ? '' : $this->getTag())
504
        );
505
    }
506
507
    private function checkHasNoAAD()
508
    {
509
        Assertion::true(empty($this->getAAD()), 'This JWE has AAD and cannot be converted into Compact JSON.');
510
    }
511
512
    /**
513
     * @param int $id
514
     */
515
    private function checkRecipientHasNoHeaders(int $id)
516
    {
517
        Assertion::true(
518
            empty($this->getSharedHeaders()) && empty($this->getRecipient($id)->getHeaders()),
519
            'This JWE has shared headers or recipient headers and cannot be converted into Compact JSON.'
520
        );
521
    }
522
523
    private function checkHasSharedProtectedHeaders()
524
    {
525
        Assertion::notEmpty(
526
            $this->getSharedProtectedHeaders(),
527
            'This JWE does not have shared protected headers and cannot be converted into Compact JSON.'
528
        );
529
    }
530
531
    /**
532
     * @param int $id
533
     *
534
     * @return string
535
     */
536
    public function toFlattenedJSON(int $id): string
537
    {
538
        $recipient = $this->getRecipient($id);
539
540
        $json = $this->getJSONBase();
541
542
        if (!empty($recipient->getHeaders())) {
543
            $json['header'] = $recipient->getHeaders();
544
        }
545
        if (!empty($recipient->getEncryptedKey())) {
546
            $json['encrypted_key'] = Base64Url::encode($recipient->getEncryptedKey());
547
        }
548
549
        return json_encode($json);
550
    }
551
552
    /**
553
     * @return string
554
     */
555
    public function toJSON(): string
556
    {
557
        $json = $this->getJSONBase();
558
        $json['recipients'] = [];
559
560
        foreach ($this->getRecipients() as $recipient) {
561
            $temp = [];
562
            if (!empty($recipient->getHeaders())) {
563
                $temp['header'] = $recipient->getHeaders();
564
            }
565
            if (!empty($recipient->getEncryptedKey())) {
566
                $temp['encrypted_key'] = Base64Url::encode($recipient->getEncryptedKey());
567
            }
568
            $json['recipients'][] = $temp;
569
        }
570
571
        return json_encode($json);
572
    }
573
574
    /**
575
     * @return array
576
     */
577
    private function getJSONBase(): array
578
    {
579
        $json = [
580
            'ciphertext' => Base64Url::encode($this->getCiphertext()),
581
        ];
582
        if (null !== $this->getIV()) {
583
            $json['iv'] = Base64Url::encode($this->getIV());
584
        }
585
        if (null !== $this->getTag()) {
586
            $json['tag'] = Base64Url::encode($this->getTag());
587
        }
588
        if (null !== $this->getAAD()) {
589
            $json['aad'] = Base64Url::encode($this->getAAD());
590
        }
591
        if (!empty($this->getSharedProtectedHeaders())) {
592
            $json['protected'] = $this->getEncodedSharedProtectedHeaders();
593
        }
594
        if (!empty($this->getSharedHeaders())) {
595
            $json['unprotected'] = $this->getSharedHeaders();
596
        }
597
598
        return $json;
599
    }
600
}
601