GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.

PBES2Algorithm::headerParameters()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 5
CRAP Score 1

Importance

Changes 0
Metric Value
eloc 4
dl 0
loc 6
ccs 5
cts 5
cp 1
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 0
crap 1
1
<?php
2
3
declare(strict_types = 1);
4
5
namespace Sop\JWX\JWE\KeyAlgorithm;
6
7
use Sop\AESKW\AESKeyWrapAlgorithm;
8
use Sop\JWX\JWA\JWA;
9
use Sop\JWX\JWE\KeyAlgorithm\Feature\RandomCEK;
10
use Sop\JWX\JWE\KeyManagementAlgorithm;
11
use Sop\JWX\JWK\JWK;
12
use Sop\JWX\JWK\Symmetric\SymmetricKeyJWK;
13
use Sop\JWX\JWT\Header\Header;
14
use Sop\JWX\JWT\Parameter\AlgorithmParameter;
15
use Sop\JWX\JWT\Parameter\PBES2CountParameter;
16
use Sop\JWX\JWT\Parameter\PBES2SaltInputParameter;
17
18
/**
19
 * Base class for algorithms implementing PBES2 key encryption.
20
 *
21
 * @see https://tools.ietf.org/html/rfc7518#section-4.8
22
 */
23
abstract class PBES2Algorithm extends KeyManagementAlgorithm
24
{
25
    use RandomCEK;
26
27
    /**
28
     * Mapping from algorithm name to class name.
29
     *
30
     * @internal
31
     *
32
     * @var array
33
     */
34
    public const MAP_ALGO_TO_CLASS = [
35
        JWA::ALGO_PBES2_HS256_A128KW => PBES2HS256A128KWAlgorithm::class,
36
        JWA::ALGO_PBES2_HS384_A192KW => PBES2HS384A192KWAlgorithm::class,
37
        JWA::ALGO_PBES2_HS512_A256KW => PBES2HS512A256KWAlgorithm::class,
38
    ];
39
40
    /**
41
     * Password.
42
     *
43
     * @var string
44
     */
45
    protected $_password;
46
47
    /**
48
     * Salt input.
49
     *
50
     * @var string
51
     */
52
    protected $_saltInput;
53
54
    /**
55
     * Iteration count.
56
     *
57
     * @var int
58
     */
59
    protected $_count;
60
61
    /**
62
     * Derived key.
63
     *
64
     * @var string
65
     */
66
    private $_derivedKey;
67
68
    /**
69
     * Constructor.
70
     *
71
     * @param string $password   Password
72
     * @param string $salt_input Salt input
73
     * @param int    $count      Iteration count
74
     */
75 10
    public function __construct(string $password, string $salt_input, int $count)
76
    {
77 10
        $this->_password = $password;
78 10
        $this->_saltInput = $salt_input;
79 10
        $this->_count = $count;
80 10
    }
81
82
    /**
83
     * Initialize from JWK.
84
     *
85
     * @throws \UnexpectedValueException
86
     *
87
     * @return self
88
     */
89 7
    public static function fromJWK(JWK $jwk, Header $header): KeyManagementAlgorithm
90
    {
91 7
        $jwk = SymmetricKeyJWK::fromJWK($jwk);
92 7
        if (!$header->hasPBES2SaltInput()) {
93 1
            throw new \UnexpectedValueException('No salt input.');
94
        }
95 6
        $salt_input = $header->PBES2SaltInput()->saltInput();
96 6
        if (!$header->hasPBES2Count()) {
97 1
            throw new \UnexpectedValueException('No iteration count.');
98
        }
99 5
        $count = $header->PBES2Count()->value();
100 5
        $alg = JWA::deriveAlgorithmName($header, $jwk);
101 5
        if (!array_key_exists($alg, self::MAP_ALGO_TO_CLASS)) {
102 1
            throw new \UnexpectedValueException("Unsupported algorithm '{$alg}'.");
103
        }
104 4
        $cls = self::MAP_ALGO_TO_CLASS[$alg];
105 4
        return new $cls($jwk->key(), $salt_input, $count);
106
    }
107
108
    /**
109
     * Initialize from a password with random salt and default iteration count.
110
     *
111
     * @param string $password   Password
112
     * @param int    $count      Optional user defined iteration count
113
     * @param int    $salt_bytes Optional user defined salt length
114
     */
115 1
    public static function fromPassword(string $password, int $count = 64000,
116
        int $salt_bytes = 8): self
117
    {
118 1
        $salt_input = openssl_random_pseudo_bytes($salt_bytes);
119 1
        return new static($password, $salt_input, $count);
120
    }
121
122
    /**
123
     * Get salt input.
124
     */
125 1
    public function saltInput(): string
126
    {
127 1
        return $this->_saltInput;
128
    }
129
130
    /**
131
     * Get computed salt.
132
     */
133 9
    public function salt(): string
134
    {
135 9
        return PBES2SaltInputParameter::fromString($this->_saltInput)->salt(
136 9
            AlgorithmParameter::fromAlgorithm($this));
137
    }
138
139
    /**
140
     * Get iteration count.
141
     */
142 1
    public function iterationCount(): int
143
    {
144 1
        return $this->_count;
145
    }
146
147
    /**
148
     * {@inheritdoc}
149
     */
150 3
    public function headerParameters(): array
151
    {
152 3
        return array_merge(parent::headerParameters(),
153 3
            [AlgorithmParameter::fromAlgorithm($this),
154 3
                PBES2SaltInputParameter::fromString($this->_saltInput),
155 3
                new PBES2CountParameter($this->_count), ]);
156
    }
157
158
    /**
159
     * Get hash algorithm for hash_pbkdf2.
160
     */
161
    abstract protected function _hashAlgo(): string;
162
163
    /**
164
     * Get derived key length.
165
     */
166
    abstract protected function _keyLength(): int;
167
168
    /**
169
     * Get key wrapping algoritym.
170
     */
171
    abstract protected function _kwAlgo(): AESKeyWrapAlgorithm;
172
173
    /**
174
     * Get derived key.
175
     */
176 11
    protected function _derivedKey(): string
177
    {
178 11
        if (!isset($this->_derivedKey)) {
179 8
            $this->_derivedKey = hash_pbkdf2($this->_hashAlgo(),
180 8
                $this->_password, $this->salt(), $this->_count,
181 8
                $this->_keyLength(), true);
182
        }
183 11
        return $this->_derivedKey;
184
    }
185
186
    /**
187
     * {@inheritdoc}
188
     */
189 7
    protected function _encryptKey(string $key, Header &$header): string
190
    {
191 7
        return $this->_kwAlgo()->wrap($key, $this->_derivedKey());
192
    }
193
194
    /**
195
     * {@inheritdoc}
196
     */
197 4
    protected function _decryptKey(string $ciphertext, Header $header): string
198
    {
199 4
        return $this->_kwAlgo()->unwrap($ciphertext, $this->_derivedKey());
200
    }
201
}
202