Completed
Push — master ( 6a1fad...afb84c )
by Sebastian
05:39
created

OpenSSL::deleteUncrypted()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 5
ccs 0
cts 0
cp 0
rs 9.4285
cc 1
eloc 3
nc 1
nop 1
crap 2
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
     * Use password or key
32
     *
33
     * @var string
34
     */
35
    private $mode;
36
37
    /**
38
     * File to encrypt
39
     *
40
     * @var string
41
     */
42
    private $sourceFile;
43
44
    /**
45
     * SSL Cert file
46
     *
47
     * @var string
48
     */
49
    private $certFile;
50
51
    /**
52
     * Password
53
     *
54
     * @var string
55
     */
56
    private $password;
57
58
    /**
59
     * Algorithm to use
60
     *
61
     * @var string
62
     */
63
    private $algorithm;
64
65
    /**
66
     * Use base64 encoding
67
     *
68
     * @var boolean
69
     */
70
    private $base64;
71
72
    /**
73
     * Path to the encrypted file
74
     *
75
     * @var string
76
     */
77
    private $targetFile;
78
79
    /**
80
     * List of available algorithms
81
     *
82
     * @var array
83
     */
84
    private $availableAlgorithms = [
85
        'enc'   => [
86
            'aes-128-cbc'  => true,
87
            'aes-128-ecb'  => true,
88
            'aes-192-cbc'  => true,
89
            'aes-192-ecb'  => true,
90
            'aes-256-cbc'  => true,
91
            'aes-256-ecb'  => true,
92
            'base64'       => true,
93
            'bf'           => true,
94
            'bf-cbc'       => true,
95
            'bf-cfb'       => true,
96
            'bf-ecb'       => true,
97
            'bf-ofb'       => true,
98
            'cast'         => true,
99
            'cast-cbc'     => true,
100
            'cast5-cbc'    => true,
101
            'cast5-cfb'    => true,
102
            'cast5-ecb'    => true,
103
            'cast5-ofb'    => true,
104
            'des'          => true,
105
            'des-cbc'      => true,
106
            'des-cfb'      => true,
107
            'des-ecb'      => true,
108
            'des-ede'      => true,
109
            'des-ede-cbc'  => true,
110
            'des-ede-cfb'  => true,
111
            'des-ede-ofb'  => true,
112
            'des-ede3'     => true,
113
            'des-ede3-cbc' => true,
114
            'des-ede3-cfb' => true,
115
            'des-ede3-ofb' => true,
116
            'des-ofb'      => true,
117
            'des3'         => true,
118
            'desx'         => true,
119
            'rc2'          => true,
120
            'rc2-40-cbc'   => true,
121
            'rc2-64-cbc'   => true,
122
            'rc2-cbc'      => true,
123
            'rc2-cfb'      => true,
124
            'rc2-ecb'      => true,
125
            'rc2-ofb'      => true,
126
            'rc4'          => true,
127
            'rc4-40'       => true,
128
            'rc5'          => true,
129
            'rc5-cbc'      => true,
130
            'rc5-cfb'      => true,
131
            'rc5-ecb'      => true,
132
            'rc5-ofb'      => true,
133
            'seed'         => true,
134
            'seed-cbc'     => true,
135
            'seed-cfb'     => true,
136
            'seed-ecb'     => true,
137
            'seed-ofb'     => true,
138
        ],
139
        'smime' => [
140
            'des3'    => true,
141
            'des'     => true,
142
            'seed'    => true,
143
            'rc2-40'  => true,
144
            'rc2-64'  => true,
145
            'rc2-128' => true,
146
            'aes128'  => true,
147
            'aes192'  => true,
148
            'aes256'  => true,
149
        ]
150
    ];
151
152
    /**
153
     * Keep the not encrypted file
154
     *
155
     * @var boolean
156
     */
157
    private $deleteUncrypted = true;
158
159
    /**
160 13
     * Constructor.
161
     *
162 13
     * @param string $path
163 13
     */
164 13
    public function __construct(string $path = '')
165
    {
166
        $this->setup('openssl', $path);
167
        $this->setMaskCandidates(['password']);
168
    }
169
170
    /**
171
     * Encrypt a file.
172
     *
173 8
     * @param  string $file
174
     * @return \phpbu\App\Cli\Executable\OpenSSL
175 8
     * @throws Exception
176 8
     */
177 8
    public function encryptFile(string $file) : OpenSSL
178
    {
179
        $this->sourceFile = $file;
180
        $this->targetFile = $file . '.enc';
181
        return $this;
182
    }
183
184
    /**
185
     * Delete the uncrypted data.
186 3
     *
187
     * @param  boolean $bool
188 3
     * @return \phpbu\App\Cli\Executable\OpenSSL
189 3
     */
190
    public function deleteUncrypted(bool $bool) : OpenSSL
191
    {
192
        $this->deleteUncrypted = $bool;
193
        return $this;
194
    }
195
196
    /**
197
     * Password to use for encryption.
198
     *
199 8
     * @param  string $password
200
     * @return \phpbu\App\Cli\Executable\OpenSSL
201 8
     * @throws \phpbu\App\Exception
202 1
     */
