Skip to content

Commit 35ba760

Browse files
committed
Merge pull request archwisp#13 from johnkary/cleanup
[PR13] Added test case for a previously uncovered Exception path and improved the test for IV generation
2 parents 92f76e4 + 740fa0c commit 35ba760

File tree

2 files changed

+79
-47
lines changed

2 files changed

+79
-47
lines changed

Simple.php

+7-7
Original file line numberDiff line numberDiff line change
@@ -29,15 +29,15 @@ class Simple
2929
public function __construct($encryptionKey, $macKey) {
3030
$this->_encryptionKey = base64_decode($encryptionKey);
3131
$this->_macKey = base64_decode($macKey);
32-
32+
3333
$keySize = $this->_getKeySize();
3434

3535
if (strlen($this->_encryptionKey) !== $keySize) {
3636
throw new \InvalidArgumentException(
3737
sprintf('Encryption key must be exactly %s bytes long.', $keySize)
3838
);
3939
}
40-
40+
4141
if (strlen($this->_macKey) !== $keySize) {
4242
throw new \InvalidArgumentException(
4343
sprintf('MAC key must be exactly %s bytes long.', $keySize)
@@ -49,19 +49,19 @@ public function encrypt($plaintext, $iv = null) {
4949
if (is_null($iv)) {
5050
$iv = $this->generateIv();
5151
}
52-
52+
5353
$decodedIv = base64_decode($iv);
54-
54+
5555
if (strlen($decodedIv) !== $this->_getBlockSize()) {
5656
throw new \InvalidArgumentException(
5757
sprintf('IV must be exactly %s bytes long.', $this->_getBlockSize())
5858
);
5959
}
60-
60+
6161
$paddedPlaintext = $this->_padWithPkcs7($plaintext);
6262

63-
$ciphertext = $decodedIv . mcrypt_encrypt($this->_encryptionAlgorithm,
64-
$this->_encryptionKey, $paddedPlaintext, $this->_mode, $decodedIv
63+
$ciphertext = $decodedIv . mcrypt_encrypt($this->_encryptionAlgorithm,
64+
$this->_encryptionKey, $paddedPlaintext, $this->_mode, $decodedIv
6565
);
6666

6767
$signature = hash_hmac($this->_macAlgorithm, $ciphertext, $this->_macKey, true);

SimpleTest.php

+72-40
Original file line numberDiff line numberDiff line change
@@ -4,42 +4,65 @@
44

55
class SimpleTest extends \PHPUnit_Framework_TestCase
66
{
7+
/**
8+
* @var Simple
9+
*/
710
private $_instance;
811
private $_encryptionKey = 'nXA5gXtlOgHgxl6EZTfkfDmIzWaRqxZ1rq7DRNCIQ/Q=';
912
private $_macKey = 'K9iPmOMowXUvcQTd7ehfcxvvHd4OtzyztQp+wuQwb6U=';
1013

1114
public function setUp() {
12-
$this->_instance = new \PHPCrypt\Simple($this->_encryptionKey, $this->_macKey);
15+
$this->_instance = new Simple($this->_encryptionKey, $this->_macKey);
1316
}
1417

15-
public function testEncrypt() {
18+
public function testCanEncryptPlaintext() {
1619
$ciphertext = $this->_instance->encrypt('FooBar ', 'lAuCU7ft5tnHPKWRjF1IKV4J6V9/eCGQIisHZfuqMtY=');
17-
18-
$this->assertEquals(
20+
21+
$this->assertSame(
1922
'cmpkLTI1Ni1obWFjLXNoYTI1NnxsQXVDVTdmdDV0bkhQS1dSakYxSUtWNEo2VjkvZUNHUUlpc0haZnVxTXRhLzNnSmc3SWhIZ3h2YVVZNmlzUnlQY1JxK3gvclFmblB4WS9BMVhxWTJuQT09fDZNQkJDS0JiWWMrYVdMcG5rMU1RVlcyak01Sm56NW9IZlhuRHJpeUlMOVE9',
2023
$ciphertext
2124
);
2225
}
23-
24-
public function testDecrypt() {
26+
27+
public function testCanDecryptCiphertext() {
2528
$plaintext = $this->_instance->decrypt(
2629
'cmpkLTI1Ni1obWFjLXNoYTI1NnxsQXVDVTdmdDV0bkhQS1dSakYxSUtWNEo2VjkvZUNHUUlpc0haZnVxTXRhLzNnSmc3SWhIZ3h2YVVZNmlzUnlQY1JxK3gvclFmblB4WS9BMVhxWTJuQT09fDZNQkJDS0JiWWMrYVdMcG5rMU1RVlcyak01Sm56NW9IZlhuRHJpeUlMOVE9'
2730
);
28-
29-
$this->assertEquals('FooBar ', $plaintext);
31+
32+
$this->assertSame('FooBar ', $plaintext);
3033
}
31-
32-
public function testDecryptUnknownConstruction() {
33-
$this->setExpectedException('Exception', 'Unknown construction, "rjd-256-hmac-sha256/128"');
34-
$plaintext = $this->_instance->decrypt(
34+
35+
/**
36+
* @expectedException \RunTimeException
37+
* @expectedExceptionMessage Unknown construction, "rjd-256-hmac-sha256/128"
38+
*/
39+
public function testDecryptingSignedCiphertextWithUnknownConstructionThrowsException() {
40+
$this->_instance->decrypt(
3541
'cmpkLTI1Ni1obWFjLXNoYTI1Ni8xMjh8bEF1Q1U3ZnQ1dG5IUEtXUmpGMUlLVjRKNlY5L2VDR1FJaXNIWmZ1cU10YS8zZ0pnN0loSGd4dmFVWTZpc1J5UGNScSt4L3JRZm5QeFkvQTFYcVkybkE9PXw2TUJCQ0tCYlljK2FXTHBuazFNUVZXMmpNNUpuejVvSGZYbkRyaXlJTDlRPQ=='
3642
);
3743
}
3844

45+
public function invalidCiphertextPartsData()
46+
{
47+
return array(
48+
'Too few parts' => array('cGFydDF8cGFydDI='), // 'part1|part2'
49+
'Too many parts' => array('cGFydDF8cGFydDJ8cGFydDN8cGFydDQ='), // 'part1|part2|part3|part4'
50+
);
51+
}
52+
53+
/**
54+
* @dataProvider invalidCiphertextPartsData
55+
* @expectedException \RuntimeException
56+
* @expectedExceptionMessage Invalid encoding
57+
*/
58+
public function testDecryptingCiphertextWithWrongNumberOfPartsThrowsException($ciphertext) {
59+
$this->_instance->decrypt($ciphertext);
60+
}
61+
3962
/**
40-
/* This function encrypts the same string with randomized IVs and
41-
/* flips a single bit of the ciphertext
42-
*/
63+
* Encrypts the same string with randomized IVs and flips a single bit of
64+
* the ciphertext.
65+
*/
4366
public function invalidCiphertextData() {
4467
$this->setUp();
4568
$invalidCiphertexts = array();
@@ -51,15 +74,15 @@ public function invalidCiphertextData() {
5174
$ciphertext = base64_decode($encodedCiphertext);
5275
$randomByte = rand(1, strlen($ciphertext));
5376
$mask = str_repeat("\x00", $randomByte -1) . "\x01" . str_repeat("\x00", strlen($ciphertext) - $randomByte);
54-
77+
5578
// SANITY CHECK: If this mask is removed, this test should fail every
5679
// single run because the ciphertext should match.
5780
$invalidCiphertext = $ciphertext ^ $mask;
5881

5982
// printf("Ciphertext: %s\n", bin2hex($ciphertext));
6083
// printf("Mask: %s\n", bin2hex($mask));
6184
// printf("Invalid Ciphertext: %s\n", bin2hex($invalidCiphertext));
62-
85+
6386
$encodedInvalidCiphertext = base64_encode($invalidCiphertext);
6487
$invalidCiphertexts[] = array(base64_encode($construction . '|' . $encodedInvalidCiphertext . '|' . $encodedSignature));
6588
}
@@ -69,16 +92,18 @@ public function invalidCiphertextData() {
6992

7093
/**
7194
* @dataProvider invalidCiphertextData
95+
* @expectedException \RuntimeException
96+
* @expectedExceptionMessage Invalid signature
7297
*/
73-
public function testDecryptInvalidCiphertext($signedCiphertext) {
74-
$this->setExpectedException('Exception', 'Invalid signature');
75-
$plaintext = $this->_instance->decrypt($signedCiphertext);
98+
public function testDecryptingInvalidCiphertextThrowsException($signedCiphertext) {
99+
$this->_instance->decrypt($signedCiphertext);
76100
}
77-
78-
public function testEncryptAndDecrypt() {
101+
102+
public function testEncryptedDataCanBeDecrypted() {
79103
$plaintext = 'Something';
80104
$ciphertext = $this->_instance->encrypt('Something');
81-
$this->assertEquals($plaintext, $this->_instance->decrypt($ciphertext));
105+
106+
$this->assertSame($plaintext, $this->_instance->decrypt($ciphertext));
82107
}
83108

84109
public function invalidKeyData() {
@@ -94,32 +119,39 @@ public function invalidKeyData() {
94119

95120
/**
96121
* @dataProvider invalidKeyData
122+
* @expectedException \InvalidArgumentException
123+
* @expectedExceptionMessage Encryption key must be
97124
*/
98-
public function testEncryptInvalidEncryptionKeySize($invalidKey) {
99-
$this->setExpectedException('Exception');
100-
$instance = new \PHPCrypt\Simple($invalidKey, $this->_macKey);
125+
public function testInvalidEncryptionKeyThrowsException($invalidKey) {
126+
new Simple($invalidKey, $this->_macKey);
101127
}
102-
128+
103129
/**
104130
* @dataProvider invalidKeyData
131+
* @expectedException \InvalidArgumentException
132+
* @expectedExceptionMessage MAC key must be
105133
*/
106-
public function testEncryptInvalidMacKeySize($invalidKey) {
107-
$this->setExpectedException('Exception');
108-
$instance = new \PHPCrypt\Simple($this->_encryptionKey, $invalidKey);
134+
public function testInvalidMacKeySizeThrowsException($invalidKey) {
135+
new Simple($this->_encryptionKey, $invalidKey);
109136
}
110137

111-
public function testEncryptInvalidIvLength() {
112-
$this->setExpectedException('Exception');
138+
/**
139+
* @expectedException \InvalidArgumentException
140+
* @expectedExceptionMessage IV must be exactly
141+
*/
142+
public function testEncryptWithInvalidIvLengthThrowsException() {
143+
$this->_instance->encrypt('FooBar ', 'wrong-iv-length');
144+
}
113145

114-
$ciphertext = $this->_instance->encrypt(
115-
'FooBar ', $this->_encryptionKey, $this->macKey, 'Short IV');
146+
public function testDifferentIvGeneratedOnEachRun() {
147+
$expected = 20;
148+
$ivs = array();
149+
for ($i = 1; $i <= $expected; $i++) {
150+
$ivs[] = $this->_instance->generateIv();
151+
}
116152

117-
$this->assertEquals('This should never execute', base64_encode($ciphertext));
118-
}
153+
$duplicatesRemoved = array_values($ivs);
119154

120-
public function testGenerateIv() {
121-
$iv = $this->_instance->generateIv();
122-
$secondIv = $this->_instance->generateIv();
123-
$this->assertNotEquals($iv, $secondIv);
155+
$this->assertCount($expected, $duplicatesRemoved);
124156
}
125157
}

0 commit comments

Comments
 (0)