Failed Conditions
Push — v7 ( e446d4...9b9adb )
by Florent
02:29
created

JWSParser::getHeaders()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 8
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 8
rs 9.4285
c 0
b 0
f 0
cc 2
eloc 4
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\Signature;
15
16
use Base64Url\Base64Url;
17
18
/**
19
 * Class able to parse JWS.
20
 */
21
final class JWSParser
22
{
23
    /**
24
     * Load data and return a JWS object.
25
     * Compact, Flattened or complete serialization formats are supported.
26
     *
27
     * @param string $input A string that represents a JWS
28
     *
29
     * @return JWS
30
     */
31
    public static function parse(string $input): JWS
32
    {
33
        $json = JWSConverter::convert($input);
34
35
        $jws = JWS::create();
36
37
        foreach ($json['signatures'] as $signature) {
38
            $bin_signature = Base64Url::decode($signature['signature']);
39
            $protected_headers = self::getProtectedHeaders($signature);
40
            $headers = self::getHeaders($signature);
41
42
            $jws = $jws->addSignature($bin_signature, $protected_headers, $headers);
43
        }
44
45
        self::populatePayload($jws, $json);
46
47
        return $jws;
48
    }
49
50
    /**
51
     * @param array $data
52
     *
53
     * @return string|null
54
     */
55
    private static function getProtectedHeaders(array $data): ?string
56
    {
57
        if (array_key_exists('protected', $data)) {
58
            return $data['protected'];
59
        }
60
61
        return null;
62
    }
63
64
    /**
65
     * @param array $data
66
     *
67
     * @return array
68
     */
69
    private static function getHeaders(array $data): array
70
    {
71
        if (array_key_exists('header', $data)) {
72
            return $data['header'];
73
        }
74
75
        return [];
76
    }
77
78
    /**
79
     * @param JWS   $jws
80
     * @param array $data
81
     */
82
    private static function populatePayload(JWS &$jws, array $data)
83
    {
84
        if (array_key_exists('payload', $data)) {
85
            $isPayloadEncoded = null;
86
            foreach ($jws->getSignatures() as $signature) {
87
                if (null === $isPayloadEncoded) {
88
                    $isPayloadEncoded = self::isPayloadEncoded($signature);
89
                }
90
                if (self::isPayloadEncoded($signature) !== $isPayloadEncoded) {
91
                    throw new \InvalidArgumentException('Foreign payload encoding detected. The JWS cannot be loaded.');
92
                }
93
            }
94
            $payload = $data['payload'];
95
            $jws = $jws->withAttachedPayload();
96
            $jws = $jws->withEncodedPayload($payload);
97
            if (false !== $isPayloadEncoded) {
98
                $payload = Base64Url::decode($payload);
99
            }
100
            $jws = $jws->withPayload($payload);
101
        } else {
102
            $jws = $jws->withDetachedPayload();
103
        }
104
    }
105
106
    /**
107
     * @param Signature $signature
108
     *
109
     * @return bool
110
     */
111
    private static function isPayloadEncoded(Signature $signature): bool
112
    {
113
        return !$signature->hasProtectedHeader('b64') || true === $signature->getProtectedHeader('b64');
114
    }
115
}
116