Completed
Push — develop ( 6eb36d...b43094 )
by Christoper
02:17
created

FileEncrypterTest::setUp()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 7
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 1
Metric Value
c 1
b 0
f 1
dl 0
loc 7
rs 9.4286
cc 1
eloc 5
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
    public function testSetCipher()
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
    public function testSetMode()
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
     */
126
    public function testDecrypt()
127
    {
128
        $encryptedFile = $this->fileCrypt->encrypt($this->test_file, $this->test_encrypted_file);
129
130
        $this->fileCrypt->decrypt($encryptedFile, $this->test_decrypted_file);
131
132
        // Test if the decrypted file exists
133
        $this->assertTrue(file_exists($this->test_decrypted_file));
134
135
        // Test if the checksum equals the original file
136
        $this->assertEquals($encryptedFile->getChecksum(), sha1_file($this->test_decrypted_file));
137
138
        // Test if the decrypted file contains the same content as the original
139
        $this->assertEquals(file_get_contents($this->test_file), file_get_contents($this->test_decrypted_file));
140
141
        // Test decryption of encrypted file with incorrect wrong IV
142
        try {
143
            $invalidEncryptedFile = EncryptedFile::create(
144
                '2394qsf3-f9',
145
                $encryptedFile->getChecksum(),
146
                $encryptedFile->getPadding(),
147
                $encryptedFile->getFile()->getRealPath()
148
            );
149
            $this->fileCrypt->decrypt($invalidEncryptedFile, $this->test_decrypted_file);
150
            $this->fail('No exception was thrown on decrypting with an incorrect IV');
151
        } catch (\Exception $e) {
152
            $this->assertInstanceOf(
153
                DecryptException::class,
154
                $e,
155
                'Expected an instance of DecryptException containing a message about IV, got '. get_class($e)
156
            );
157
        }
158
159
        // Test decryption of encrypted file with incorrect checksum
160
        try {
161
            $invalidEncryptedFile = EncryptedFile::create(
162
                $encryptedFile->getIV(),
163
                bin2hex(openssl_random_pseudo_bytes(16)),
164
                $encryptedFile->getPadding(),
165
                $encryptedFile->getFile()->getRealPath()
166
            );
167
            $this->fileCrypt->decrypt($invalidEncryptedFile, $this->test_decrypted_file);
168
            $this->fail('No exception was thrown on decrypting with unmatching checksums');
169
        } catch (\Exception $e) {
170
            $this->assertInstanceOf(
171
                DecryptException::class,
172
                $e,
173
                'Expected an instance of DecryptException with a message about the checksum, got '. get_class($e)
174
            );
175
        }
176
177
        // Test decryption of encrypted file with twice the amount of padding
178
        try {
179
            $invalidEncryptedFile = EncryptedFile::create(
180
                $encryptedFile->getIV(),
181
                $encryptedFile->getChecksum(),
182
                $encryptedFile->getPadding() * 2,
183
                $encryptedFile->getFile()->getRealPath()
184
            );
185
            $this->fileCrypt->decrypt($invalidEncryptedFile, $this->test_decrypted_file);
186
            $this->fail('No exception was thrown on decrypting with too much padding');
187
        } catch (\Exception $e) {
188
            $this->assertInstanceOf(
189
                DecryptException::class,
190
                $e,
191
                'Expected an instance of DecryptException with a message about the checksum, got '. get_class($e)
192
            );
193
        }
194
    }
195
196
    /**
197
     * Test streaming decryption
198
     */
199
    public function testStreamDecrypt()
200
    {
201
        $encryptedFile = $this->fileCrypt->encrypt($this->test_file, $this->test_encrypted_file);
202
203
        // Test whether the checksum of the decrypted data equals the checksum of the file
204
        $decrypted_data = '';
205
        $this->fileCrypt->streamDecrypt(
206
            $encryptedFile,
207
            function ($data, $stream) use (&$decrypted_data, $encryptedFile) {
208
                if (feof($stream)) {
209
                    $data = substr($data, 0, -$encryptedFile->getPadding());
210
                }
211
212
                $decrypted_data .= $data;
213
            }
214
        );
215
216
        $this->assertEquals(sha1($decrypted_data), $encryptedFile->getChecksum());
217
    }
218
219
    /**
220
     * Removes all of the created encrypted and decrypted files created during testing
221
     */
222
    protected function cleanupFiles()
223
    {
224
        if (is_file($this->test_file)) {
225
            unlink($this->test_file);
226
        }
227
228
        if (is_file($this->test_encrypted_file)) {
229
            unlink($this->test_encrypted_file);
230
        }
231
232
        if (is_file($this->test_decrypted_file)) {
233
            unlink($this->test_decrypted_file);
234
        }
235
    }
236
237
    /**
238
     * Creates a test file
239
     *
240
     * @return string
241
     */
242
    protected function createTestFile()
243
    {
244
        $file = __DIR__ .'/test.json';
245
246
        file_put_contents($file, json_encode(['unit' => 'test']));
247
        return $file;
248
    }
249
}
250