Completed
Push — develop ( 8ddc4a...d84806 )
by Florent
02:34
created

JWE::addRecipientWithEncryptedKey()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 10
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Importance

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