Completed
Push — v2.0.x ( 7a58b6 )
by Florent
24:58
created

Loader::loadSerializedJsonJWS()   B

Complexity

Conditions 5
Paths 10

Size

Total Lines 22
Code Lines 13

Duplication

Lines 0
Ratio 0 %

Importance

Changes 6
Bugs 1 Features 3
Metric Value
c 6
b 1
f 3
dl 0
loc 22
rs 8.6737
cc 5
eloc 13
nc 10
nop 1
1
<?php
2
3
/*
4
 * The MIT License (MIT)
5
 *
6
 * Copyright (c) 2014-2015 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;
13
14
use Base64Url\Base64Url;
15
use Jose\Object\JWE;
16
use Jose\Object\JWS;
17
use Jose\Object\Recipient;
18
use Jose\Object\Signature;
19
20
/**
21
 * Class able to load JWS or JWE.
22
 * JWS object can also be verified.
23
 */
24
final class Loader implements LoaderInterface
25
{
26
    /**
27
     * Loader constructor.
28
     */
29
    private function __construct() {}
30
31
    /**
32
     * {@inheritdoc}
33
     */
34
    public static function load($input)
35
    {
36
        $json = self::convert($input);
37
        if (array_key_exists('signatures', $json)) {
38
            return self::loadSerializedJsonJWS($json);
39
        }
40
        if (array_key_exists('recipients', $json)) {
41
            return self::loadSerializedJsonJWE($json, $input);
42
        }
43
        throw new \InvalidArgumentException('Unable to load the input');
44
    }
45
46
    /**
47
     * @param array  $data
48
     *
49
     * @return \Jose\Object\JWSInterface|\Jose\Object\JWSInterface[]
50
     */
51
    private static function loadSerializedJsonJWS(array $data)
52
    {
53
        $jws = new JWS();
54
        if (array_key_exists('payload', $data)) {
55
            $jws = $jws->withPayload(Base64Url::decode($data['payload']));
56
        }
57
58
        foreach ($data['signatures'] as $signature) {
59
            $object = new Signature();
60
            $object = $object->withSignature(Base64Url::decode($signature['signature']));
61
            if (array_key_exists('protected', $signature)) {
62
                $object = $object->withEncodedProtectedHeaders($signature['protected']);
63
            }
64
            if (array_key_exists('header', $signature)) {
65
                $object = $object->withHeaders($signature['header']);
66
            }
67
68
            $jws = $jws->addSignature($object);
69
        }
70
71
        return $jws;
72
    }
73
74
    /**
75
     * @param array  $data
76
     * @param string $input
77
     *
78
     * @return \Jose\Object\JWEInterface|\Jose\Object\JWEInterface[]
79
     */
80
    private static function loadSerializedJsonJWE(array $data, $input)
0 ignored issues
show
Unused Code introduced by
The parameter $input is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
81
    {
82
        $jwe = new JWE();
83
        $jwe = $jwe->withCiphertext(Base64Url::decode($data['ciphertext']));
84
        if (array_key_exists('iv', $data)) {
85
            $jwe = $jwe->withIV(Base64Url::decode($data['iv']));
86
        }
87
        if (array_key_exists('aad', $data)) {
88
            $jwe = $jwe->withAAD(Base64Url::decode($data['aad']));
89
        }
90
        if (array_key_exists('tag', $data)) {
91
            $jwe = $jwe->withTag(Base64Url::decode($data['tag']));
92
        }
93
        if (array_key_exists('protected', $data)) {
94
            $jwe = $jwe->withEncodedSharedProtectedHeaders($data['tag']);
95
        }
96
        if (array_key_exists('unprotected', $data)) {
97
            $jwe = $jwe->withSharedHeaders($data['unprotected']);
98
        }
99
        foreach ($data['recipients'] as $recipient) {
100
            $object = new Recipient();
101
            if (array_key_exists('header', $recipient)) {
102
                $object = $object->withHeaders($recipient['header']);
103
            }
104
            if (array_key_exists('encrypted_key', $recipient)) {
105
                $object = $object->withEncryptedKey($recipient['encrypted_key']);
106
            }
107
108
            $jwe = $jwe->addRecipient($object);
109
        }
110
111
        return $jwe;
112
    }
113
114
    private static function convert($input)
115
    {
116
        if (is_array($data = json_decode($input, true))) {
117
            if (array_key_exists('signatures', $data) || array_key_exists('recipients', $data)) {
118
                return $data;
119
            } elseif (array_key_exists('signature', $data)) {
120
                return self::fromFlattenedSerializationSignatureToSerialization($data);
121
            } elseif (array_key_exists('ciphertext', $data)) {
122
                return self::fromFlattenedSerializationRecipientToSerialization($data);
123
            }
124
        } elseif (is_string($input)) {
125
            return self::fromCompactSerializationToSerialization($input);
126
        }
127
        throw new \InvalidArgumentException('Unsupported input');
128
    }
129
130
    /**
131
     * @param $input
132
     *
133
     * @return array
134
     */
135
    private static function fromFlattenedSerializationRecipientToSerialization($input)
136
    {
137
        $recipient = [];
138
        foreach (['header', 'encrypted_key'] as $key) {
139
            if (array_key_exists($key, $input)) {
140
                $recipient[$key] = $input[$key];
141
            }
142
        }
143
        $recipients = [
144
            'ciphertext' => $input['ciphertext'],
145
            'recipients' => [$recipient],
146
        ];
147
        foreach (['ciphertext', 'protected', 'unprotected', 'iv', 'aad', 'tag'] as $key) {
148
            if (array_key_exists($key, $input)) {
149
                $recipients[$key] = $input[$key];
150
            }
151
        }
152
153
        return $recipients;
154
    }
155
156
    /**
157
     * @param $input
158
     *
159
     * @return array
160
     */
161
    private static function fromFlattenedSerializationSignatureToSerialization($input)
162
    {
163
        $signature = [
164
            'signature' => $input['signature'],
165
        ];
166
        foreach (['protected', 'header'] as $key) {
167
            if (array_key_exists($key, $input)) {
168
                $signature[$key] = $input[$key];
169
            }
170
        }
171
172
        $temp = [];
173
        if (!empty($input['payload'])) {
174
            $temp['payload'] = $input['payload'];
175
        }
176
        $temp['signatures'] = [$signature];
177
178
        return $temp;
179
    }
180
181
    /**
182
     * @param $input
183
     *
184
     * @return array
185
     */
186
    private static function fromCompactSerializationToSerialization($input)
187
    {
188
        $parts = explode('.', $input);
189
        switch (count($parts)) {
190
            case 3:
191
                return self::fromCompactSerializationSignatureToSerialization($parts);
192
            case 5:
193
                return self::fromCompactSerializationRecipientToSerialization($parts);
194
            default:
195
                throw new \InvalidArgumentException('Unsupported input');
196
        }
197
    }
198
199
    /**
200
     * @param array $parts
201
     *
202
     * @return array
203
     */
204
    private static function fromCompactSerializationRecipientToSerialization(array $parts)
205
    {
206
        $recipient = [];
207
        if (!empty($parts[1])) {
208
            $recipient['encrypted_key'] = $parts[1];
209
        }
210
211
        $recipients = [
212
            'recipients' => [$recipient],
213
        ];
214
        foreach ([3 => 'ciphertext', 0 => 'protected', 2 => 'iv', 4 => 'tag'] as $part => $key) {
215
            if (!empty($parts[$part])) {
216
                $recipients[$key] = $parts[$part];
217
            }
218
        }
219
220
        return $recipients;
221
    }
222
223
    /**
224
     * @param array $parts
225
     *
226
     * @return array
227
     */
228
    private static function fromCompactSerializationSignatureToSerialization(array $parts)
229
    {
230
        $temp = [];
231
232
        if (!empty($parts[1])) {
233
            $temp['payload'] = $parts[1];
234
        }
235
        $temp['signatures'] = [[
236
            'protected' => $parts[0],
237
            'signature' => $parts[2],
238
        ]];
239
240
        return $temp;
241
    }
242
}
243