Completed
Push — master ( 72f2d0...1a78ee )
by Christoper
04:21 queued 02:19
created

FileEncrypterTest::testSetMode()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 10
Code Lines 6

Duplication

Lines 10
Ratio 100 %

Importance

Changes 1
Bugs 0 Features 1
Metric Value
c 1
b 0
f 1
dl 10
loc 10
rs 9.4286
cc 1
eloc 6
nc 1
nop 0
1
<?php namespace Wubbajack\Tests;
2
3
use TypeError;
4
use Wubbajack\Encryption\EncryptedFile;
5
use Wubbajack\Encryption\Exceptions\DecryptException;
6
use Wubbajack\Encryption\Exceptions\EncryptException;
7
use Wubbajack\Encryption\FileEncrypter;
8
9
class FileEncrypterTest extends \PHPUnit_Framework_TestCase
10
{
11
12
    /**
13
     * @var FileEncrypter
14
     */
15
    protected $fileCrypt;
16
17
    /**
18
     * @var string
19
     */
20
    protected $default_key = '2ApWknyPwb4N8Hhv4zT34FvubrCTx0Sh';
21
22
    /**
23
     * @var string
24
     */
25
    protected $default_cipher = MCRYPT_RIJNDAEL_128;
26
27
    /**
28
     * @var string
29
     */
30
    protected $default_mode = MCRYPT_MODE_CBC;
31
32
    /**
33
     * @var string
34
     */
35
    protected $test_file;
36
37
    /**
38
     * @var string
39
     */
40
    protected $test_encrypted_file;
41
42
    /**
43
     * @var string
44
     */
45
    protected $test_decrypted_file;
46
47
    /**
48
     * Sets up the file encrypter
49
     */
50
    protected function setUp()
51
    {
52
        $this->fileCrypt = new FileEncrypter($this->default_key);
53
        $this->test_file = $this->createTestFile();
54
        $this->test_encrypted_file = __DIR__ .'/test.enc';
55
        $this->test_decrypted_file = __DIR__ .'/test.dec.json';
56
    }
57
58
    protected function tearDown()
59
    {
60
        $this->fileCrypt->setMode($this->default_mode);
61
        $this->fileCrypt->setCipher($this->default_cipher);
62
        $this->fileCrypt->setKey($this->default_key);
63
64
        $this->cleanupFiles();
65
    }
66
67
    /**
68
     * Tests whether the cipher is properly set and the block size is updated correctly
69
     */
70 View Code Duplication
    public function testSetCipher()
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...
71
    {
72
        $cipher = MCRYPT_TRIPLEDES;
73
        $this->fileCrypt->setCipher($cipher);
74
75
        $this->assertEquals($cipher, $this->readAttribute($this->fileCrypt, 'cipher'));
76
77
        $block_size = mcrypt_get_block_size($cipher, $this->readAttribute($this->fileCrypt, 'mode'));
78
        $this->assertEquals($block_size, $this->readAttribute($this->fileCrypt, 'block'));
79
    }
80
81
    /**
82
     * Tests whether the mode is set correctly and and the block size is updated accordingly
83
     */
84 View Code Duplication
    public function testSetMode()
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...
85
    {
86
        $mode = MCRYPT_MODE_OFB;
87
        $this->fileCrypt->setMode($mode);
88
89
        $this->assertEquals($mode, $this->readAttribute($this->fileCrypt, 'mode'));
90
91
        $block_size = mcrypt_get_block_size($this->readAttribute($this->fileCrypt, 'cipher'), $mode);
92
        $this->assertEquals($block_size, $this->readAttribute($this->fileCrypt, 'block'));
93
    }
94
95
    /**
96
     * Tests the setting of the key
97
     */
98
    public function testSetKey()
99
    {
100
        $key = bin2hex(openssl_random_pseudo_bytes(16));
101
        $this->fileCrypt->setKey($key);
102
103
        $this->assertEquals($key, $this->readAttribute($this->fileCrypt, 'key'));
104
    }
105
106
    /**
107
     * Test encryption
108
     *
109
     * @throws \Wubbajack\Encryption\Exceptions\EncryptException
110
     */
111
    public function testEncrypt()
112
    {
113
        $this->assertInstanceOf(
114
            EncryptedFile::class,
115
            $this->fileCrypt->encrypt($this->test_file, $this->test_encrypted_file)
116
        );
117
118
        // Try testing with a non-existent source file
119
        $this->setExpectedException(EncryptException::class);
120
        $this->fileCrypt->encrypt(__DIR__ .'/test.test', __DIR__ .'/test.test.enc');
121
    }
122
123
    /**
124
     * Test decryption
125
     * @expectedException TypeError
126
     */
127
    public function testDecrypt()
128
    {
129
        $encryptedFile = $this->fileCrypt->encrypt($this->test_file, $this->test_encrypted_file);
130
131
        $this->fileCrypt->decrypt($encryptedFile, $this->test_decrypted_file);
132
133
        // Test if the decrypted file exists
134
        $this->assertTrue(file_exists($this->test_decrypted_file));
135
136
        // Test if the checksum equals the original file
137
        $this->assertEquals($encryptedFile->getChecksum(), sha1_file($this->test_decrypted_file));
138
139
        // Test if the decrypted file contains the same content as the original
140
        $this->assertEquals(file_get_contents($this->test_file), file_get_contents($this->test_decrypted_file));
141
142
        // Test decryption of encrypted file with incorrect wrong IV
143
        try {
144
            $invalidEncryptedFile = EncryptedFile::create(
145
                '2394qsf3-f9',
146
                $encryptedFile->getChecksum(),
147
                $encryptedFile->getPadding(),
148
                $encryptedFile->getFile()->getRealPath()
149
            );
150
            $this->fileCrypt->decrypt($invalidEncryptedFile, $this->test_decrypted_file);
151
            $this->fail('No exception was thrown on decrypting with an incorrect IV');
152
        } catch (\Exception $e) {
153
            $this->assertInstanceOf(
154
                DecryptException::class,
155
                $e,
156
                'Expected an instance of DecryptException containing a message about IV, got '. get_class($e)
157
            );
158
        }
159
160
        // Test decryption of encrypted file with incorrect checksum
161
        try {
162
            $invalidEncryptedFile = EncryptedFile::create(
163
                $encryptedFile->getIV(),
164
                bin2hex(openssl_random_pseudo_bytes(16)),
165
                $encryptedFile->getPadding(),
166
                $encryptedFile->getFile()->getRealPath()
167
            );
168
            $this->fileCrypt->decrypt($invalidEncryptedFile, $this->test_decrypted_file);
169
            $this->fail('No exception was thrown on decrypting with unmatching checksums');
170
        } catch (\Exception $e) {
171
            $this->assertInstanceOf(
172
                DecryptException::class,
173
                $e,
174
                'Expected an instance of DecryptException with a message about the checksum, got '. get_class($e)
175
            );
176
        }
177
178
        // Test decryption of encrypted file with twice the amount of padding
179
        try {
180
            $invalidEncryptedFile = EncryptedFile::create(
181
                $encryptedFile->getIV(),
182
                $encryptedFile->getChecksum(),
183
                $encryptedFile->getPadding() * 2,
184
                $encryptedFile->getFile()->getRealPath()
185
            );
186
            $this->fileCrypt->decrypt($invalidEncryptedFile, $this->test_decrypted_file);
187
            $this->fail('No exception was thrown on decrypting with too much padding');
188
        } catch (\Exception $e) {
189
            $this->assertInstanceOf(
190
                DecryptException::class,
191
                $e,
192
                'Expected an instance of DecryptException with a message about the checksum, got '. get_class($e)
193
            );
194
        }
195
196
        // Test the decrypt method with an invalid variable type
197
        $this->fileCrypt->decrypt($this->test_encrypted_file, $this->test_decrypted_file);
0 ignored issues
show
Documentation introduced by
$this->test_encrypted_file is of type string, but the function expects a object<Wubbajack\Encryption\EncryptedFile>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
198
    }
199
200
    /**
201
     * Test streaming decryption
202
     */
203
    public function testStreamDecrypt()
204
    {
205
        $encryptedFile = $this->fileCrypt->encrypt($this->test_file, $this->test_encrypted_file);
206
207
        // Test whether the checksum of the decrypted data equals the checksum of the file
208
        $decrypted_data = '';
209
        $this->fileCrypt->streamDecrypt(
210
            $encryptedFile,
211
            function ($data, $stream) use (&$decrypted_data, $encryptedFile) {
212
                if (feof($stream)) {
213
                    $data = substr($data, 0, -$encryptedFile->getPadding());
214
                }
215
216
                $decrypted_data .= $data;
217
            }
218
        );
219
220
        $this->assertEquals(sha1($decrypted_data), $encryptedFile->getChecksum());
221
    }
222
223
    /**
224
     * Removes all of the created encrypted and decrypted files created during testing
225
     */
226
    protected function cleanupFiles()
227
    {
228
        if (is_file($this->test_file)) {
229
            unlink($this->test_file);
230
        }
231
232
        if (is_file($this->test_encrypted_file)) {
233
            unlink($this->test_encrypted_file);
234
        }
235
236
        if (is_file($this->test_decrypted_file)) {
237
            unlink($this->test_decrypted_file);
238
        }
239
    }
240
241
    /**
242
     * Creates a test file
243
     *
244
     * @return string
245
     */
246
    protected function createTestFile()
247
    {
248
        $file = __DIR__ .'/test.json';
249
250
        file_put_contents($file, json_encode(['unit' => 'test']));
251
        return $file;
252
    }
253
}
254