1
|
|
|
<?php |
2
|
|
|
namespace phpbu\App\Backup\Crypter; |
3
|
|
|
|
4
|
|
|
use phpbu\App\Backup\Restore\Plan; |
5
|
|
|
use phpbu\App\Backup\Target; |
6
|
|
|
use phpbu\App\Cli\Executable; |
7
|
|
|
use phpbu\App\Result; |
8
|
|
|
use phpbu\App\Util; |
9
|
|
|
|
10
|
|
|
/** |
11
|
|
|
* OpenSSL crypter class |
12
|
|
|
* |
13
|
|
|
* @package phpbu |
14
|
|
|
* @subpackage Backup |
15
|
|
|
* @author Sebastian Feldmann <[email protected]> |
16
|
|
|
* @copyright Sebastian Feldmann <[email protected]> |
17
|
|
|
* @license https://opensource.org/licenses/MIT The MIT License (MIT) |
18
|
|
|
* @link https://phpbu.de/ |
19
|
|
|
* @since Class available since Release 2.1.6 |
20
|
|
|
*/ |
21
|
|
|
class OpenSSL extends Abstraction implements Simulator, Restorable |
22
|
|
|
{ |
23
|
|
|
/** |
24
|
|
|
* Path to mcrypt command |
25
|
|
|
* |
26
|
|
|
* @var string |
27
|
|
|
*/ |
28
|
|
|
private $pathToOpenSSL; |
29
|
|
|
|
30
|
|
|
/** |
31
|
|
|
* Key file |
32
|
|
|
* |
33
|
|
|
* @var string |
34
|
|
|
*/ |
35
|
|
|
private $certFile; |
36
|
|
|
|
37
|
|
|
/** |
38
|
|
|
* Algorithm to use |
39
|
|
|
* |
40
|
|
|
* @var string |
41
|
|
|
*/ |
42
|
|
|
private $algorithm; |
43
|
|
|
|
44
|
|
|
/** |
45
|
|
|
* Password to use |
46
|
|
|
* |
47
|
|
|
* @var string |
48
|
|
|
*/ |
49
|
|
|
private $password; |
50
|
|
|
|
51
|
|
|
/** |
52
|
|
|
* Keep the not encrypted file |
53
|
|
|
* |
54
|
|
|
* @var boolean |
55
|
|
|
*/ |
56
|
|
|
private $keepUncrypted; |
57
|
|
|
|
58
|
|
|
private $weakAlgorithms = [ |
59
|
|
|
'rc2' => true, |
60
|
|
|
'rc2-40' => true, |
61
|
|
|
'rc2-64' => true, |
62
|
|
|
'rc2-128' => true, |
63
|
|
|
'rc2-40-cbc' => true, |
64
|
10 |
|
'rc2-64-cbc' => true, |
65
|
|
|
'rc2-cbc' => true, |
66
|
10 |
|
'rc2-cfb' => true, |
67
|
1 |
|
'rc2-ecb' => true, |
68
|
|
|
'rc2-ofb' => true, |
69
|
9 |
|
'rc4' => true, |
70
|
9 |
|
'rc4-40' => true, |
71
|
1 |
|
'des' => true, |
72
|
|
|
'des-cbc' => true, |
73
|
|
|
'des-cfb' => true, |
74
|
8 |
|
'des-ecb' => true, |
75
|
8 |
|
'des-ede' => true, |
76
|
8 |
|
'des-ede-cbc' => true, |
77
|
8 |
|
'des-ede-cfb' => true, |
78
|
8 |
|
'des-ede-ofb' => true, |
79
|
8 |
|
'des-ede3' => true, |
80
|
|
|
'des-ede3-cbc' => true, |
81
|
|
|
'des-ede3-cfb' => true, |
82
|
|
|
'des-ede3-ofb' => true, |
83
|
|
|
'des-ofb' => true, |
84
|
|
|
'des3' => true, |
85
|
|
|
'desx' => true, |
86
|
|
|
'seed' => true, |
87
|
1 |
|
'seed-cbc' => true, |
88
|
|
|
'seed-cfb' => true, |
89
|
1 |
|
'seed-ecb' => true, |
90
|
|
|
'seed-ofb' => true, |
91
|
|
|
]; |
92
|
|
|
|
93
|
|
|
/** |
94
|
|
|
* @inheritDoc |
95
|
|
|
*/ |
96
|
|
|
public function crypt(Target $target, Result $result) |
97
|
|
|
{ |
98
|
|
|
if ($this->isUsingWeakAlgorithm()) { |
99
|
2 |
|
$name = strtolower(get_class($this)); |
100
|
|
|
|
101
|
2 |
|
$result->warn($name . ': The ' . $this->algorithm . ' algorithm is considered weak'); |
102
|
2 |
|
} |
103
|
2 |
|
|
104
|
|
|
return parent::crypt($target, $result); |
|
|
|
|
105
|
|
|
} |
106
|
|
|
|
107
|
|
|
|
108
|
|
|
/** |
109
|
|
|
* @inheritDoc |
110
|
|
|
*/ |
111
|
|
|
public function simulate(Target $target, Result $result) |
112
|
5 |
|
{ |
113
|
|
|
if ($this->isUsingWeakAlgorithm()) { |
114
|
5 |
|
$name = strtolower(get_class($this)); |
115
|
|
|
|
116
|
|
|
$result->warn($name . ': The ' . $this->algorithm . ' algorithm is considered weak'); |
117
|
|
|
} |
118
|
|
|
|
119
|
|
|
return parent::simulate($target, $result); |
|
|
|
|
120
|
|
|
} |
121
|
|
|
|
122
|
|
|
public function isUsingWeakAlgorithm(): bool |
123
|
|
|
{ |
124
|
5 |
|
if (null === $this->algorithm) { |
125
|
|
|
throw new Exception('algorithm is not set'); |
126
|
5 |
|
} |
127
|
5 |
|
|
128
|
5 |
|
return isset($this->weakAlgorithms[$this->algorithm]); |
129
|
|
|
} |
130
|
5 |
|
|
131
|
|
|
/** |
132
|
|
|
* Setup |
133
|
|
|
* |
134
|
|
|
* @see \phpbu\App\Backup\Crypter |
135
|
|
|
* @param array $options |
136
|
|
|
* @throws Exception |
137
|
|
|
*/ |
138
|
|
|
public function setup(array $options = []) |
139
|
|
|
{ |
140
|
2 |
|
if (!Util\Arr::isSetAndNotEmptyString($options, 'algorithm')) { |
141
|
|
|
throw new Exception('openssl expects \'algorithm\''); |
142
|
2 |
|
} |
143
|
2 |
|
if (!Util\Arr::isSetAndNotEmptyString($options, 'password') |
144
|
2 |
|
&& !Util\Arr::isSetAndNotEmptyString($options, 'certFile')) { |
145
|
|
|
throw new Exception('openssl expects \'certFile\' or \'password\''); |
146
|
2 |
|
} |
147
|
|
|
|
148
|
|
|
$this->pathToOpenSSL = Util\Arr::getValue($options, 'pathToOpenSSL', ''); |
149
|
|
|
$this->keepUncrypted = Util\Str::toBoolean(Util\Arr::getValue($options, 'keepUncrypted', ''), false); |
150
|
|
|
$this->certFile = $this->toAbsolutePath(Util\Arr::getValue($options, 'certFile', '')); |
151
|
|
|
$this->algorithm = Util\Arr::getValue($options, 'algorithm', ''); |
152
|
|
|
$this->password = Util\Arr::getValue($options, 'password', ''); |
153
|
|
|
} |
154
|
|
|
|
155
|
|
|
/** |
156
|
7 |
|
* Return file suffix of encrypted target |
157
|
|
|
* |
158
|
7 |
|
* @see \phpbu\App\Backup\Crypter |
159
|
|
|
* @return string |
160
|
7 |
|
*/ |
161
|
4 |
|
public function getSuffix() : string |
162
|
|
|
{ |
163
|
3 |
|
return 'enc'; |
164
|
3 |
|
} |
165
|
|
|
|
166
|
7 |
|
/** |
167
|
|
|
* Decrypt the backup |
168
|
7 |
|
* |
169
|
|
|
* @param \phpbu\App\Backup\Target $target |
170
|
|
|
* @param \phpbu\App\Backup\Restore\Plan $plan |
171
|
|
|
* @throws \phpbu\App\Exception |
172
|
|
|
*/ |
173
|
|
|
public function restore(Target $target, Plan $plan) |
174
|
|
|
{ |
175
|
|
|
$executable = $this->createDecryptionOpenSSL($target); |
176
|
|
|
$plan->addDecryptionCommand($executable->getCommand()); |
177
|
|
|
} |
178
|
|
|
|
179
|
|
|
/** |
180
|
|
|
* Create the Executable to run the 'mcrypt' command |
181
|
|
|
* |
182
|
|
|
* @param \phpbu\App\Backup\Target $target |
183
|
|
|
* @return \phpbu\App\Cli\Executable |
184
|
|
|
* @throws \phpbu\App\Exception |
185
|
|
|
*/ |
186
|
|
|
protected function createExecutable(Target $target) : Executable |
187
|
|
|
{ |
188
|
|
|
return $this->createEncryptionOpenSSL($target); |
189
|
|
|
} |
190
|
|
|
|
191
|
|
|
/** |
192
|
|
|
* Create encryption OpenSSL |
193
|
|
|
* |
194
|
|
|
* @param \phpbu\App\Backup\Target $target |
195
|
|
|
* @return \phpbu\App\Cli\Executable\OpenSSL |
196
|
|
|
* @throws \phpbu\App\Exception |
197
|
|
|
*/ |
198
|
|
|
private function createEncryptionOpenSSL(Target $target): Executable\OpenSSL |
199
|
|
|
{ |
200
|
|
|
$executable = $this->createOpenSSL($target); |
201
|
|
|
$executable->encryptFile($target->getPathname()) |
202
|
|
|
->deleteSource(!$this->keepUncrypted); |
203
|
|
|
|
204
|
|
|
return $executable; |
205
|
|
|
} |
206
|
|
|
|
207
|
|
|
/** |
208
|
|
|
* Create decryption OpenSSL |
209
|
|
|
* |
210
|
|
|
* @param \phpbu\App\Backup\Target $target |
211
|
|
|
* @return \phpbu\App\Cli\Executable\OpenSSL |
212
|
|
|
* @throws \phpbu\App\Exception |
213
|
|
|
*/ |
214
|
|
|
private function createDecryptionOpenSSL(Target $target): Executable\OpenSSL |
215
|
|
|
{ |
216
|
|
|
$executable = $this->createOpenSSL($target); |
217
|
|
|
$executable->decryptFile($target->getPathname()) |
218
|
|
|
->deleteSource(false); |
219
|
|
|
|
220
|
|
|
return $executable; |
221
|
|
|
} |
222
|
|
|
|
223
|
|
|
/** |
224
|
|
|
* Setup an OpenSSL executable only thing missing is the decision of en or decryption |
225
|
|
|
* |
226
|
|
|
* @param \phpbu\App\Backup\Target $target |
227
|
|
|
* @return \phpbu\App\Cli\Executable\OpenSSL |
228
|
|
|
* @throws \phpbu\App\Exception |
229
|
|
|
*/ |
230
|
|
|
private function createOpenSSL(Target $target): Executable\OpenSSL |
|
|
|
|
231
|
|
|
{ |
232
|
|
|
$executable = new Executable\OpenSSL($this->pathToOpenSSL); |
233
|
|
|
// use key or password to encrypt |
234
|
|
|
if (!empty($this->certFile)) { |
235
|
|
|
$executable->useSSLCert($this->certFile); |
236
|
|
|
} else { |
237
|
|
|
$executable->usePassword($this->password) |
238
|
|
|
->encodeBase64(true); |
239
|
|
|
} |
240
|
|
|
$executable->useAlgorithm($this->algorithm); |
241
|
|
|
|
242
|
|
|
return $executable; |
243
|
|
|
} |
244
|
|
|
} |
245
|
|
|
|
This check looks for function or method calls that always return null and whose return value is used.
The method
getObject()
can return nothing but null, so it makes no sense to use the return value.The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.