Completed
Pull Request — master (#32)
by Michael
01:21
created

OpensslKey::authenticationKey()   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
c 0
b 0
f 0
ccs 2
cts 2
cp 1
rs 10
cc 1
nc 1
nop 0
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 49
    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 49
        $this->_key = \base64_decode($key, true);
83
84
        // If key was not proper base64, bail out
85 49
        if ($this->_key === false) {
86 9
            throw new InvalidKeyEncodingException();
87
        }
88
89
        // If key was to short, bail out
90 40
        if (Str::strlen($this->_key) < 32) {
91
            throw new InvalidKeyLengthException();
92
        }
93
94
        // Store algo in object
95 40
        $this->_algo = $algo;
96
97
        // Store init vector in object
98 40
        $this->_iv = $iv;
99
100
        // Store the cipher name
101 40
        $this->_cipher = $cipher;
102 40
    }
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 secure read only access to private properties.
150
     *
151
     * @param string $name
152
     *
153
     * @throws Exception
154
     *
155
     * @return mixed
156
     */
157 38
    public function __get(string $name): string
158
    {
159 38
        if (!in_array($name, ['iv', 'cipher'])) {
160 1
            throw new Exceptions\InvalidPropertyAccessException();
161
        }
162
163 37
        return $this->{"_{$name}"};
164
    }
165
166
    /**
167
     * Generate a new key.
168
     *
169
     * @param int $bytes Size of key in bytes
170
     *
171
     * @throws Exception
172
     * @throws InvalidKeyLengthException
173
     *
174
     * @return string
175
     */
176 32
    public static function create(int $bytes = 32): string
177
    {
178 32
        if ($bytes < 32) {
179 1
            throw new InvalidKeyLengthException();
180
        }
181
182 32
        return \base64_encode(\random_bytes($bytes));
183
    }
184
}
185