Completed
Pull Request — master (#32)
by Michael
08:05 queued 06:53
created

OpensslKey::__get()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 8

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 2.0625

Importance

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