Spomky-Labs /
jose
These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
| 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\Object\JWEInterface; |
||
| 15 | use Jose\Object\JWKInterface; |
||
| 16 | use Jose\Object\JWKSet; |
||
| 17 | use Jose\Object\JWKSetInterface; |
||
| 18 | use Jose\Object\JWSInterface; |
||
| 19 | |||
| 20 | /** |
||
| 21 | * Class able to load JWS or JWE. |
||
| 22 | * JWS object can also be verified. |
||
| 23 | */ |
||
| 24 | final class Loader |
||
| 25 | { |
||
| 26 | /** |
||
| 27 | * @param $input |
||
| 28 | * @param JWKInterface $jwk |
||
| 29 | * @param array $allowed_key_encryption_algorithms |
||
| 30 | * @param array $allowed_content_encryption_algorithms |
||
| 31 | * @param int|null $recipient_index |
||
| 32 | * @return JWEInterface |
||
| 33 | */ |
||
| 34 | public function loadAndDecryptUsingKey($input, JWKInterface $jwk, array $allowed_key_encryption_algorithms, array $allowed_content_encryption_algorithms, ?int &$recipient_index = null): JWEInterface |
||
| 35 | { |
||
| 36 | $jwk_set = new JWKSet(); |
||
| 37 | $jwk_set->addKey($jwk); |
||
| 38 | |||
| 39 | return $this->loadAndDecrypt($input, $jwk_set, $allowed_key_encryption_algorithms, $allowed_content_encryption_algorithms, $recipient_index); |
||
| 40 | } |
||
| 41 | |||
| 42 | /** |
||
| 43 | * @param $input |
||
| 44 | * @param JWKSetInterface $jwk_set |
||
| 45 | * @param array $allowed_key_encryption_algorithms |
||
| 46 | * @param array $allowed_content_encryption_algorithms |
||
| 47 | * @param int|null $recipient_index |
||
| 48 | * @return JWEInterface |
||
| 49 | */ |
||
| 50 | public function loadAndDecryptUsingKeySet($input, JWKSetInterface $jwk_set, array $allowed_key_encryption_algorithms, array $allowed_content_encryption_algorithms, ?int &$recipient_index = null): JWEInterface |
||
| 51 | { |
||
| 52 | return $this->loadAndDecrypt($input, $jwk_set, $allowed_key_encryption_algorithms, $allowed_content_encryption_algorithms, $recipient_index); |
||
| 53 | } |
||
| 54 | |||
| 55 | /** |
||
| 56 | * @param $input |
||
| 57 | * @param JWKInterface $jwk |
||
| 58 | * @param array $allowed_algorithms |
||
| 59 | * @param int|null $signature_index |
||
| 60 | * @return JWSInterface |
||
| 61 | */ |
||
| 62 | public function loadAndVerifySignatureUsingKey($input, JWKInterface $jwk, array $allowed_algorithms, ?int &$signature_index = null): JWSInterface |
||
| 63 | { |
||
| 64 | $jwk_set = new JWKSet(); |
||
| 65 | $jwk_set->addKey($jwk); |
||
| 66 | |||
| 67 | return $this->loadAndVerifySignature($input, $jwk_set, $allowed_algorithms, null, $signature_index); |
||
| 68 | } |
||
| 69 | |||
| 70 | /** |
||
| 71 | * @param $input |
||
| 72 | * @param JWKSetInterface $jwk_set |
||
| 73 | * @param array $allowed_algorithms |
||
| 74 | * @param int|null $signature_index |
||
| 75 | * @return JWSInterface |
||
| 76 | */ |
||
| 77 | public function loadAndVerifySignatureUsingKeySet($input, JWKSetInterface $jwk_set, array $allowed_algorithms, ?int &$signature_index = null): JWSInterface |
||
| 78 | { |
||
| 79 | return $this->loadAndVerifySignature($input, $jwk_set, $allowed_algorithms, null, $signature_index); |
||
| 80 | } |
||
| 81 | |||
| 82 | /** |
||
| 83 | * @param $input |
||
| 84 | * @param JWKInterface $jwk |
||
| 85 | * @param array $allowed_algorithms |
||
| 86 | * @param string $detached_payload |
||
| 87 | * @param int|null $signature_index |
||
| 88 | * @return JWSInterface |
||
| 89 | */ |
||
| 90 | public function loadAndVerifySignatureUsingKeyAndDetachedPayload($input, JWKInterface $jwk, array $allowed_algorithms, string $detached_payload, ?int &$signature_index = null): JWSInterface |
||
| 91 | { |
||
| 92 | $jwk_set = new JWKSet(); |
||
| 93 | $jwk_set->addKey($jwk); |
||
| 94 | |||
| 95 | return $this->loadAndVerifySignature($input, $jwk_set, $allowed_algorithms, $detached_payload, $signature_index); |
||
| 96 | } |
||
| 97 | |||
| 98 | /** |
||
| 99 | * @param $input |
||
| 100 | * @param JWKSetInterface $jwk_set |
||
| 101 | * @param array $allowed_algorithms |
||
| 102 | * @param string $detached_payload |
||
| 103 | * @param int|null $signature_index |
||
| 104 | * @return JWSInterface |
||
| 105 | */ |
||
| 106 | public function loadAndVerifySignatureUsingKeySetAndDetachedPayload($input, JWKSetInterface $jwk_set, array $allowed_algorithms, string $detached_payload, ?int &$signature_index = null): JWSInterface |
||
| 107 | { |
||
| 108 | return $this->loadAndVerifySignature($input, $jwk_set, $allowed_algorithms, $detached_payload, $signature_index); |
||
| 109 | } |
||
| 110 | |||
| 111 | /** |
||
| 112 | * @param string $input |
||
| 113 | * @param JWKSetInterface $jwk_set |
||
| 114 | * @param array $allowed_key_encryption_algorithms |
||
| 115 | * @param array $allowed_content_encryption_algorithms |
||
| 116 | * @param null|int $recipient_index |
||
| 117 | * |
||
| 118 | * @return JWEInterface |
||
| 119 | */ |
||
| 120 | private function loadAndDecrypt(string $input, JWKSetInterface $jwk_set, array $allowed_key_encryption_algorithms, array $allowed_content_encryption_algorithms, ?int &$recipient_index = null): JWEInterface |
||
| 121 | { |
||
| 122 | $jwt = $this->load($input); |
||
| 123 | if (!$jwt instanceof JWEInterface) { |
||
| 124 | throw new \InvalidArgumentException('The input is not a valid JWE.'); |
||
| 125 | } |
||
| 126 | $decrypted = Decrypter::createDecrypter($allowed_key_encryption_algorithms, $allowed_content_encryption_algorithms, ['DEF', 'ZLIB', 'GZ']); |
||
| 127 | |||
| 128 | $decrypted->decryptUsingKeySet($jwt, $jwk_set, $recipient_index); |
||
| 129 | |||
| 130 | return $jwt; |
||
| 131 | } |
||
| 132 | |||
| 133 | /** |
||
| 134 | * @param string $input |
||
| 135 | * @param JWKSetInterface $jwk_set |
||
| 136 | * @param array $allowed_algorithms |
||
| 137 | * @param string|null $detached_payload |
||
| 138 | * @param null|int $signature_index |
||
| 139 | * |
||
| 140 | * @return JWSInterface |
||
| 141 | */ |
||
| 142 | private function loadAndVerifySignature(string $input, JWKSetInterface $jwk_set, array $allowed_algorithms, string $detached_payload = null, ?int &$signature_index = null): JWSInterface |
||
| 143 | { |
||
| 144 | $jwt = $this->load($input); |
||
| 145 | if (!$jwt instanceof JWSInterface) { |
||
| 146 | throw new \InvalidArgumentException('The input is not a valid JWS.'); |
||
| 147 | } |
||
| 148 | $verifier = Verifier::createVerifier($allowed_algorithms); |
||
| 149 | |||
| 150 | $verifier->verifyWithKeySet($jwt, $jwk_set, $detached_payload, $signature_index); |
||
|
0 ignored issues
–
show
It seems like
$signature_index defined by parameter $signature_index on line 142 can also be of type integer; however, Jose\Verifier::verifyWithKeySet() 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...
|
|||
| 151 | |||
| 152 | return $jwt; |
||
| 153 | } |
||
| 154 | |||
| 155 | /** |
||
| 156 | * @param string $input |
||
| 157 | * @return JWEInterface|JWSInterface |
||
| 158 | */ |
||
| 159 | public function load(string $input) |
||
| 160 | { |
||
| 161 | $json = $this->convert($input); |
||
| 162 | if (array_key_exists('signatures', $json)) { |
||
| 163 | return Util\JWSLoader::loadSerializedJsonJWS($json); |
||
| 164 | } |
||
| 165 | if (array_key_exists('recipients', $json)) { |
||
| 166 | return Util\JWELoader::loadSerializedJsonJWE($json); |
||
| 167 | } |
||
| 168 | } |
||
| 169 | |||
| 170 | /** |
||
| 171 | * @param string $input |
||
| 172 | * |
||
| 173 | * @return array |
||
| 174 | */ |
||
| 175 | private function convert(string $input): array |
||
| 176 | { |
||
| 177 | if (is_array($data = json_decode($input, true))) { |
||
| 178 | if (array_key_exists('signatures', $data) || array_key_exists('recipients', $data)) { |
||
| 179 | return $data; |
||
| 180 | } elseif (array_key_exists('signature', $data)) { |
||
| 181 | return $this->fromFlattenedSerializationSignatureToSerialization($data); |
||
| 182 | } elseif (array_key_exists('ciphertext', $data)) { |
||
| 183 | return $this->fromFlattenedSerializationRecipientToSerialization($data); |
||
| 184 | } |
||
| 185 | } elseif (is_string($input)) { |
||
| 186 | return $this->fromCompactSerializationToSerialization($input); |
||
| 187 | } |
||
| 188 | throw new \InvalidArgumentException('Unsupported input'); |
||
| 189 | } |
||
| 190 | |||
| 191 | /** |
||
| 192 | * @param array $input |
||
| 193 | * @return array |
||
| 194 | */ |
||
| 195 | private function fromFlattenedSerializationRecipientToSerialization(array $input): array |
||
| 196 | { |
||
| 197 | $recipient = []; |
||
| 198 | foreach (['header', 'encrypted_key'] as $key) { |
||
| 199 | if (array_key_exists($key, $input)) { |
||
| 200 | $recipient[$key] = $input[$key]; |
||
| 201 | } |
||
| 202 | } |
||
| 203 | $recipients = [ |
||
| 204 | 'ciphertext' => $input['ciphertext'], |
||
| 205 | 'recipients' => [$recipient], |
||
| 206 | ]; |
||
| 207 | foreach (['protected', 'unprotected', 'iv', 'aad', 'tag'] as $key) { |
||
| 208 | if (array_key_exists($key, $input)) { |
||
| 209 | $recipients[$key] = $input[$key]; |
||
| 210 | } |
||
| 211 | } |
||
| 212 | |||
| 213 | return $recipients; |
||
| 214 | } |
||
| 215 | |||
| 216 | /** |
||
| 217 | * @param array $input |
||
| 218 | * @return array |
||
| 219 | */ |
||
| 220 | private function fromFlattenedSerializationSignatureToSerialization(array $input): array |
||
| 221 | { |
||
| 222 | $signature = [ |
||
| 223 | 'signature' => $input['signature'], |
||
| 224 | ]; |
||
| 225 | foreach (['protected', 'header'] as $key) { |
||
| 226 | if (array_key_exists($key, $input)) { |
||
| 227 | $signature[$key] = $input[$key]; |
||
| 228 | } |
||
| 229 | } |
||
| 230 | |||
| 231 | $temp = []; |
||
| 232 | if (!empty($input['payload'])) { |
||
| 233 | $temp['payload'] = $input['payload']; |
||
| 234 | } |
||
| 235 | $temp['signatures'] = [$signature]; |
||
| 236 | |||
| 237 | return $temp; |
||
| 238 | } |
||
| 239 | |||
| 240 | /** |
||
| 241 | * @param string $input |
||
| 242 | * |
||
| 243 | * @return array |
||
| 244 | */ |
||
| 245 | private function fromCompactSerializationToSerialization($input) |
||
| 246 | { |
||
| 247 | $parts = explode('.', $input); |
||
| 248 | switch (count($parts)) { |
||
| 249 | case 3: |
||
| 250 | return $this->fromCompactSerializationSignatureToSerialization($parts); |
||
| 251 | case 5: |
||
| 252 | return $this->fromCompactSerializationRecipientToSerialization($parts); |
||
| 253 | default: |
||
| 254 | throw new \InvalidArgumentException('Unsupported input'); |
||
| 255 | } |
||
| 256 | } |
||
| 257 | |||
| 258 | /** |
||
| 259 | * @param array $parts |
||
| 260 | * |
||
| 261 | * @return array |
||
| 262 | */ |
||
| 263 | private function fromCompactSerializationRecipientToSerialization(array $parts): array |
||
| 264 | { |
||
| 265 | $recipient = []; |
||
| 266 | if (!empty($parts[1])) { |
||
| 267 | $recipient['encrypted_key'] = $parts[1]; |
||
| 268 | } |
||
| 269 | |||
| 270 | $recipients = [ |
||
| 271 | 'recipients' => [$recipient], |
||
| 272 | ]; |
||
| 273 | foreach ([0 => 'protected', 2 => 'iv', 3 => 'ciphertext', 4 => 'tag'] as $part => $key) { |
||
| 274 | if (!empty($parts[$part])) { |
||
| 275 | $recipients[$key] = $parts[$part]; |
||
| 276 | } |
||
| 277 | } |
||
| 278 | |||
| 279 | return $recipients; |
||
| 280 | } |
||
| 281 | |||
| 282 | /** |
||
| 283 | * @param array $parts |
||
| 284 | * |
||
| 285 | * @return array |
||
| 286 | */ |
||
| 287 | private function fromCompactSerializationSignatureToSerialization(array $parts): array |
||
| 288 | { |
||
| 289 | $temp = []; |
||
| 290 | |||
| 291 | if (!empty($parts[1])) { |
||
| 292 | $temp['payload'] = $parts[1]; |
||
| 293 | } |
||
| 294 | $temp['signatures'] = [[ |
||
| 295 | 'protected' => $parts[0], |
||
| 296 | 'signature' => $parts[2], |
||
| 297 | ]]; |
||
| 298 | |||
| 299 | return $temp; |
||
| 300 | } |
||
| 301 | } |
||
| 302 |
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.