Completed
Pull Request — master (#237)
by
unknown
04:26
created

OpenSSL::encodeBase64()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
cc 1
eloc 2
nc 1
nop 1
dl 0
loc 4
ccs 0
cts 0
cp 0
crap 2
rs 10
c 0
b 0
f 0
1
<?php
2
namespace phpbu\App\Cli\Executable;
3
4
use phpbu\App\Cli\Executable;
5
use phpbu\App\Exception;
6
use SebastianFeldmann\Cli\CommandLine;
7
use SebastianFeldmann\Cli\Command\Executable as Cmd;
8
9
/**
10
 * OpenSSL executable class.
11
 *
12
 * @package    phpbu
13
 * @subpackage Backup
14
 * @author     Sebastian Feldmann <[email protected]>
15
 * @copyright  Sebastian Feldmann <[email protected]>
16
 * @license    https://opensource.org/licenses/MIT The MIT License (MIT)
17
 * @link       http://phpbu.de/
18
 * @since      Class available since Release 2.1.6
19
 */
20
class OpenSSL extends Abstraction implements Executable
21
{
22
    use OptionMasker;
23
24
    /**
25
     * Encryption modes
26
     */
27
    const MODE_CERT = 'smime';
28
    const MODE_PASS = 'enc';
29
30
    /**
31
     * Actions
32
     */
33
    const ACTION_ENCRYPT = 'e';
34
    const ACTION_DECRYPT = 'd';
35
36
    /**
37
     * Use password or key
38
     *
39
     * @var string
40
     */
41
    private $mode;
42
43
    /**
44
     * Encryption or decryption
45
     *
46
     * @var string
47
     */
48
    private $action;
49
50
    /**
51
     * File to encrypt
52
     *
53
     * @var string
54
     */
55
    private $sourceFile;
56
57
    /**
58
     * SSL Cert file
59
     *
60
     * @var string
61
     */
62
    private $certFile;
63
64
    /**
65
     * Password
66
     *
67
     * @var string
68
     */
69
    private $password;
70
71
    /**
72
     * Algorithm to use
73
     *
74
     * @var string
75
     */
76
    private $algorithm;
77
78
    /**
79
     * Use base64 encoding
80
     *
81
     * @var boolean
82
     */
83
    private $base64;
84
85
    /**
86
     * Path to the encrypted file
87
     *
88
     * @var string
89
     */
90
    private $targetFile;
91
92
    /**
93
     * List of available algorithms
94
     *
95
     * @var array
96
     */
97
    private $availableAlgorithms = [
98
        'enc'   => [
99
            'aes-128-cbc'  => true,
100
            'aes-128-ecb'  => true,
101
            'aes-192-cbc'  => true,
102
            'aes-192-ecb'  => true,
103
            'aes-256-cbc'  => true,
104
            'aes-256-ecb'  => true,
105
            'base64'       => true,
106
            'bf'           => true,
107
            'bf-cbc'       => true,
108
            'bf-cfb'       => true,
109
            'bf-ecb'       => true,
110
            'bf-ofb'       => true,
111
            'cast'         => true,
112
            'cast-cbc'     => true,
113
            'cast5-cbc'    => true,
114
            'cast5-cfb'    => true,
115
            'cast5-ecb'    => true,
116
            'cast5-ofb'    => true,
117
            'des'          => true,
118
            'des-cbc'      => true,
119
            'des-cfb'      => true,
120
            'des-ecb'      => true,
121
            'des-ede'      => true,
122
            'des-ede-cbc'  => true,
123
            'des-ede-cfb'  => true,
124
            'des-ede-ofb'  => true,
125
            'des-ede3'     => true,
126
            'des-ede3-cbc' => true,
127
            'des-ede3-cfb' => true,
128
            'des-ede3-ofb' => true,
129
            'des-ofb'      => true,
130
            'des3'         => true,
131
            'desx'         => true,
132
            'rc2'          => true,
133
            'rc2-40-cbc'   => true,
134
            'rc2-64-cbc'   => true,
135
            'rc2-cbc'      => true,
136
            'rc2-cfb'      => true,
137
            'rc2-ecb'      => true,
138
            'rc2-ofb'      => true,
139
            'rc4'          => true,
140
            'rc4-40'       => true,
141
            'rc5'          => true,
142
            'rc5-cbc'      => true,
143
            'rc5-cfb'      => true,
144
            'rc5-ecb'      => true,
145
            'rc5-ofb'      => true,
146
            'seed'         => true,
147
            'seed-cbc'     => true,
148
            'seed-cfb'     => true,
149
            'seed-ecb'     => true,
150
            'seed-ofb'     => true,
151
        ],
152
        'smime' => [
153
            'des3'    => true,
154
            'des'     => true,
155
            'seed'    => true,
156
            'rc2-40'  => true,
157
            'rc2-64'  => true,
158
            'rc2-128' => true,
159
            'aes128'  => true,
160
            'aes192'  => true,
161
            'aes256'  => true,
162
        ]
163
    ];
164
165
    /**
166
     * Keep the not encrypted file
167
     *
168
     * @var bool
169
     */
170
    private $deleteSource = true;
171
172
    /**
173
     * Constructor
174
     *
175
     * @param string $path
176
     */
177 19
    public function __construct(string $path = '')
178
    {
179 19
        $this->setup('openssl', $path);
180 19
        $this->setMaskCandidates(['password']);
181 19
    }
182
183
    /**
184
     * Encrypt a file
185
     *
186
     * @param  string $file
187
     * @return \phpbu\App\Cli\Executable\OpenSSL
188
     */
189 11
    public function encryptFile(string $file): OpenSSL
190
    {
191 11
        $this->action     = self::ACTION_ENCRYPT;
192 11
        $this->sourceFile = $file;
193 11
        $this->targetFile = $file . '.enc';
194 11
        return $this;
195
    }
196
197
    /**
198
     * Encrypt a file
199
     *
200
     * @param  string $file
201
     * @return \phpbu\App\Cli\Executable\OpenSSL
202
     */
203 3
    public function decryptFile(string $file): OpenSSL
204
    {
205 3
        $this->action     = self::ACTION_DECRYPT;
206 3
        $this->sourceFile = $file . '.enc';
207 3
        $this->targetFile = $file;
208 3
        return $this;
209
    }
210
211
    /**
212
     * Delete the uncrypted data
213
     *
214
     * @param  boolean $bool
215
     * @return \phpbu\App\Cli\Executable\OpenSSL
216
     */
217 9
    public function deleteSource(bool $bool): OpenSSL
218
    {
219 9
        $this->deleteSource = $bool;
220 9
        return $this;
221
    }
222
223
    /**
224
     * Password to use for encryption
225
     *
226
     * @param  string $password
227
     * @return \phpbu\App\Cli\Executable\OpenSSL
228
     * @throws \phpbu\App\Exception
229
     */
230 11
    public function usePassword(string $password): OpenSSL
231
    {
232 11
        if (self::MODE_CERT === $this->mode) {
233 1
            throw new Exception('Cert file already set');
234
        }
235 10
        $this->mode = self::MODE_PASS;
236 10
        $this->password = $password;
237 10
        return $this;
238
    }
239
240
    /**
241
     * Set algorithm to use
242
     *
243
     * @param  string $algorithm
244
     * @return \phpbu\App\Cli\Executable\OpenSSL
245
     * @throws \phpbu\App\Exception
246
     */
247 14
    public function useAlgorithm(string $algorithm): OpenSSL
248
    {
249 14
        if (null === $this->mode) {
250 1
            throw new Exception('choose mode first, password or cert');
251
        }
252 13
        if (!isset($this->availableAlgorithms[$this->mode][$algorithm])) {
253 1
            throw new Exception('invalid algorithm');
254
        }
255 12
        $this->algorithm = $algorithm;
256 12
        return $this;
257
    }
258
259
    public function isUsingWeakAlgorithm(): bool
260
    {
261
        if (null === $this->algorithm) {
262
            throw new Exception('algorithm is not set');
263
        }
264
265 4
        return isset($this->weakAlgorithms[$this->algorithm]);
0 ignored issues
show
Bug Best Practice introduced by
The property weakAlgorithms does not exist on phpbu\App\Cli\Executable\OpenSSL. Did you maybe forget to declare it?
Loading history...
266
    }
267 4
268 4
    /**
269
     * Use base64 encoding
270
     *
271
     * @param bool $encode
272
     * @return \phpbu\App\Cli\Executable\OpenSSL
273
     */
274
    public function encodeBase64(bool $encode): OpenSSL
275
    {
276
        $this->base64 = $encode;
277
        return $this;
278 7
    }
279
280 7
    /**
281 1
     * Public key to use
282
     *
283 6
     * @param  string $file
284 6
     * @return \phpbu\App\Cli\Executable\OpenSSL
285 6
     * @throws \phpbu\App\Exception
286
     */
287
    public function useSSLCert(string $file): OpenSSL
288
    {
289
        if (self::MODE_PASS === $this->mode) {
290
            throw new Exception('Password already set');
291
        }
292
        $this->mode = self::MODE_CERT;
293
        $this->certFile = $file;
294 15
        return $this;
295
    }
296 15
297 1
    /**
298
     * OpenSSL CommandLine generator
299 14
     *
300 1
     * @return \SebastianFeldmann\Cli\CommandLine
301
     * @throws \phpbu\App\Exception
302 13
     */
303 1
    protected function createCommandLine(): CommandLine
304
    {
305
        if (empty($this->sourceFile)) {
306 12
            throw new Exception('file is missing');
307 12
        }
308
        if (empty($this->mode)) {
309 12
            throw new Exception('one of \'password\' or \'cert\' is mandatory');
310
        }
311 12
        if (empty($this->algorithm)) {
312 12
            throw new Exception('no algorithm specified');
313
        }
314 12
315
        $process = new CommandLine();
316
        $cmd     = new Cmd($this->binary);
317
318
        $process->addCommand($cmd);
319
320
        $this->setOptions($cmd);
321
        $this->addDeleteCommand($process);
322 12
323
        return $process;
324 12
    }
325 5
326
    /**
327 7
     * Set the openssl command line options
328
     *
329 12
     * @param \SebastianFeldmann\Cli\Command\Executable $cmd
330
     */
331
    protected function setOptions(Cmd $cmd): void
332
    {
333
        if ($this->mode == self::MODE_CERT) {
334
            $this->setCertOptions($cmd);
335
        } else {
336 5
            $this->setPasswordOptions($cmd);
337
        }
338 5
    }
339 5
340 5
    /**
341 5
     * Set command line options for SSL cert encryption
342 5
     *
343 5
     * @param \SebastianFeldmann\Cli\Command\Executable $cmd
344 5
     */
345 5
    protected function setCertOptions(Cmd $cmd): void
346 5
    {
347
        $cmd->addOption('smime');
348
        $cmd->addOption('-' . ($this->action === 'e' ? 'encrypt' : 'decrypt'));
349
        $cmd->addOption('-' . $this->algorithm);
350
        $cmd->addOption('-binary');
351
        $cmd->addOption('-in', $this->sourceFile, ' ');
352
        $cmd->addOption('-out', $this->targetFile, ' ');
353 7
        $cmd->addOption('-outform DER');
354
        $cmd->addArgument($this->certFile);
355 7
    }
356
357 7
    /**
358 7
     * Set command line options for password encryption
359 7
     *
360 7
     * @param \SebastianFeldmann\Cli\Command\Executable $cmd
361 7
     */
362 7
    protected function setPasswordOptions(Cmd $cmd): void
363 7
    {
364 7
        $password = 'pass:' . $this->password;
365
366
        $cmd->addOption('enc');
367
        $cmd->addOption('-' . $this->action);
368
        $cmd->addOptionIfNotEmpty('-a', $this->base64, false);
369
        $cmd->addOption('-' . $this->algorithm);
370
        $cmd->addOption('-pass', $password, ' ');
371 12
        $cmd->addOption('-in', $this->sourceFile, ' ');
372
        $cmd->addOption('-out', $this->targetFile, ' ');
373 12
    }
374 8
375 8
    /**
376 8
     * Add the 'rm' command to remove the uncrypted file
377
     *
378 12
     * @param \SebastianFeldmann\Cli\CommandLine $process
379
     */
380
    protected function addDeleteCommand(CommandLine $process): void
381
    {
382
        if ($this->deleteSource) {
383
            $cmd = new Cmd('rm');
384
            $cmd->addArgument($this->sourceFile);
385
            $process->addCommand($cmd);
386
        }
387
    }
388
}
389