Failed Conditions
Push — v7 ( a94305...5a1c51 )
by Florent
02:15
created

JWE::create()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 4
rs 10
c 0
b 0
f 0
cc 1
eloc 2
nc 1
nop 8

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\JWTInterface;
19
20
/**
21
 * Class JWE.
22
 */
23
final class JWE implements JWTInterface
24
{
25
    /**
26
     * @var Recipient[]
27
     */
28
    private $recipients = [];
29
30
    /**
31
     * @var string|null
32
     */
33
    private $ciphertext = null;
34
35
    /**
36
     * @var string|null
37
     */
38
    private $iv = null;
39
40
    /**
41
     * @var string|null
42
     */
43
    private $aad = null;
44
45
    /**
46
     * @var string|null
47
     */
48
    private $tag = null;
49
50
    /**
51
     * @var array
52
     */
53
    private $sharedHeaders = [];
54
55
    /**
56
     * @var array
57
     */
58
    private $sharedProtectedHeaders = [];
59
60
    /**
61
     * @var string|null
62
     */
63
    private $encodedSharedProtectedHeaders = null;
64
65
    /**
66
     * @var string|null
67
     */
68
    private $payload = null;
69
70
    /**
71
     * JWE constructor.
72
     *
73
     * @param string      $ciphertext
74
     * @param null|string $iv
75
     * @param null|string $aad
76
     * @param null|string $tag
77
     * @param array       $sharedHeaders
78
     * @param array       $sharedProtectedHeaders
79
     * @param null|string $encodedSharedProtectedHeaders
80
     * @param array       $recipients
81
     */
82
    private function __construct(string $ciphertext, ?string $iv = null, ?string $aad = null, ?string $tag = null, array $sharedHeaders = [], array $sharedProtectedHeaders = [], ?string $encodedSharedProtectedHeaders = null, array $recipients = [])
83
    {
84
        $this->ciphertext = $ciphertext;
85
        $this->iv = $iv;
86
        $this->aad = $aad;
87
        $this->tag = $tag;
88
        $this->sharedHeaders = $sharedHeaders;
89
        $this->sharedProtectedHeaders = $sharedProtectedHeaders;
90
        $this->encodedSharedProtectedHeaders = $encodedSharedProtectedHeaders;
91
        $this->recipients = $recipients;
92
    }
93
94
    /**
95
     * @param string      $ciphertext
96
     * @param null|string $iv
97
     * @param null|string $aad
98
     * @param null|string $tag
99
     * @param array       $sharedHeaders
100
     * @param array       $sharedProtectedHeaders
101
     * @param null|string $encodedSharedProtectedHeaders
102
     * @param array       $recipients
103
     *
104
     * @return JWE
105
     */
106
    public static function create(string $ciphertext, ?string $iv = null, ?string $aad = null, ?string $tag = null, array $sharedHeaders = [], array $sharedProtectedHeaders = [], ?string $encodedSharedProtectedHeaders = null, array $recipients = []): JWE
107
    {
108
        return new self($ciphertext, $iv, $aad, $tag, $sharedHeaders, $sharedProtectedHeaders, $encodedSharedProtectedHeaders, $recipients);
109
    }
110
111
    /**
112
     * {@inheritdoc}
113
     */
114
    public function getPayload(): ?string
115
    {
116
        return $this->payload;
117
    }
118
119
    /**
120
     * @param string $payload
121
     *
122
     * @return JWE
123
     */
124
    public function withPayload(string $payload): JWE
125
    {
126
        $clone = clone $this;
127
        $clone->payload = $payload;
128
129
        return $clone;
130
    }
131
132
    /**
133
     * Returns the number of recipients associated with the JWS.
134
     *
135
     * @return int
136
     */
137
    public function countRecipients(): int
138
    {
139
        return count($this->recipients);
140
    }
141
142
    /**
143
     * @return bool
144
     */
145
    public function isEncrypted(): bool
146
    {
147
        return null !== $this->getCiphertext();
148
    }
149
150
    /**
151
     * Returns the recipients associated with the JWS.
152
     *
153
     * @return Recipient[]
154
     */
155
    public function getRecipients(): array
156
    {
157
        return $this->recipients;
158
    }
159
160
    /**
161
     * @param int $id
162
     *
163
     * @return Recipient
164
     */
165
    public function getRecipient(int $id): Recipient
166
    {
167
        Assertion::keyExists($this->recipients, $id, 'The recipient does not exist.');
168
169
        return $this->recipients[$id];
170
    }
171
172
    /**
173
     * @return string|null The cyphertext
174
     */
175
    public function getCiphertext(): ?string
176
    {
177
        return $this->ciphertext;
178
    }
179
180
    /**
181
     * @return string|null
182
     */
183
    public function getAAD(): ?string
184
    {
185
        return $this->aad;
186
    }
187
188
    /**
189
     * @return string|null
190
     */
191
    public function getIV(): ?string
192
    {
193
        return $this->iv;
194
    }
195
196
    /**
197
     * @return string|null
198
     */
199
    public function getTag(): ?string
200
    {
201
        return $this->tag;
202
    }
203
204
    /**
205
     * @return string
206
     */
207
    public function getEncodedSharedProtectedHeaders(): string
208
    {
209
        return $this->encodedSharedProtectedHeaders ?? '';
210
    }
211
212
    /**
213
     * @return array
214
     */
215
    public function getSharedProtectedHeaders(): array
216
    {
217
        return $this->sharedProtectedHeaders;
218
    }
219
220
    /**
221
     * @param string $key The key
222
     *
223
     * @return mixed|null Header value
224
     */
225
    public function getSharedProtectedHeader(string $key)
226
    {
227
        if ($this->hasSharedProtectedHeader($key)) {
228
            return $this->sharedProtectedHeaders[$key];
229
        }
230
        throw new \InvalidArgumentException(sprintf('The shared protected header "%s" does not exist.', $key));
231
    }
232
233
    /**
234
     * @param string $key The key
235
     *
236
     * @return bool
237
     */
238
    public function hasSharedProtectedHeader(string $key): bool
239
    {
240
        return array_key_exists($key, $this->sharedProtectedHeaders);
241
    }
242
243
    /**
244
     * @return array
245
     */
246
    public function getSharedHeaders(): array
247
    {
248
        return $this->sharedHeaders;
249
    }
250
251
    /**
252
     * @param string $key The key
253
     *
254
     * @return mixed|null Header value
255
     */
256
    public function getSharedHeader(string $key)
257
    {
258
        if ($this->hasSharedHeader($key)) {
259
            return $this->sharedHeaders[$key];
260
        }
261
        throw new \InvalidArgumentException(sprintf('The shared header "%s" does not exist.', $key));
262
    }
263
264
    /**
265
     * @param string $key The key
266
     *
267
     * @return bool
268
     */
269
    public function hasSharedHeader(string $key): bool
270
    {
271
        return array_key_exists($key, $this->sharedHeaders);
272
    }
273
274
    /**
275
     * @param int $id
276
     *
277
     * @return string
278
     */
279
    public function toCompactJSON(int $id): string
280
    {
281
        $recipient = $this->getRecipient($id);
282
283
        $this->checkHasNoAAD();
284
        $this->checkHasSharedProtectedHeaders();
285
        $this->checkRecipientHasNoHeaders($id);
286
287
        return sprintf(
288
            '%s.%s.%s.%s.%s',
289
            $this->getEncodedSharedProtectedHeaders(),
290
            Base64Url::encode(null === $recipient->getEncryptedKey() ? '' : $recipient->getEncryptedKey()),
291
            Base64Url::encode(null === $this->getIV() ? '' : $this->getIV()),
292
            Base64Url::encode($this->getCiphertext()),
293
            Base64Url::encode(null === $this->getTag() ? '' : $this->getTag())
294
        );
295
    }
296
297
    private function checkHasNoAAD()
298
    {
299
        Assertion::true(empty($this->getAAD()), 'This JWE has AAD and cannot be converted into Compact JSON.');
300
    }
301
302
    /**
303
     * @param int $id
304
     */
305
    private function checkRecipientHasNoHeaders(int $id)
306
    {
307
        Assertion::true(
308
            empty($this->getSharedHeaders()) && empty($this->getRecipient($id)->getHeaders()),
309
            'This JWE has shared headers or recipient headers and cannot be converted into Compact JSON.'
310
        );
311
    }
312
313
    private function checkHasSharedProtectedHeaders()
314
    {
315
        Assertion::notEmpty(
316
            $this->getSharedProtectedHeaders(),
317
            'This JWE does not have shared protected headers and cannot be converted into Compact JSON.'
318
        );
319
    }
320
321
    /**
322
     * @param int $id
323
     *
324
     * @return string
325
     */
326
    public function toFlattenedJSON(int $id): string
327
    {
328
        $recipient = $this->getRecipient($id);
329
330
        $json = $this->getJSONBase();
331
332
        if (!empty($recipient->getHeaders())) {
333
            $json['header'] = $recipient->getHeaders();
334
        }
335
        if (!empty($recipient->getEncryptedKey())) {
336
            $json['encrypted_key'] = Base64Url::encode($recipient->getEncryptedKey());
337
        }
338
339
        return json_encode($json);
340
    }
341
342
    /**
343
     * @return string
344
     */
345
    public function toJSON(): string
346
    {
347
        $json = $this->getJSONBase();
348
        $json['recipients'] = [];
349
350
        foreach ($this->getRecipients() as $recipient) {
351
            $temp = [];
352
            if (!empty($recipient->getHeaders())) {
353
                $temp['header'] = $recipient->getHeaders();
354
            }
355
            if (!empty($recipient->getEncryptedKey())) {
356
                $temp['encrypted_key'] = Base64Url::encode($recipient->getEncryptedKey());
357
            }
358
            $json['recipients'][] = $temp;
359
        }
360
361
        return json_encode($json);
362
    }
363
364
    /**
365
     * @return array
366
     */
367
    private function getJSONBase(): array
368
    {
369
        $json = [
370
            'ciphertext' => Base64Url::encode($this->getCiphertext()),
371
        ];
372
        if (null !== $this->getIV()) {
373
            $json['iv'] = Base64Url::encode($this->getIV());
374
        }
375
        if (null !== $this->getTag()) {
376
            $json['tag'] = Base64Url::encode($this->getTag());
377
        }
378
        if (null !== $this->getAAD()) {
379
            $json['aad'] = Base64Url::encode($this->getAAD());
380
        }
381
        if (!empty($this->getSharedProtectedHeaders())) {
382
            $json['protected'] = $this->getEncodedSharedProtectedHeaders();
383
        }
384
        if (!empty($this->getSharedHeaders())) {
385
            $json['unprotected'] = $this->getSharedHeaders();
386
        }
387
388
        return $json;
389
    }
390
}
391