Completed
Push — v2.0.x ( b31625...24925e )
by Florent
02:26
created

JWE::toCompactJSON()   A

Complexity

Conditions 4
Paths 1

Size

Total Lines 17
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Importance

Changes 5
Bugs 2 Features 0
Metric Value
c 5
b 2
f 0
dl 0
loc 17
rs 9.2
cc 4
eloc 12
nc 1
nop 1
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
namespace Jose\Object;
13
14
use Base64Url\Base64Url;
15
16
/**
17
 * Class JWE.
18
 */
19
final class JWE implements JWEInterface
20
{
21
    use JWT;
22
23
    /**
24
     * @var \Jose\Object\RecipientInterface[]
25
     */
26
    private $recipients = [];
27
28
    /**
29
     * @var string|null
30
     */
31
    private $ciphertext = null;
32
33
    /**
34
     * @var string|null
35
     */
36
    private $iv = null;
37
38
    /**
39
     * @var string|null
40
     */
41
    private $aad = null;
42
43
    /**
44
     * @var string|null
45
     */
46
    private $tag = null;
47
48
    /**
49
     * @var array
50
     */
51
    private $shared_headers = [];
52
53
    /**
54
     * @var array
55
     */
56
    private $shared_protected_headers = [];
57
58
    /**
59
     * @var string|null
60
     */
61
    private $encoded_shared_protected_headers = null;
62
63
    /**
64
     * @var string|null
65
     */
66
    private $content_encryption_key = null;
67
68
    /**
69
     * {@inheritdoc}
70
     */
71
    public function countRecipients()
72
    {
73
        return count($this->recipients);
74
    }
75
76
    /**
77
     * {@inheritdoc}
78
     */
79
    public function addRecipient(RecipientInterface $recipient)
80
    {
81
        $jwe = clone $this;
82
        $jwe->recipients[] = $recipient;
83
84
        return $jwe;
85
    }
86
87
    /**
88
     * {@inheritdoc}
89
     */
90
    public function getRecipients()
91
    {
92
        return $this->recipients;
93
    }
94
95
    /**
96
     * {@inheritdoc}
97
     */
98
    public function getRecipient($id)
99
    {
100
        if (!isset($this->recipients[$id])) {
101
            throw new \InvalidArgumentException('The recipient does not exist.');
102
        }
103
104
        return $this->recipients[$id];
105
    }
106
107
    /**
108
     * {@inheritdoc}
109
     */
110
    public function getCiphertext()
111
    {
112
        return $this->ciphertext;
113
    }
114
115
    /**
116
     * {@inheritdoc}
117
     */
118
    public function withCiphertext($ciphertext)
119
    {
120
        $jwe = clone $this;
121
        $jwe->ciphertext = $ciphertext;
122
123
        return $jwe;
124
    }
125
126
    /**
127
     * {@inheritdoc}
128
     */
129
    public function getAAD()
130
    {
131
        return $this->aad;
132
    }
133
134
    /**
135
     * {@inheritdoc}
136
     */
137
    public function withAAD($aad)
138
    {
139
        $jwe = clone $this;
140
        $jwe->aad = $aad;
141
142
        return $jwe;
143
    }
144
145
    /**
146
     * {@inheritdoc}
147
     */
148
    public function getIV()
149
    {
150
        return $this->iv;
151
    }
152
153
    /**
154
     * {@inheritdoc}
155
     */
156
    public function withIV($iv)
157
    {
158
        $jwe = clone $this;
159
        $jwe->iv = $iv;
160
161
        return $jwe;
162
    }
163
164
    /**
165
     * {@inheritdoc}
166
     */
167
    public function getTag()
168
    {
169
        return $this->tag;
170
    }
171
172
    /**
173
     * {@inheritdoc}
174
     */
175
    public function withTag($tag)
176
    {
177
        $jwe = clone $this;
178
        $jwe->tag = $tag;
179
180
        return $jwe;
181
    }
182
183
    /**
184
     * {@inheritdoc}
185
     */
186
    public function getEncodedSharedProtectedHeaders()
187
    {
188
        return $this->encoded_shared_protected_headers;
189
    }
190
191
    /**
192
     * {@inheritdoc}
193
     */
194
    public function withEncodedSharedProtectedHeaders($encoded_shared_protected_headers)
195
    {
196
        $jwe = clone $this;
197
        $jwe->encoded_shared_protected_headers = $encoded_shared_protected_headers;
198
199
        return $jwe;
200
    }
201
202
    /**
203
     * {@inheritdoc}
204
     */
205
    public function getSharedProtectedHeaders()
206
    {
207
        return $this->shared_protected_headers;
208
    }
209
210
    /**
211
     * {@inheritdoc}
212
     */
213
    public function withSharedProtectedHeaders(array $shared_protected_headers)
214
    {
215
        $jwe = clone $this;
216
        $jwe->shared_protected_headers = $shared_protected_headers;
217
218
        return $jwe;
219
    }
220
221
    /**
222
     * {@inheritdoc}
223
     */
224
    public function withSharedProtectedHeader($key, $value)
225
    {
226
        $jwe = clone $this;
227
        $jwe->shared_protected_headers[$key] = $value;
228
229
        return $jwe;
230
    }
231
232
    /**
233
     * {@inheritdoc}
234
     */
235
    public function getSharedProtectedHeader($key)
236
    {
237
        if ($this->hasSharedProtectedHeader($key)) {
238
            return $this->shared_protected_headers[$key];
239
        }
240
        throw new \InvalidArgumentException(sprintf('The shared protected header "%s" does not exist', $key));
241
    }
242
243
    /**
244
     * {@inheritdoc}
245
     */
246
    public function hasSharedProtectedHeader($key)
247
    {
248
        return array_key_exists($key, $this->shared_protected_headers);
249
    }
250
251
    /**
252
     * {@inheritdoc}
253
     */
254
    public function withSharedHeaders(array $shared_headers)
255
    {
256
        $jwe = clone $this;
257
        $jwe->shared_headers = $shared_headers;
258
259
        return $jwe;
260
    }
261
262
    /**
263
     * {@inheritdoc}
264
     */
265
    public function withSharedHeader($key, $value)
266
    {
267
        $jwe = clone $this;
268
        $jwe->shared_headers[$key] = $value;
269
270
        return $jwe;
271
    }
272
273
    /**
274
     * {@inheritdoc}
275
     */
276
    public function getSharedHeaders()
277
    {
278
        return $this->shared_headers;
279
    }
280
281
    /**
282
     * {@inheritdoc}
283
     */
284
    public function getSharedHeader($key)
285
    {
286
        if ($this->hasSharedHeader($key)) {
287
            return $this->shared_headers[$key];
288
        }
289
        throw new \InvalidArgumentException(sprintf('The shared header "%s" does not exist', $key));
290
    }
291
292
    /**
293
     * {@inheritdoc}
294
     */
295
    public function hasSharedHeader($key)
296
    {
297
        return array_key_exists($key, $this->shared_headers);
298
    }
299
300
    /**
301
     * {@inheritdoc}
302
     */
303
    public function toCompactJSON($id)
304
    {
305
        $recipient = $this->getRecipient($id);
306
307
        $this->checkHasNoAAD();
308
        $this->checkHasSharedProtectedHeaders();
309
        $this->checkRecipientHasNoHeaders($id);
310
311
        return sprintf(
312
            '%s.%s.%s.%s.%s',
313
            $this->getEncodedSharedProtectedHeaders(),
314
            Base64Url::encode(null === $recipient->getEncryptedKey() ? '' : $recipient->getEncryptedKey()),
315
            Base64Url::encode(null === $this->getIV() ? '' : $this->getIV()),
316
            Base64Url::encode($this->getCiphertext()),
317
            Base64Url::encode(null === $this->getTag() ? '' : $this->getTag())
318
        );
319
    }
320
321
    /**
322
     *
323
     */
324
    private function checkHasNoAAD()
325
    {
326
        if (!empty($this->getAAD())) {
327
            throw new \InvalidArgumentException('This JWE has AAD and cannot be converted into Compact JSON.');
328
        }
329
    }
330
331
    /**
332
     * @param int $id
333
     */
334
    private function checkRecipientHasNoHeaders($id)
335
    {
336
        if (!empty($this->getSharedHeaders()) || !empty($this->getRecipient($id)->getHeaders())) {
337
            throw new \InvalidArgumentException('This JWE has shared headers or recipient headers and cannot be converted into Compact JSON.');
338
        }
339
    }
340
341
    /**
342
     *
343
     */
344
    private function checkHasSharedProtectedHeaders()
345
    {
346
        if (empty($this->getSharedProtectedHeaders())) {
347
            throw new \InvalidArgumentException('This JWE does not have shared protected headers and cannot be converted into Compact JSON.');
348
        }
349
    }
350
351
    /**
352
     * {@inheritdoc}
353
     */
354
    public function toFlattenedJSON($id)
355
    {
356
        $recipient = $this->getRecipient($id);
357
358
        $json = $this->getJSONBase();
359
360
        if (!empty($recipient->getHeaders())) {
361
            $json['header'] = $recipient->getHeaders();
362
        }
363
        if (!empty($recipient->getEncryptedKey())) {
364
            $json['encrypted_key'] = Base64Url::encode($recipient->getEncryptedKey());
365
        }
366
367
        return json_encode($json);
368
    }
369
370
    /**
371
     * {@inheritdoc}
372
     */
373
    public function toJSON()
374
    {
375
376
        $json = $this->getJSONBase();
377
        $json['recipients'] = [];
378
379
        foreach ($this->getRecipients() as $recipient) {
380
            $temp = [];
381
            if (!empty($recipient->getHeaders())) {
382
                $temp['header'] = $recipient->getHeaders();
383
            }
384
            if (!empty($recipient->getEncryptedKey())) {
385
                $temp['encrypted_key'] = Base64Url::encode($recipient->getEncryptedKey());
386
            }
387
            $json['recipients'][] = $temp;
388
        }
389
390
        return json_encode($json);
391
    }
392
393
    /**
394
     * @return array
395
     */
396
    private function getJSONBase()
397
    {
398
        $json = [
399
            'ciphertext' => Base64Url::encode($this->getCiphertext()),
400
        ];
401
        if (null !== $this->getIV()) {
402
            $json['iv'] = Base64Url::encode($this->getIV());
403
        }
404
        if (null !== $this->getTag()) {
405
            $json['tag'] = Base64Url::encode($this->getTag());
406
        }
407
        if (null !== $this->getAAD()) {
408
            $json['aad'] = Base64Url::encode($this->getAAD());
409
        }
410
        if (!empty($this->getSharedProtectedHeaders())) {
411
            $json['protected'] = $this->getEncodedSharedProtectedHeaders();
412
        }
413
        if (!empty($this->getSharedHeaders())) {
414
            $json['unprotected'] = $this->getSharedHeaders();
415
        }
416
417
        return $json;
418
    }
419
420
    /**
421
     * {@inheritdoc}
422
     */
423
    public function getContentEncryptionKey()
424
    {
425
        return $this->content_encryption_key;
426
    }
427
428
    /**
429
     * {@inheritdoc}
430
     */
431
    public function withContentEncryptionKey($content_encryption_key)
432
    {
433
        $jwe = clone $this;
434
        $jwe->content_encryption_key = $content_encryption_key;
435
436
        return $jwe;
437
    }
438
}
439