1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
/** |
4
|
|
|
* Cryptobase.php |
5
|
|
|
* |
6
|
|
|
* PHP version 5 |
7
|
|
|
* |
8
|
|
|
* @category Dcrypt |
9
|
|
|
* @package Dcrypt |
10
|
|
|
* @author Michael Meyer (mmeyer2k) <[email protected]> |
11
|
|
|
* @license http://opensource.org/licenses/MIT The MIT License (MIT) |
12
|
|
|
* @link https://github.com/mmeyer2k/dcrypt |
13
|
|
|
*/ |
14
|
|
|
|
15
|
|
|
namespace Dcrypt; |
16
|
|
|
|
17
|
|
|
/** |
18
|
|
|
* Provides functionality common to Dcrypt's block ciphers. |
19
|
|
|
* |
20
|
|
|
* @category Dcrypt |
21
|
|
|
* @package Dcrypt |
22
|
|
|
* @author Michael Meyer (mmeyer2k) <[email protected]> |
23
|
|
|
* @license http://opensource.org/licenses/MIT The MIT License (MIT) |
24
|
|
|
* @link https://github.com/mmeyer2k/dcrypt |
25
|
|
|
* @link https://apigen.ci/github/mmeyer2k/dcrypt/namespace-Dcrypt.html |
26
|
|
|
*/ |
27
|
|
|
class Cryptobase |
28
|
|
|
{ |
29
|
|
|
|
30
|
|
|
/** |
31
|
|
|
* Create a message authentication checksum. |
32
|
|
|
* |
33
|
|
|
* @param string $cyphertext Cyphertext that needs a check sum. |
34
|
|
|
* @param string $iv Initialization vector. |
35
|
|
|
* @param string $key HMAC key |
36
|
|
|
* @param string $cipher Mcrypt cipher |
37
|
|
|
* @param string $mode Mcrypt mode |
38
|
|
|
* @param string $algo Hashing algorithm to use for internal operations |
39
|
|
|
* |
40
|
|
|
* @return string |
41
|
|
|
*/ |
42
|
6 |
|
protected static function checksum($cyphertext, $iv, $key, $cipher = 'rijndael-128', $mode = 'cbc', $algo = 'sha256') |
43
|
|
|
{ |
44
|
|
|
// Prevent potentially large string concat by hmac-ing the cyphertext |
45
|
|
|
// by itself... |
46
|
6 |
|
$sum = \hash_hmac($algo, $cyphertext, $key, true); |
47
|
|
|
|
48
|
|
|
// ... then hash other elements with previous hmac and return |
49
|
6 |
|
return \hash_hmac($algo, $sum . $iv . $mode . $cipher, $key, true); |
50
|
|
|
} |
51
|
|
|
|
52
|
|
|
/** |
53
|
|
|
* This will normalize a hash to a certain length by extending it if |
54
|
|
|
* too short and truncating it if too long. This ensures that any |
55
|
|
|
* hash algo will work with any combination of other settings. However, |
56
|
|
|
* it is probably best to make sure that the keysize and algo size |
57
|
|
|
* are identical so that the input hash passes through unchanged. |
58
|
|
|
* |
59
|
|
|
* @param string $hash Hash to be normalized |
60
|
|
|
* @param int $size Size of the desired output hash, in bytes |
61
|
|
|
* @param string $algo Hashing algorithm to use for internal operations |
62
|
|
|
* |
63
|
|
|
* @return string |
64
|
|
|
*/ |
65
|
6 |
|
protected static function hashNormalize($hash, $size, $algo) |
66
|
|
|
{ |
67
|
|
|
// Extend hash if too short |
68
|
6 |
|
while (Str::strlen($hash) < $size) { |
69
|
1 |
|
$hash .= \hash($algo, $hash, true); |
70
|
1 |
|
} |
71
|
|
|
|
72
|
|
|
// Truncate to specified number of bytes (if needed) and return |
73
|
6 |
|
return Str::substr($hash, 0, $size); |
74
|
|
|
} |
75
|
|
|
|
76
|
|
|
/** |
77
|
|
|
* Determine the length of the output of a given hash algorithm in bytes. |
78
|
|
|
* |
79
|
|
|
* @param string $algo Name of algorithm to look up |
80
|
|
|
* |
81
|
|
|
* @return int |
82
|
|
|
*/ |
83
|
10 |
|
protected static function hashSize($algo) |
84
|
|
|
{ |
85
|
10 |
|
return Str::strlen(\hash($algo, 'hash me', true)); |
86
|
|
|
} |
87
|
|
|
|
88
|
|
|
/** |
89
|
|
|
* Transform password into key and perform iterative HMAC |
90
|
|
|
* |
91
|
|
|
* @param string $password Encryption key |
92
|
|
|
* @param string $iv Initialization vector |
93
|
|
|
* @param int $cost Number of HMAC iterations to perform on key |
94
|
|
|
* @param string $cipher Mcrypt cipher |
95
|
|
|
* @param string $mode Mcrypt block mode |
96
|
|
|
* @param string $algo Hashing algorithm to use for internal operations |
97
|
|
|
* |
98
|
|
|
* @return string |
99
|
|
|
*/ |
100
|
6 |
|
protected static function key($password, $iv, $cost, $cipher = 'rijndael-128', $mode = 'cbc', $algo = 'sha256') |
101
|
|
|
{ |
102
|
|
|
// This if statement allows the usage of the Openssl library without |
103
|
|
|
// the need to have the mcrypt plugin installed at all. |
104
|
6 |
|
if ($mode === 'cbc' && $cipher === 'rijndael-128') { |
105
|
6 |
|
$keysize = 32; |
106
|
6 |
|
} else { |
107
|
1 |
|
$keysize = \mcrypt_get_key_size($cipher, $mode); |
108
|
|
|
} |
109
|
|
|
|
110
|
|
|
// Perform key derivation |
111
|
6 |
|
$key = Hash::ihmac($password . $iv, $password, $cost, $algo); |
112
|
|
|
|
113
|
|
|
// Return hash normalized to key length |
114
|
6 |
|
return self::hashNormalize($key, $keysize, $algo); |
115
|
|
|
} |
116
|
|
|
|
117
|
|
|
protected static function checksumVerify($calculated, $supplied) |
118
|
|
|
{ |
119
|
|
|
if (!Str::equal($calculated, $supplied)) { |
120
|
|
|
$e = 'Decryption can not proceed due to invalid cyphertext checksum.'; |
121
|
|
|
throw new \InvalidArgumentException($e); |
122
|
|
|
} |
123
|
|
|
} |
124
|
|
|
|
125
|
|
|
} |
126
|
|
|
|