Skip to content

Commit 38f0bc2

Browse files
committed
Unit tests for encryption adapters
1 parent 66f3284 commit 38f0bc2

File tree

3 files changed

+274
-0
lines changed

3 files changed

+274
-0
lines changed
Lines changed: 188 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,188 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
7+
declare(strict_types=1);
8+
9+
/**
10+
* Test case for \Magento\Framework\Encryption\Adapter\Mcrypt
11+
*/
12+
namespace Magento\Framework\Encryption\Test\Unit\Adapter;
13+
14+
class McryptTest extends \PHPUnit\Framework\TestCase
15+
{
16+
private $key;
17+
18+
private static $cipherInfo;
19+
20+
private const SUPPORTED_CIPHER_MODE_COMBINATIONS = [
21+
MCRYPT_BLOWFISH => [MCRYPT_MODE_ECB],
22+
MCRYPT_RIJNDAEL_128 => [MCRYPT_MODE_ECB],
23+
MCRYPT_RIJNDAEL_256 => [MCRYPT_MODE_CBC],
24+
];
25+
26+
protected function setUp()
27+
{
28+
$this->key = substr(__CLASS__, -32, 32);
29+
}
30+
31+
protected function getRandomString(int $length): string
32+
{
33+
$result = '';
34+
35+
do {
36+
$result .= sha1(microtime());
37+
} while (strlen($result) < $length);
38+
39+
return substr($result, -$length);
40+
}
41+
42+
private function requireCipherInfo()
43+
{
44+
$filename = __DIR__ . '/../Crypt/_files/_cipher_info.php';
45+
46+
if (!self::$cipherInfo) {
47+
self::$cipherInfo = include $filename;
48+
}
49+
}
50+
51+
private function getKeySize(string $cipherName, string $modeName): int
52+
{
53+
$this->requireCipherInfo();
54+
return self::$cipherInfo[$cipherName][$modeName]['key_size'];
55+
}
56+
57+
private function getInitVectorSize(string $cipherName, string $modeName): int
58+
{
59+
$this->requireCipherInfo();
60+
return self::$cipherInfo[$cipherName][$modeName]['iv_size'];
61+
}
62+
63+
public function getCipherModeCombinations(): array
64+
{
65+
$result = [];
66+
foreach (self::SUPPORTED_CIPHER_MODE_COMBINATIONS as $cipher => $modes) {
67+
/** @var array $modes */
68+
foreach ($modes as $mode) {
69+
$result[$cipher . '-' . $mode] = [$cipher, $mode];
70+
}
71+
}
72+
return $result;
73+
}
74+
75+
/**
76+
* @dataProvider getCipherModeCombinations
77+
*/
78+
public function testConstructor(string $cipher, string $mode)
79+
{
80+
/* Generate random init vector */
81+
$initVector = $this->getRandomString($this->getInitVectorSize($cipher, $mode));
82+
83+
$crypt = new \Magento\Framework\Encryption\Adapter\Mcrypt($this->key, $cipher, $mode, $initVector);
84+
85+
$this->assertEquals($cipher, $crypt->getCipher());
86+
$this->assertEquals($mode, $crypt->getMode());
87+
$this->assertEquals($initVector, $crypt->getInitVector());
88+
}
89+
90+
public function getConstructorExceptionData(): array
91+
{
92+
$key = substr(__CLASS__, -32, 32);
93+
$result = [];
94+
foreach (self::SUPPORTED_CIPHER_MODE_COMBINATIONS as $cipher => $modes) {
95+
/** @var array $modes */
96+
foreach ($modes as $mode) {
97+
$tooLongKey = str_repeat('-', $this->getKeySize($cipher, $mode) + 1);
98+
$tooShortInitVector = str_repeat('-', $this->getInitVectorSize($cipher, $mode) - 1);
99+
$tooLongInitVector = str_repeat('-', $this->getInitVectorSize($cipher, $mode) + 1);
100+
$result['tooLongKey-' . $cipher . '-' . $mode . '-false'] = [$tooLongKey, $cipher, $mode, false];
101+
$keyPrefix = 'key-' . $cipher . '-' . $mode;
102+
$result[$keyPrefix . '-tooShortInitVector'] = [$key, $cipher, $mode, $tooShortInitVector];
103+
$result[$keyPrefix . '-tooLongInitVector'] = [$key, $cipher, $mode, $tooLongInitVector];
104+
}
105+
}
106+
return $result;
107+
}
108+
109+
/**
110+
* @dataProvider getConstructorExceptionData
111+
* @expectedException \Magento\Framework\Exception\LocalizedException
112+
*/
113+
public function testConstructorException(string $key, string $cipher, string $mode, ?string $initVector = null)
114+
{
115+
new \Magento\Framework\Encryption\Adapter\Mcrypt($key, $cipher, $mode, $initVector);
116+
}
117+
118+
public function testConstructorDefaults()
119+
{
120+
$cryptExpected = new \Magento\Framework\Encryption\Adapter\Mcrypt(
121+
$this->key,
122+
MCRYPT_BLOWFISH,
123+
MCRYPT_MODE_ECB,
124+
null
125+
);
126+
$cryptActual = new \Magento\Framework\Encryption\Adapter\Mcrypt($this->key);
127+
128+
$this->assertEquals($cryptExpected->getCipher(), $cryptActual->getCipher());
129+
$this->assertEquals($cryptExpected->getMode(), $cryptActual->getMode());
130+
$this->assertEquals($cryptExpected->getInitVector(), $cryptActual->getInitVector());
131+
}
132+
133+
public function getCryptData(): array
134+
{
135+
$fixturesFilename = __DIR__ . '/../Crypt/_files/_crypt_fixtures.php';
136+
137+
$result = include $fixturesFilename;
138+
/* Restore encoded string back to binary */
139+
foreach ($result as &$cryptParams) {
140+
$cryptParams[5] = base64_decode($cryptParams[5]);
141+
}
142+
unset($cryptParams);
143+
144+
return $result;
145+
}
146+
147+
/**
148+
* @dataProvider getCryptData
149+
*/
150+
public function testDecrypt(
151+
string $key,
152+
string $cipher,
153+
string $mode,
154+
?string $initVector,
155+
string $expectedData,
156+
string $inputData
157+
) {
158+
$crypt = new \Magento\Framework\Encryption\Adapter\Mcrypt($key, $cipher, $mode, $initVector);
159+
$actualData = $crypt->decrypt($inputData);
160+
$this->assertEquals($expectedData, $actualData);
161+
}
162+
163+
/**
164+
* @expectedException \Exception
165+
*/
166+
public function testEncrypt()
167+
{
168+
$crypt = new \Magento\Framework\Encryption\Adapter\Mcrypt($this->key);
169+
$crypt->encrypt('Hello World!!');
170+
}
171+
172+
/**
173+
* @dataProvider getCipherModeCombinations
174+
*/
175+
public function testInitVectorNone(string $cipher, string $mode)
176+
{
177+
$crypt = new \Magento\Framework\Encryption\Adapter\Mcrypt(
178+
$this->key,
179+
$cipher,
180+
$mode,
181+
null
182+
);
183+
$actualInitVector = $crypt->getInitVector();
184+
185+
$expectedInitVector = str_repeat("\0", $this->getInitVectorSize($cipher, $mode));
186+
$this->assertEquals($expectedInitVector, $actualInitVector);
187+
}
188+
}
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
7+
declare(strict_types=1);
8+
9+
/**
10+
* Test case for \Magento\Framework\Encryption\Adapter\SodiumChachaIetf
11+
*/
12+
namespace Magento\Framework\Encryption\Test\Unit\Adapter;
13+
14+
class SodiumChachaIetfTest extends \PHPUnit\Framework\TestCase
15+
{
16+
public function getCryptData(): array
17+
{
18+
$fixturesFilename = __DIR__ . '/../Crypt/_files/_sodium_chachaieft_fixtures.php';
19+
20+
$result = include $fixturesFilename;
21+
/* Restore encoded string back to binary */
22+
foreach ($result as &$cryptParams) {
23+
$cryptParams['encrypted'] = base64_decode($cryptParams['encrypted']);
24+
}
25+
unset($cryptParams);
26+
27+
return $result;
28+
}
29+
30+
/**
31+
* @dataProvider getCryptData
32+
*/
33+
public function testEncrypt(string $key, string $encrypted, string $decrypted)
34+
{
35+
$crypt = new \Magento\Framework\Encryption\Adapter\SodiumChachaIetf($key);
36+
$result = $crypt->encrypt($decrypted);
37+
38+
$this->assertNotEquals($encrypted, $result);
39+
}
40+
41+
/**
42+
* @dataProvider getCryptData
43+
*/
44+
public function testDecrypt(string $key, string $encrypted, string $decrypted)
45+
{
46+
$crypt = new \Magento\Framework\Encryption\Adapter\SodiumChachaIetf($key);
47+
$result = $crypt->decrypt($encrypted);
48+
49+
$this->assertEquals($decrypted, $result);
50+
}
51+
}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
7+
declare(strict_types=1);
8+
9+
return [
10+
0 => [
11+
'key' => '6wRADHwwCBGgdxbcHhovGB0upmg0mbsN',
12+
'encrypted' => '146BhsQ3grT0VgkYuY3ii3gpClXHkFqlIcNpAD4+bAMBP+ToCHZHiJID',
13+
'decrypted' => 'Hello World!!!',
14+
],
15+
1 => [
16+
'key' => 'uPuzBU067DXTM4PqEi14Sv5tbWjVcRZI',
17+
'encrypted' => '6SQaVrCnY10n8tOxYyvWuVGKddjR12ZbGylM9K+bRHqsqltRwuLs15vV',
18+
'decrypted' => 'Hello World!!!',
19+
],
20+
2 => [
21+
'key' => 'zsmVdKkwVgylxMM8ZzQ3GTv7SxvusKnJ',
22+
'encrypted' => 'eQcREUJDV8EEB9WA1pBd5LbVQrs4Kyv6iWnkhOnjeitySuPQAcpIVoCM',
23+
'decrypted' => 'Hello World!!!',
24+
],
25+
3 => [
26+
'key' => 'aggaHLvRCxRRyebpsrGAdLAIfSrufYrN',
27+
'encrypted' => 'PSOa8KCpTsxnTgq4IKbpneF38FIp0JeAeiXQIf30vS5X+riylx05pz9b',
28+
'decrypted' => 'Hello World!!!',
29+
],
30+
4 => [
31+
'key' => '6tEWnKY6AcdjS2XfPe1DjTbkvu2cFFZo',
32+
'encrypted' => 'UglO9dEgslFpwPwejJmrK89PmBicv+I1pfdaXaEI69IrETD8LpdzOLF7',
33+
'decrypted' => 'Hello World!!!',
34+
],
35+
];

0 commit comments

Comments
 (0)