Completed
Push — master ( e5d930...4cc314 )
by Michael
01:28
created

OpensslKey::deriveKey()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 0
Metric Value
dl 0
loc 4
ccs 2
cts 2
cp 1
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 1
crap 1
1
<?php
2
3
declare(strict_types=1);
4
5
/**
6
 * OpensslKey.php.
7
 *
8
 * PHP version 7
9
 *
10
 * @category Dcrypt
11
 *
12
 * @author   Michael Meyer (mmeyer2k) <[email protected]>
13
 * @license  http://opensource.org/licenses/MIT The MIT License (MIT)
14
 *
15
 * @link     https://github.com/mmeyer2k/dcrypt
16
 */
17
18
namespace Dcrypt;
19
20
use Dcrypt\Exceptions\InvalidKeyEncodingException;
21
use Dcrypt\Exceptions\InvalidKeyLengthException;
22
use Exception;
23
24
/**
25
 * Provides key derivation functions.
26
 *
27
 * @category Dcrypt
28
 *
29
 * @author   Michael Meyer (mmeyer2k) <[email protected]>
30
 * @license  http://opensource.org/licenses/MIT The MIT License (MIT)
31
 *
32
 * @link     https://github.com/mmeyer2k/dcrypt
33
 */
34
final class OpensslKey
35
{
36
    /**
37
     * High entropy key.
38
     *
39
     * @var string
40
     */
41
    private $_key;
42
43
    /**
44
     * Algo string.
45
     *
46
     * @var string
47
     */
48
    private $_algo;
49
50
    /**
51
     * High entropy salt.
52
     *
53
     * @var string
54
     */
55
    private $_iv;
56
57
    /**
58
     * Name of cipher.
59
     *
60
     * @var string
61
     */
62
    private $_cipher;
63
64
    /**
65
     * OpensslKey constructor.
66
     *
67
     * @param string $key    Key to use for encryption
68
     * @param string $algo   Algo to use for HKDF
69
     * @param string $cipher Name of cipher
70
     * @param string $iv     Initialization vector
71
     *
72
     * @throws InvalidKeyLengthException
73
     * @throws InvalidKeyEncodingException
74
     */
75 48
    public function __construct(
76
        string $key,
77
        string $algo,
78
        string $cipher = '',
79
        string $iv = ''
80
    ) {
81
        // Store the key as what was supplied
82 48
        $this->_key = base64_decode($key, true);
83
84
        // If key was not proper base64, bail out
85 48
        if ($this->_key === false) {
86 9
            throw new InvalidKeyEncodingException();
87
        }
88
89
        // If key was to short, bail out
90 39
        if (Str::strlen($this->_key) < 32) {
91
            throw new InvalidKeyLengthException();
92
        }
93
94
        // Store algo in object
95 39
        $this->_algo = $algo;
96
97
        // Store init vector in object
98 39
        $this->_iv = $iv;
99
100
        // Store the cipher name
101 39
        $this->_cipher = $cipher;
102 39
    }
103
104
    /**
105
     * Generate the authentication key.
106
     *
107
     * @return string
108
     */
109 36
    public function authenticationKey(): string
110
    {
111 36
        return $this->deriveKey(__FUNCTION__ . '|' . $this->_cipher);
112
    }
113
114
    /**
115
     * Generate the encryption key.
116
     *
117
     * @return string
118
     */
119 37
    public function encryptionKey(): string
120
    {
121 37
        return $this->deriveKey(__FUNCTION__ . '|' . $this->_cipher);
122
    }
123
124
    /**
125
     * Derive a key with differing info string parameters.
126
     *
127
     * @param string $info Info parameter to provide to hash_hkdf
128
     *
129
     * @return string
130
     */
131 39
    public function deriveKey(string $info): string
132
    {
133 39
        return hash_hkdf($this->_algo, $this->_key, 0, $info, $this->_iv);
134
    }
135
136
    /**
137
     * Calculates a given message HMAC.
138
     *
139
     * @param string $message
140
     *
141
     * @return string
142
     */
143 36
    public function messageChecksum(string $message): string
144
    {
145 36
        return hash_hmac($this->_algo, $message, $this->authenticationKey(), true);
146
    }
147
148
    /**
149
     * Allows read only access to the internal variables needed by the openssl wrapper.
150
     *
151
     * @return array
152
     */
153 37
    public function wrapperVariables(): array
154
    {
155
        return [
156 37
            $this->_iv,
157 37
            $this->encryptionKey(),
158 36
            $this->_cipher,
159
        ];
160
    }
161
162
    /**
163
     * Generate a new key.
164
     *
165
     * @param int $bytes Size of key in bytes
166
     *
167
     * @throws Exception
168
     * @throws InvalidKeyLengthException
169
     *
170
     * @return string
171
     */
172 31
    public static function create(int $bytes = 32): string
173
    {
174 31
        if ($bytes < 32) {
175 1
            throw new InvalidKeyLengthException();
176
        }
177
178 31
        return base64_encode(random_bytes($bytes));
179
    }
180
}
181