JSONGeneralSerializer::serialize()   B
last analyzed

Complexity

Conditions 8
Paths 41

Size

Total Lines 34

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 34
rs 8.1315
c 0
b 0
f 0
cc 8
nc 41
nop 2
1
<?php
2
3
declare(strict_types=1);
4
5
/*
6
 * The MIT License (MIT)
7
 *
8
 * Copyright (c) 2014-2019 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\Serializer;
15
16
use Base64Url\Base64Url;
17
use InvalidArgumentException;
18
use Jose\Component\Core\Util\JsonConverter;
19
use Jose\Component\Encryption\JWE;
20
use Jose\Component\Encryption\Recipient;
21
use LogicException;
22
23
final class JSONGeneralSerializer implements JWESerializer
24
{
25
    public const NAME = 'jwe_json_general';
26
27
    public function displayName(): string
28
    {
29
        return 'JWE JSON General';
30
    }
31
32
    public function name(): string
33
    {
34
        return self::NAME;
35
    }
36
37
    /**
38
     * @throws LogicException if there is no recipient
39
     */
40
    public function serialize(JWE $jwe, ?int $recipientIndex = null): string
41
    {
42
        if (0 === $jwe->countRecipients()) {
43
            throw new LogicException('No recipient.');
44
        }
45
46
        $data = [
47
            'ciphertext' => Base64Url::encode($jwe->getCiphertext()),
48
            'iv' => Base64Url::encode($jwe->getIV()),
49
            'tag' => Base64Url::encode($jwe->getTag()),
50
        ];
51
        if (null !== $jwe->getAAD()) {
52
            $data['aad'] = Base64Url::encode($jwe->getAAD());
53
        }
54
        if (0 !== \count($jwe->getSharedProtectedHeader())) {
55
            $data['protected'] = $jwe->getEncodedSharedProtectedHeader();
56
        }
57
        if (0 !== \count($jwe->getSharedHeader())) {
58
            $data['unprotected'] = $jwe->getSharedHeader();
59
        }
60
        $data['recipients'] = [];
61
        foreach ($jwe->getRecipients() as $recipient) {
62
            $temp = [];
63
            if (0 !== \count($recipient->getHeader())) {
64
                $temp['header'] = $recipient->getHeader();
65
            }
66
            if (null !== $recipient->getEncryptedKey()) {
67
                $temp['encrypted_key'] = Base64Url::encode($recipient->getEncryptedKey());
68
            }
69
            $data['recipients'][] = $temp;
70
        }
71
72
        return JsonConverter::encode($data);
73
    }
74
75
    public function unserialize(string $input): JWE
76
    {
77
        $data = JsonConverter::decode($input);
78
        $this->checkData($data);
79
80
        $ciphertext = Base64Url::decode($data['ciphertext']);
81
        $iv = Base64Url::decode($data['iv']);
82
        $tag = Base64Url::decode($data['tag']);
83
        $aad = \array_key_exists('aad', $data) ? Base64Url::decode($data['aad']) : null;
84
        list($encodedSharedProtectedHeader, $sharedProtectedHeader, $sharedHeader) = $this->processHeaders($data);
85
        $recipients = [];
86
        foreach ($data['recipients'] as $recipient) {
87
            list($encryptedKey, $header) = $this->processRecipient($recipient);
88
            $recipients[] = new Recipient($header, $encryptedKey);
89
        }
90
91
        return new JWE(
92
            $ciphertext,
93
            $iv,
94
            $tag,
95
            $aad,
96
            $sharedHeader,
97
            $sharedProtectedHeader,
98
            $encodedSharedProtectedHeader,
99
            $recipients
100
        );
101
    }
102
103
    /**
104
     * @throws InvalidArgumentException if the input is not supported
105
     */
106
    private function checkData(?array $data): void
107
    {
108
        if (null === $data || !isset($data['ciphertext']) || !isset($data['recipients'])) {
109
            throw new InvalidArgumentException('Unsupported input.');
110
        }
111
    }
112
113
    private function processRecipient(array $recipient): array
114
    {
115
        $encryptedKey = \array_key_exists('encrypted_key', $recipient) ? Base64Url::decode($recipient['encrypted_key']) : null;
116
        $header = \array_key_exists('header', $recipient) ? $recipient['header'] : [];
117
118
        return [$encryptedKey, $header];
119
    }
120
121
    private function processHeaders(array $data): array
122
    {
123
        $encodedSharedProtectedHeader = \array_key_exists('protected', $data) ? $data['protected'] : null;
124
        $sharedProtectedHeader = $encodedSharedProtectedHeader ? JsonConverter::decode(Base64Url::decode($encodedSharedProtectedHeader)) : [];
125
        $sharedHeader = \array_key_exists('unprotected', $data) ? $data['unprotected'] : [];
126
127
        return [$encodedSharedProtectedHeader, $sharedProtectedHeader, $sharedHeader];
128
    }
129
}
130