Completed
Push — v2.0.x ( 5740fb...b31625 )
by Florent
02:24
created

Verifier::checkPayload()   A

Complexity

Conditions 3
Paths 2

Size

Total Lines 6
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 6
rs 9.4285
cc 3
eloc 3
nc 2
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;
13
14
use Jose\Algorithm\JWAManagerInterface;
15
use Jose\Algorithm\SignatureAlgorithmInterface;
16
use Jose\Behaviour\HasCheckerManager;
17
use Jose\Behaviour\HasJWAManager;
18
use Jose\Behaviour\HasKeyChecker;
19
use Jose\Checker\CheckerManagerInterface;
20
use Jose\Object\JWKInterface;
21
use Jose\Object\JWKSet;
22
use Jose\Object\JWKSetInterface;
23
use Jose\Object\JWSInterface;
24
use Jose\Object\SignatureInterface;
25
26
/**
27
 */
28
final class Verifier implements VerifierInterface
29
{
30
    use HasKeyChecker;
31
    use HasJWAManager;
32
    use HasCheckerManager;
33
34
    /**
35
     * Loader constructor.
36
     *
37
     * @param \Jose\Algorithm\JWAManagerInterface   $jwa_manager
38
     * @param \Jose\Checker\CheckerManagerInterface $checker_manager
39
     */
40
    public function __construct(
41
        JWAManagerInterface $jwa_manager,
42
        CheckerManagerInterface $checker_manager)
43
    {
44
        $this->setJWAManager($jwa_manager);
45
        $this->setCheckerManager($checker_manager);
46
    }
47
48
    /**
49
     * {@inheritdoc}
50
     *
51
     * @throws \InvalidArgumentException
52
     */
53
    public function verifyWithKey(JWSInterface $jws, JWKInterface $jwk, $detached_payload = null)
54
    {
55
        $jwk_set = new JWKSet();
56
        $jwk_set = $jwk_set->addKey($jwk);
57
58
        return $this->verifyWithKeySet($jws, $jwk_set, $detached_payload);
59
    }
60
61
    /**
62
     * {@inheritdoc}
63
     *
64
     * @throws \InvalidArgumentException
65
     */
66
    public function verifyWithKeySet(JWSInterface $jws, JWKSetInterface $jwk_set, $detached_payload = null)
67
    {
68
        $this->checkPayload($jws, $detached_payload);
0 ignored issues
show
Bug introduced by
It seems like $detached_payload defined by parameter $detached_payload on line 66 can also be of type string; however, Jose\Verifier::checkPayload() does only seem to accept null, maybe add an additional type check?

This check looks at variables that have been passed in as parameters and are passed out again to other methods.

If the outgoing method call has stricter type requirements than the method itself, an issue is raised.

An additional type check may prevent trouble.

Loading history...
69
        $this->checkJWKSet($jwk_set);
70
71
        foreach ($jws->getSignatures() as $signature) {
72
            $input = $signature->getEncodedProtectedHeaders().'.'.(null === $detached_payload ? $jws->getEncodedPayload() : $detached_payload);
73
74
            foreach ($jwk_set->getKeys() as $jwk) {
75
                $algorithm = $this->getAlgorithm($signature);
76
                try {
77
                    $this->checkKeyUsage($jwk, 'verification');
78
                    $this->checkKeyAlgorithm($jwk, $algorithm->getAlgorithmName());
79
                    if (true === $algorithm->verify($jwk, $input, $signature->getSignature())) {
80
                        $this->getCheckerManager()->checkJWT($jws);
81
82
                        return true;
83
                    }
84
                } catch (\Exception $e) {
85
                    //We do nothing, we continue with other keys
86
                    continue;
87
                }
88
            }
89
        }
90
91
        return false;
92
    }
93
94
    /**
95
     * @param \Jose\Object\JWKSetInterface $jwk_set
96
     */
97
    private function checkJWKSet(JWKSetInterface $jwk_set)
98
    {
99
        if (0 === count($jwk_set)) {
100
            throw new \InvalidArgumentException('No key in the key set.');
101
        }
102
    }
103
104
    /**
105
     * @param \Jose\Object\JWSInterface $jws
106
     * @param null                      $detached_payload
107
     */
108
    private function checkPayload(JWSInterface $jws, $detached_payload = null)
109
    {
110
        if (null !== $detached_payload && !empty($jws->getEncodedPayload())) {
111
            throw new \InvalidArgumentException('A detached payload is set, but the JWS already has a payload.');
112
        }
113
    }
114
115
    /**
116
     * @param \Jose\Object\SignatureInterface $signature
117
     *
118
     * @return \Jose\Algorithm\SignatureAlgorithmInterface|null
119
     */
120
    private function getAlgorithm(SignatureInterface $signature)
121
    {
122
        $complete_headers = array_merge(
123
            $signature->getProtectedHeaders(),
124
            $signature->getHeaders()
125
        );
126
        if (!array_key_exists('alg', $complete_headers)) {
127
            throw new \InvalidArgumentException('No "alg" parameter set in the header.');
128
        }
129
130
        $algorithm = $this->getJWAManager()->getAlgorithm($complete_headers['alg']);
131
        if (!$algorithm instanceof SignatureAlgorithmInterface) {
132
            throw new \RuntimeException(sprintf('The algorithm "%s" is not supported or does not implement SignatureInterface.', $complete_headers['alg']));
133
        }
134
135
        return $algorithm;
136
    }
137
}
138