PBES2::encryptWithKey()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 1

Importance

Changes 0
Metric Value
eloc 2
dl 0
loc 4
c 0
b 0
f 0
ccs 3
cts 3
cp 1
rs 10
cc 1
nc 1
nop 2
crap 1
1
<?php
2
3
declare(strict_types = 1);
4
5
namespace Sop\PKCS5;
6
7
use Sop\CryptoBridge\Crypto;
8
use Sop\CryptoTypes\AlgorithmIdentifier\Cipher\BlockCipherAlgorithmIdentifier;
9
use Sop\PKCS5\PBEKD\PBEKDF;
10
use Sop\PKCS5\PBEKD\PBEKDF2;
11
use Sop\PKCS5\PRF\PRF;
12
13
/**
14
 * Implements password-based encryption scheme #2.
15
 *
16
 * @see https://tools.ietf.org/html/rfc2898#section-6.2
17
 */
18
class PBES2 extends PBEScheme
19
{
20
    /**
21
     * Pseudorandom functor.
22
     *
23
     * @var PRF
24
     */
25
    protected $_prf;
26
27
    /**
28
     * Cipher algorithm.
29
     *
30
     * @var BlockCipherAlgorithmIdentifier
31
     */
32
    protected $_cipher;
33
34
    /**
35
     * Salt.
36
     *
37
     * @var string
38
     */
39
    protected $_salt;
40
41
    /**
42
     * Iteration count.
43
     *
44
     * @var int
45
     */
46
    protected $_iterationCount;
47
48
    /**
49
     * Crypto engine.
50
     *
51
     * @var Crypto
52
     */
53
    protected $_crypto;
54
55
    /**
56
     * Padding instance.
57
     *
58
     * @var Padding
59
     */
60
    protected $_padding;
61
62
    /**
63
     * Constructor.
64
     *
65
     * @param PRF                            $prf             Pseudorandom functor
66
     * @param BlockCipherAlgorithmIdentifier $cipher          Algorithm
67
     * @param string                         $salt            Salt
68
     * @param int                            $iteration_count Iteration count
69
     * @param null|Crypto                    $crypto          Crypto implementation,
70
     *                                                        use default if not set
71
     */
72 2
    public function __construct(PRF $prf, BlockCipherAlgorithmIdentifier $cipher,
73
        string $salt, int $iteration_count, ?Crypto $crypto = null)
74
    {
75 2
        $this->_prf = $prf;
76 2
        $this->_cipher = $cipher;
77 2
        $this->_salt = $salt;
78 2
        $this->_iterationCount = $iteration_count;
79 2
        $this->_crypto = $crypto ?? Crypto::getDefault();
80 2
        $this->_padding = new Padding($cipher->blockSize());
81 2
    }
82
83
    /**
84
     * {@inheritdoc}
85
     */
86 2
    public function encrypt(string $data, string $password): string
87
    {
88 2
        $key = $this->kdf()->derive($password, $this->_salt,
89 2
            $this->_iterationCount, $this->_cipher->keySize());
90 2
        return $this->encryptWithKey($data, $key);
91
    }
92
93
    /**
94
     * {@inheritdoc}
95
     */
96 2
    public function encryptWithKey(string $data, string $key): string
97
    {
98 2
        return $this->_crypto->encrypt($this->_padding->add($data), $key,
99 2
            $this->_cipher);
100
    }
101
102
    /**
103
     * {@inheritdoc}
104
     */
105 2
    public function decrypt(string $data, string $password): string
106
    {
107 2
        $key = $this->kdf()->derive($password, $this->_salt,
108 2
            $this->_iterationCount, $this->_cipher->keySize());
109 2
        return $this->decryptWithKey($data, $key);
110
    }
111
112
    /**
113
     * {@inheritdoc}
114
     *
115
     * @throws \UnexpectedValueException If decryption fails
116
     */
117 2
    public function decryptWithKey(string $data, string $key): string
118
    {
119
        try {
120 2
            $str = $this->_crypto->decrypt($data, $key, $this->_cipher);
121 2
            return $this->_padding->remove($str);
122 1
        } catch (\RuntimeException $e) {
123 1
            throw new \UnexpectedValueException('Decryption failed.', 0, $e);
124
        }
125
    }
126
127
    /**
128
     * {@inheritdoc}
129
     */
130 2
    public function kdf(): PBEKDF
131
    {
132 2
        return new PBEKDF2($this->_prf);
133
    }
134
}
135