203 View Code Duplication
    public function usePassword(string $password) : OpenSSL
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
204 7
    {
205 7
        if (self::MODE_CERT === $this->mode) {
206 7
            throw new Exception('Cert file already set');
207
        }
208
        $this->mode = self::MODE_PASS;
209
        $this->password = $password;
210
        return $this;
211
    }
212
213
    /**
214
     * Set algorithm to use.
215
     *
216 8
     * @param  string $algorithm
217
     * @return \phpbu\App\Cli\Executable\OpenSSL
218 8
     * @throws \phpbu\App\Exception
219 1
     */
220
    public function useAlgorithm(string $algorithm) : OpenSSL
221 7
    {
222 1
        if (null === $this->mode) {
223
            throw new Exception('choose mode first, password or cert');
224 6
        }
225 6
        if (!isset($this->availableAlgorithms[$this->mode][$algorithm])) {
226
            throw new Exception('invalid algorithm');
227
        }
228
        $this->algorithm = $algorithm;
229
        return $this;
230
    }
231
232
    /**
233
     * Use base64 encoding
234 2
     *
235
     * @param bool $encode
236 2
     * @return \phpbu\App\Cli\Executable\OpenSSL
237 2
     */
238
    public function encodeBase64(bool $encode) : OpenSSL
239
    {
240
        $this->base64 = $encode;
241
        return $this;
242
    }
243
244
    /**
245
     * Public key to use.
246
     *
247 4
     * @param  string $file
248
     * @return \phpbu\App\Cli\Executable\OpenSSL
249 4
     * @throws \phpbu\App\Exception
250 1
     */
251 View Code Duplication
    public function useSSLCert(string $file) : OpenSSL
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
252 3
    {
253 3
        if (self::MODE_PASS === $this->mode) {
254 3
            throw new Exception('Password already set');
255
        }
256
        $this->mode = self::MODE_CERT;
257
        $this->certFile = $file;
258
        return $this;
259
    }
260
261
    /**
262
     * OpenSSL CommandLine generator.
263 9
     *
264
     * @return \SebastianFeldmann\Cli\CommandLine
265 9
     * @throws \phpbu\App\Exception
266 1
     */
267
    protected function createCommandLine() : CommandLine
268 8
    {
269 1
        if (empty($this->sourceFile)) {
270
            throw new Exception('file is missing');
271 7
        }
272 1
        if (empty($this->mode)) {
273
            throw new Exception('one of \'password\' or \'cert\' is mandatory');
274
        }
275 6
        if (empty($this->algorithm)) {
276 6
            throw new Exception('no algorithm specified');
277 6
        }
278
279
        $process = new CommandLine();
280 6
        $cmd     = new Cmd($this->binary);
281 6
282
        $process->addCommand($cmd);
283 6
284
        $this->setOptions($cmd);
285 6
        $this->addDeleteCommand($process);
286
287 6
        return $process;
288
    }
289 6
290
    /**
291
     * Set the openssl command line options
292
     *
293
     * @param \SebastianFeldmann\Cli\Command\Executable $cmd
294
     */
295
    protected function setOptions(Cmd $cmd)
296
    {
297 6
        if ($this->mode == self::MODE_CERT) {
298
            $this->setCertOptions($cmd);
299 6
        } else {
300 2
            $this->setPasswordOptions($cmd);
301 2
        }
302 4
    }
303
304 6
    /**
305
     * Set command line options for SSL cert encryption.
306
     *
307
     * @param \SebastianFeldmann\Cli\Command\Executable $cmd
308
     */
309
    protected function setCertOptions(Cmd $cmd)
310
    {
311 2
        $cmd->addOption('smime');
312
        $cmd->addOption('-encrypt');
313 2
        $cmd->addOption('-' . $this->algorithm);
314 2
        $cmd->addOption('-binary');
315 2
        $cmd->addOption('-in', $this->sourceFile, ' ');
316 2
        $cmd->addOption('-out', $this->targetFile, ' ');
317 2
        $cmd->addOption('-outform DER');
318 2
        $cmd->addArgument($this->certFile);
319 2
    }
320 2
321 2
    /**
322
     * Set command line options for password encryption
323
     *
324
     * @param \SebastianFeldmann\Cli\Command\Executable $cmd
325
     */
326
    protected function setPasswordOptions(Cmd $cmd)
327
    {
328 4
        $password = 'pass:' . $this->password;
329
330 4
        $cmd->addOption('enc');
331
        $cmd->addOption('-e');
332 4
        $cmd->addOptionIfNotEmpty('-a', $this->base64, false);
333 4
        $cmd->addOption('-' . $this->algorithm);
334 4
        $cmd->addOption('-pass', $password, ' ');
335 4
        $cmd->addOption('-in', $this->sourceFile, ' ');
336 4
        $cmd->addOption('-out', $this->targetFile, ' ');
337 4
    }
338 4
339 4
    /**
340
     * Add the 'rm' command to remove the uncrypted file.
341
     *
342
     * @param \SebastianFeldmann\Cli\CommandLine $process
343
     */
344
    protected function addDeleteCommand(CommandLine $process)
345
    {
346 6
        if ($this->deleteUncrypted) {
347
            $cmd = new Cmd('rm');
348 6
            $cmd->addArgument($this->sourceFile);
349 5
            $process->addCommand($cmd);
350 5
        }
351 5
    }
352
}
353