Completed
Pull Request — master (#33)
by Michael
01:22
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 49
    public function __construct(
76
        string $key,
0 ignored issues
show
Unused Code introduced by
The parameter $key is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
77
        string $algo,
0 ignored issues
show
Unused Code introduced by
The parameter $algo is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
78
        string $cipher,
0 ignored issues
show
Unused Code introduced by
The parameter $cipher is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
79
        string $iv
0 ignored issues
show
Unused Code introduced by
The parameter $iv is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
80
    ) {
81
        // Store args into the object
82 49
        [$this->_key, $this->_algo, $this->_cipher, $this->_iv] = func_get_args();
83
84
        // Attempt to base64 decode the key
85 49
        $this->_key = base64_decode($this->_key, true);
86
87
        // If key was not proper base64, bail out
88 49
        if ($this->_key === false) {
89 9
            throw new InvalidKeyEncodingException();
90
        }
91
92
        // If key was to short, bail out
93 40
        if (Str::strlen($this->_key) < 32) {
94
            throw new InvalidKeyLengthException();
95
        }
96 40
    }
97
98
    /**
99
     * Generate the authentication key.
100
     *
101
     * @return string
102
     */
103 37
    public function authenticationKey(): string
104
    {
105 37
        return $this->deriveKey(__FUNCTION__ . '|' . $this->_cipher);
106
    }
107
108
    /**
109
     * Generate the encryption key.
110
     *
111
     * @return string
112
     */
113 38
    public function encryptionKey(): string
114
    {
115 38
        return $this->deriveKey(__FUNCTION__ . '|' . $this->_cipher);
116
    }
117
118
    /**
119
     * Derive a key with differing info string parameters.
120
     *
121
     * @param string $info Info parameter to provide to hash_hkdf
122
     *
123
     * @return string
124
     */
125 40
    public function deriveKey(string $info): string
126
    {
127 40
        return hash_hkdf($this->_algo, $this->_key, 0, $info, $this->_iv);
128
    }
129
130
    /**
131
     * Calculates a given message HMAC.
132
     *
133
     * @param string $message
134
     *
135
     * @return string
136
     */
137 37
    public function messageChecksum(string $message): string
138
    {
139 37
        return hash_hmac($this->_algo, $message, $this->authenticationKey(), true);
140
    }
141
142
    /**
143
     * Allows read only access to the internal variables needed by the openssl wrapper.
144
     *
145
     * @return array
146
     */
147 38
    public function wrapperVariables(): array
148
    {
149
        return [
150 38
            $this->_iv,
151 38
            $this->encryptionKey(),
152 37
            $this->_cipher,
153
        ];
154
    }
155
156
    /**
157
     * Generate a new key.
158
     *
159
     * @param int $bytes Size of key in bytes
160
     *
161
     * @throws Exception
162
     * @throws InvalidKeyLengthException
163
     *
164
     * @return string
165
     */
166 32
    public static function create(int $bytes = 32): string
167
    {
168 32
        if ($bytes < 32) {
169 1
            throw new InvalidKeyLengthException();
170
        }
171
172 32
        return base64_encode(random_bytes($bytes));
173
    }
174
}
175