PBEKDF2::derive()   A
last analyzed

Complexity

Conditions 2
Paths 2

Size

Total Lines 14
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 10
CRAP Score 2

Importance

Changes 0
Metric Value
eloc 9
dl 0
loc 14
c 0
b 0
f 0
ccs 10
cts 10
cp 1
rs 9.9666
cc 2
nc 2
nop 4
crap 2
1
<?php
2
3
declare(strict_types = 1);
4
5
namespace Sop\PKCS5\PBEKD;
6
7
use Sop\PKCS5\PRF\PRF;
8
9
/**
10
 * Implements key derivation function #2 used in password-based cryptography.
11
 *
12
 * @see https://tools.ietf.org/html/rfc2898#section-5.2
13
 */
14
class PBEKDF2 extends PBEKDF
15
{
16
    /**
17
     * Pseudorandom functor.
18
     *
19
     * @var PRF
20
     */
21
    protected $_prf;
22
23
    /**
24
     * Constructor.
25
     *
26
     * @param PRF $prf
27
     */
28 3
    public function __construct(PRF $prf)
29
    {
30 3
        $this->_prf = $prf;
31 3
    }
32
33
    /**
34
     * {@inheritdoc}
35
     */
36 4
    public function derive(string $password, string $salt, int $count,
37
        int $length): string
38
    {
39 4
        $hlen = $this->_prf->length();
40 4
        $l = intval(ceil($length / $hlen));
41 4
        $r = $length - ($l - 1) * $hlen;
42 4
        $blocks = [];
43 4
        for ($i = 1; $i <= $l; ++$i) {
44 4
            $blocks[] = $this->_f($password, $salt, $count, $i);
45
        }
46
        // truncate last block
47 4
        $blocks[] = substr(array_pop($blocks), 0, $r);
48 4
        $dk = implode('', $blocks);
49 4
        return substr($dk, 0, $length);
50
    }
51
52
    /**
53
     * XOR-sum function F.
54
     *
55
     * @param string $P
56
     * @param string $S
57
     * @param int    $c
58
     * @param int    $i
59
     *
60
     * @return string
61
     */
62 4
    protected function _f(string $P, string $S, int $c, int $i): string
63
    {
64
        // compute U_1
65 4
        $U = $this->_prf->compute($P, $S . pack('N', $i));
66 4
        $result = $U;
67 4
        for ($x = 2; $x <= $c; ++$x) {
68
            // U_x receives feedback from U_{x-1}
69 3
            $U_x = $this->_prf->compute($P, $U);
70
            // add to XOR-sum
71 3
            $result ^= $U_x;
72 3
            $U = $U_x;
73
        }
74 4
        return $result;
75
    }
76
}
77