Completed
Push — develop ( 686594...b5844e )
by Florent
03:11
created

JWE::withContentEncryptionKey()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 7
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 7
rs 9.4285
cc 1
eloc 4
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 Assert\Assertion;
15
use Base64Url\Base64Url;
16
17
/**
18
 * Class JWE.
19
 */
20
final class JWE implements JWEInterface
21
{
22
    use JWT;
23
24
    /**
25
     * @var \Jose\Object\RecipientInterface[]
26
     */
27
    private $recipients = [];
28
29
    /**
30
     * @var string|null
31
     */
32
    private $ciphertext = null;
33
34
    /**
35
     * @var string|null
36
     */
37
    private $iv = null;
38
39
    /**
40
     * @var string|null
41
     */
42
    private $aad = null;
43
44
    /**
45
     * @var string|null
46
     */
47
    private $tag = null;
48
49
    /**
50
     * @var array
51
     */
52
    private $shared_headers = [];
53
54
    /**
55
     * @var array
56
     */
57
    private $shared_protected_headers = [];
58
59
    /**
60
     * @var string|null
61
     */
62
    private $encoded_shared_protected_headers = null;
63
64
    /**
65
     * @var string|null
66
     */
67
    private $content_encryption_key = null;
0 ignored issues
show
Unused Code introduced by
The property $content_encryption_key is not used and could be removed.

This check marks private properties in classes that are never used. Those properties can be removed.

Loading history...
68
69
    /**
70
     * {@inheritdoc}
71
     */
72
    public function countRecipients()
73
    {
74
        return count($this->recipients);
75
    }
76
77
    /**
78
     * {@inheritdoc}
79
     */
80
    public function isEncrypted()
81
    {
82
        return null !== $this->getCiphertext();
83
    }
84
85
    /**
86
     * {@inheritdoc}
87
     */
88
    public function addRecipient(JWKInterface $recipient_key, $recipient_headers = [])
89
    {
90
        Assertion::true(null === $this->getCiphertext(), 'The JWE is encrypted. No additional recipient allowed.');
91
        $jwe = clone $this;
92
        $jwe->recipients[] = Recipient::createRecipient($recipient_key, $recipient_headers);
93
94
        return $jwe;
95
    }
96
97
    /**
98
     * {@inheritdoc}
99
     */
100
    public function addRecipientWithEncryptedKey($encrypted_key, array $recipient_headers)
101
    {
102
        $jwe = clone $this;
103
        $jwe->recipients[] = Recipient::createRecipientFromLoadedJWE($recipient_headers, $encrypted_key);
104
105
        return $jwe;
106
    }
107
108
    /**
109
     * {@inheritdoc}
110
     */
111
    public function getRecipients()
112
    {
113
        return $this->recipients;
114
    }
115
116
    /**
117
     * {@inheritdoc}
118
     */
119
    public function &getRecipient($id)
120
    {
121
        Assertion::keyExists($this->recipients, $id, 'The recipient does not exist.');
122
123
        return $this->recipients[$id];
124
    }
125
126
    /**
127
     * {@inheritdoc}
128
     */
129
    public function getCiphertext()
130
    {
131
        return $this->ciphertext;
132
    }
133
134
    /**
135
     * {@inheritdoc}
136
     */
137
    public function withCiphertext($ciphertext)
138
    {
139
        $jwe = clone $this;
140
        $jwe->ciphertext = $ciphertext;
141
142
        return $jwe;
143
    }
144
145
    /**
146
     * {@inheritdoc}
147
     */
148
    public function getAAD()
149
    {
150
        return $this->aad;
151
    }
152
153
    /**
154
     * {@inheritdoc}
155
     */
156
    public function withAAD($aad)
157
    {
158
        $jwe = clone $this;
159
        $jwe->aad = $aad;
160
161
        return $jwe;
162
    }
163
164
    /**
165
     * {@inheritdoc}
166
     */
167
    public function getIV()
168
    {
169
        return $this->iv;
170
    }
171
172
    /**
173
     * {@inheritdoc}
174
     */
175
    public function withIV($iv)
176
    {
177
        $jwe = clone $this;
178
        $jwe->iv = $iv;
179
180
        return $jwe;
181
    }
182
183
    /**
184
     * {@inheritdoc}
185
     */
186
    public function getTag()
187
    {
188
        return $this->tag;
189
    }
190
191
    /**
192
     * {@inheritdoc}
193
     */
194
    public function withTag($tag)
195
    {
196
        $jwe = clone $this;
197
        $jwe->tag = $tag;
198
199
        return $jwe;
200
    }
201
202
    /**
203
     * {@inheritdoc}
204
     */
205
    public function getEncodedSharedProtectedHeaders()
206
    {
207
        return $this->encoded_shared_protected_headers;
208
    }
209
210
    /**
211
     * {@inheritdoc}
212
     */
213
    public function withEncodedSharedProtectedHeaders($encoded_shared_protected_headers)
214
    {
215
        $jwe = clone $this;
216
        $jwe->encoded_shared_protected_headers = $encoded_shared_protected_headers;
217
218
        return $jwe;
219
    }
220
221
    /**
222
     * {@inheritdoc}
223
     */
224
    public function getSharedProtectedHeaders()
225
    {
226
        return $this->shared_protected_headers;
227
    }
228
229
    /**
230
     * {@inheritdoc}
231
     */
232
    public function withSharedProtectedHeaders(array $shared_protected_headers)
233
    {
234
        $jwe = clone $this;
235
        $jwe->shared_protected_headers = $shared_protected_headers;
236
237
        return $jwe;
238
    }
239
240
    /**
241
     * {@inheritdoc}
242
     */
243
    public function withSharedProtectedHeader($key, $value)
244
    {
245
        $jwe = clone $this;
246
        $jwe->shared_protected_headers[$key] = $value;
247
248
        return $jwe;
249
    }
250
251
    /**
252
     * {@inheritdoc}
253
     */
254
    public function getSharedProtectedHeader($key)
255
    {
256
        if ($this->hasSharedProtectedHeader($key)) {
257
            return $this->shared_protected_headers[$key];
258
        }
259
        throw new \InvalidArgumentException(sprintf('The shared protected header "%s" does not exist.', $key));
260
    }
261
262
    /**
263
     * {@inheritdoc}
264
     */
265
    public function hasSharedProtectedHeader($key)
266
    {
267
        return array_key_exists($key, $this->shared_protected_headers);
268
    }
269
270
    /**
271
     * {@inheritdoc}
272
     */
273
    public function withSharedHeaders(array $shared_headers)
274
    {
275
        $jwe = clone $this;
276
        $jwe->shared_headers = $shared_headers;
277
278
        return $jwe;
279
    }
280
281
    /**
282
     * {@inheritdoc}
283
     */
284
    public function withSharedHeader($key, $value)
285
    {
286
        $jwe = clone $this;
287
        $jwe->shared_headers[$key] = $value;
288
289
        return $jwe;
290
    }
291
292
    /**
293
     * {@inheritdoc}
294
     */
295
    public function getSharedHeaders()
296
    {
297
        return $this->shared_headers;
298
    }
299
300
    /**
301
     * {@inheritdoc}
302
     */
303
    public function getSharedHeader($key)
304
    {
305
        if ($this->hasSharedHeader($key)) {
306
            return $this->shared_headers[$key];
307
        }
308
        throw new \InvalidArgumentException(sprintf('The shared header "%s" does not exist.', $key));
309
    }
310
311
    /**
312
     * {@inheritdoc}
313
     */
314
    public function hasSharedHeader($key)
315
    {
316
        return array_key_exists($key, $this->shared_headers);
317
    }
318
319
    /**
320
     * {@inheritdoc}
321
     */
322
    public function toCompactJSON($id)
323
    {
324
        $recipient = $this->getRecipient($id);
325
326
        $this->checkHasNoAAD();
327
        $this->checkHasSharedProtectedHeaders();
328
        $this->checkRecipientHasNoHeaders($id);
329
330
        return sprintf(
331
            '%s.%s.%s.%s.%s',
332
            $this->getEncodedSharedProtectedHeaders(),
333
            Base64Url::encode(null === $recipient->getEncryptedKey() ? '' : $recipient->getEncryptedKey()),
334
            Base64Url::encode(null === $this->getIV() ? '' : $this->getIV()),
335
            Base64Url::encode($this->getCiphertext()),
336
            Base64Url::encode(null === $this->getTag() ? '' : $this->getTag())
337
        );
338
    }
339
340
    private function checkHasNoAAD()
341
    {
342
        Assertion::true(empty($this->getAAD()), 'This JWE has AAD and cannot be converted into Compact JSON.');
343
    }
344
345
    /**
346
     * @param int $id
347
     */
348
    private function checkRecipientHasNoHeaders($id)
349
    {
350
        Assertion::true(
351
            empty($this->getSharedHeaders()) && empty($this->getRecipient($id)->getHeaders()),
352
            'This JWE has shared headers or recipient headers and cannot be converted into Compact JSON.'
353
        );
354
    }
355
356
    private function checkHasSharedProtectedHeaders()
357
    {
358
        Assertion::notEmpty(
359
            $this->getSharedProtectedHeaders(),
360
            'This JWE does not have shared protected headers and cannot be converted into Compact JSON.'
361
        );
362
    }
363
364
    /**
365
     * {@inheritdoc}
366
     */
367
    public function toFlattenedJSON($id)
368
    {
369
        $recipient = $this->getRecipient($id);
370
371
        $json = $this->getJSONBase();
372
373
        if (!empty($recipient->getHeaders())) {
374
            $json['header'] = $recipient->getHeaders();
375
        }
376
        if (!empty($recipient->getEncryptedKey())) {
377
            $json['encrypted_key'] = Base64Url::encode($recipient->getEncryptedKey());
378
        }
379
380
        return json_encode($json);
381
    }
382
383
    /**
384
     * {@inheritdoc}
385
     */
386
    public function toJSON()
387
    {
388
        $json = $this->getJSONBase();
389
        $json['recipients'] = [];
390
391
        foreach ($this->getRecipients() as $recipient) {
392
            $temp = [];
393
            if (!empty($recipient->getHeaders())) {
394
                $temp['header'] = $recipient->getHeaders();
395
            }
396
            if (!empty($recipient->getEncryptedKey())) {
397
                $temp['encrypted_key'] = Base64Url::encode($recipient->getEncryptedKey());
398
            }
399
            $json['recipients'][] = $temp;
400
        }
401
402
        return json_encode($json);
403
    }
404
405
    /**
406
     * @return array
407
     */
408
    private function getJSONBase()
409
    {
410
        $json = [
411
            'ciphertext' => Base64Url::encode($this->getCiphertext()),
412
        ];
413
        if (null !== $this->getIV()) {
414
            $json['iv'] = Base64Url::encode($this->getIV());
415
        }
416
        if (null !== $this->getTag()) {
417
            $json['tag'] = Base64Url::encode($this->getTag());
418
        }
419
        if (null !== $this->getAAD()) {
420
            $json['aad'] = $this->getAAD();
421
        }
422
        if (!empty($this->getSharedProtectedHeaders())) {
423
            $json['protected'] = $this->getEncodedSharedProtectedHeaders();
424
        }
425
        if (!empty($this->getSharedHeaders())) {
426
            $json['unprotected'] = $this->getSharedHeaders();
427
        }
428
429
        return $json;
430
    }
431
}
432