Failed Conditions
Push — master ( 7e3ce2...57efe1 )
by Florent
10:33
created

JSONGeneralSerializer::checkData()   A

Complexity

Conditions 4
Paths 2

Size

Total Lines 6
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 6
rs 9.2
c 0
b 0
f 0
cc 4
eloc 3
nc 2
nop 1
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\Serializer;
15
16
use Base64Url\Base64Url;
17
use Jose\Component\Core\Converter\JsonConverter;
18
use Jose\Component\Encryption\JWE;
19
use Jose\Component\Encryption\Recipient;
20
21
/**
22
 * Class JSONGeneralSerializer.
23
 */
24
final class JSONGeneralSerializer implements JWESerializer
25
{
26
    public const NAME = 'jwe_json_general';
27
28
    /**
29
     * @var JsonConverter
30
     */
31
    private $jsonConverter;
32
33
    /**
34
     * JSONFlattenedSerializer constructor.
35
     *
36
     * @param JsonConverter $jsonConverter
37
     */
38
    public function __construct(JsonConverter $jsonConverter)
39
    {
40
        $this->jsonConverter = $jsonConverter;
41
    }
42
43
    /**
44
     * {@inheritdoc}
45
     */
46
    public function displayName(): string
47
    {
48
        return 'JWE JSON General';
49
    }
50
51
    /**
52
     * {@inheritdoc}
53
     */
54
    public function name(): string
55
    {
56
        return self::NAME;
57
    }
58
59
    /**
60
     * {@inheritdoc}
61
     */
62
    public function serialize(JWE $jwe, ?int $recipientIndex = null): string
63
    {
64
        if (0 === $jwe->countRecipients()) {
65
            throw new \LogicException('No recipient.');
66
        }
67
68
        $data = [
69
            'ciphertext' => Base64Url::encode($jwe->getCiphertext()),
70
            'iv' => Base64Url::encode($jwe->getIV()),
71
            'tag' => Base64Url::encode($jwe->getTag()),
72
        ];
73
        if (null !== $jwe->getAAD()) {
74
            $data['aad'] = Base64Url::encode($jwe->getAAD());
75
        }
76
        if (!empty($jwe->getSharedProtectedHeaders())) {
77
            $data['protected'] = $jwe->getEncodedSharedProtectedHeaders();
78
        }
79
        if (!empty($jwe->getSharedHeaders())) {
80
            $data['unprotected'] = $jwe->getSharedHeaders();
81
        }
82
        $data['recipients'] = [];
83
        foreach ($jwe->getRecipients() as $recipient) {
84
            $temp = [];
85
            if (!empty($recipient->getHeaders())) {
86
                $temp['header'] = $recipient->getHeaders();
87
            }
88
            if (null !== $recipient->getEncryptedKey()) {
89
                $temp['encrypted_key'] = Base64Url::encode($recipient->getEncryptedKey());
90
            }
91
            $data['recipients'][] = $temp;
92
        }
93
94
        return $this->jsonConverter->encode($data);
95
    }
96
97
    /**
98
     * {@inheritdoc}
99
     */
100
    public function unserialize(string $input): JWE
101
    {
102
        $data = $this->jsonConverter->decode($input);
103
        $this->checkData($data);
104
105
        $ciphertext = Base64Url::decode($data['ciphertext']);
106
        $iv = Base64Url::decode($data['iv']);
107
        $tag = Base64Url::decode($data['tag']);
108
        $aad = array_key_exists('aad', $data) ? Base64Url::decode($data['aad']) : null;
109
        list($encodedSharedProtectedHeader, $sharedProtectedHeader, $sharedHeader) = $this->processHeaders($data);
110
        $recipients = [];
111
        foreach ($data['recipients'] as $recipient) {
112
            list($encryptedKey, $header) = $this->processRecipient($recipient);
113
            $recipients[] = Recipient::create($header, $encryptedKey);
114
        }
115
116
        return JWE::create(
117
            $ciphertext,
118
            $iv,
119
            $tag,
120
            $aad,
121
            $sharedHeader,
122
            $sharedProtectedHeader,
123
            $encodedSharedProtectedHeader,
124
            $recipients);
125
    }
126
127
    /**
128
     * @param $data
129
     */
130
    private function checkData($data)
131
    {
132
        if (!is_array($data) || !array_key_exists('ciphertext', $data) || !array_key_exists('recipients', $data)) {
133
            throw new \InvalidArgumentException('Unsupported input.');
134
        }
135
    }
136
137
    /**
138
     * @param array $recipient
139
     *
140
     * @return array
141
     */
142
    private function processRecipient(array $recipient): array
143
    {
144
        $encryptedKey = array_key_exists('encrypted_key', $recipient) ? Base64Url::decode($recipient['encrypted_key']) : null;
145
        $header = array_key_exists('header', $recipient) ? $recipient['header'] : [];
146
147
        return [$encryptedKey, $header];
148
    }
149
150
    /**
151
     * @param array $data
152
     *
153
     * @return array
154
     */
155
    private function processHeaders(array $data): array
156
    {
157
        $encodedSharedProtectedHeader = array_key_exists('protected', $data) ? $data['protected'] : null;
158
        $sharedProtectedHeader = $encodedSharedProtectedHeader ? $this->jsonConverter->decode(Base64Url::decode($encodedSharedProtectedHeader)) : [];
159
        $sharedHeader = array_key_exists('unprotected', $data) ? $data['unprotected'] : [];
160
161
        return [$encodedSharedProtectedHeader, $sharedProtectedHeader, $sharedHeader];
162
    }
163
}
164