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

OpensslKey::__get()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 8

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 2

Importance

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