Browse Source

Add test cases for mcrypt/openssl.

Also include a test to show that 2.x data can still be decrypted now.
Mark Story 11 years ago
parent
commit
3578d92ee7

+ 6 - 1
src/Utility/Crypto/Mcrypt.php

@@ -91,8 +91,13 @@ class Mcrypt {
 		$cipher = substr($cipher, $ivSize);
 		$plain = mcrypt_decrypt($algorithm, $key, $cipher, $mode, $iv);
 
-		// Remove PKCS#7 padding
+		// Remove PKCS#7 padding or Null bytes
+		// Newer values will be PKCS#7 padded, while old
+		// mcrypt values will be null byte padded.
 		$padChar = substr($plain, -1);
+		if ($padChar === "\0") {
+			return trim($plain, "\0");
+		}
 		$padLen = ord($padChar);
 		return substr($plain, 0, -$padLen);
 	}

+ 120 - 0
tests/TestCase/Utility/Crypto/McryptTest.php

@@ -0,0 +1,120 @@
+<?php
+/**
+ * CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
+ * Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
+ *
+ * Licensed under The MIT License
+ * For full copyright and license information, please see the LICENSE.txt
+ * Redistributions of files must retain the above copyright notice.
+ *
+ * @copyright     Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
+ * @link          http://cakephp.org CakePHP(tm) Project
+ * @since         0.10.0
+ * @license       http://www.opensource.org/licenses/mit-license.php MIT License
+ */
+namespace Cake\Test\TestCase\Utility\Crypto;
+
+use Cake\TestSuite\TestCase;
+use Cake\Utility\Crypto\Mcrypt;
+
+/**
+ * Mcrypt engine tests.
+ */
+class McryptTest extends TestCase {
+
+/**
+ * Setup function.
+ *
+ * @return void
+ */
+	public function setUp() {
+		parent::setUp();
+		$this->skipIf(!function_exists('mcrypt_encrypt'), 'No mcrypt skipping tests');
+		$this->crypt = new Mcrypt();
+	}
+
+/**
+ * testRijndael method
+ *
+ * @return void
+ */
+	public function testRijndael() {
+		$txt = 'The quick brown fox jumped over the lazy dog.';
+		$key = 'DYhG93b0qyJfIxfs2guVoUubWwvniR2G0FgaC9mi';
+
+		$result = $this->crypt->rijndael($txt, $key, 'encrypt');
+		$this->assertEquals($txt, $this->crypt->rijndael($result, $key, 'decrypt'));
+
+		$result = $this->crypt->rijndael($key, $txt, 'encrypt');
+		$this->assertEquals($key, $this->crypt->rijndael($result, $txt, 'decrypt'));
+
+		$result = $this->crypt->rijndael('', $key, 'encrypt');
+		$this->assertEquals('', $this->crypt->rijndael($result, $key, 'decrypt'));
+
+		$key = 'this is my key of over 32 chars, yes it is';
+		$result = $this->crypt->rijndael($txt, $key, 'encrypt');
+		$this->assertEquals($txt, $this->crypt->rijndael($result, $key, 'decrypt'));
+	}
+
+/**
+ * Test encrypt/decrypt.
+ *
+ * @return void
+ */
+	public function testEncryptDecrypt() {
+		$txt = 'The quick brown fox';
+		$key = 'This key is enough bytes';
+		$result = $this->crypt->encrypt($txt, $key);
+		$this->assertNotEquals($txt, $result, 'Should be encrypted.');
+		$this->assertNotEquals($result, $this->crypt->encrypt($txt, $key), 'Each result is unique.');
+		$this->assertEquals($txt, $this->crypt->decrypt($result, $key));
+	}
+
+/**
+ * Test that changing the key causes decryption to fail.
+ *
+ * @return void
+ */
+	public function testDecryptKeyFailure() {
+		$txt = 'The quick brown fox';
+		$key = 'This key is enough bytes';
+		$result = $this->crypt->encrypt($txt, $key);
+
+		$key = 'Not the same key.';
+		$this->assertFalse($this->crypt->decrypt($txt, $key), 'Modified key will fail.');
+	}
+
+/**
+ * Test that decrypt fails when there is an hmac error.
+ *
+ * @return void
+ */
+	public function testDecryptHmacFailure() {
+		$txt = 'The quick brown fox';
+		$key = 'This key is long enough';
+		$salt = 'this is a delicious salt!';
+		$result = $this->crypt->encrypt($txt, $key, $salt);
+
+		// Change one of the bytes in the hmac.
+		$result[10] = 'x';
+		$this->assertFalse($this->crypt->decrypt($result, $key, $salt), 'Modified hmac causes failure.');
+	}
+
+/**
+ * Ensure that data encrypted with 2.x encrypt() function can be decrypted with mcrypt engine.
+ *
+ * The $cipher variable is base64 encoded data from 2.x encrypt()
+ *
+ * @return
+ */
+	public function testDecryptOldData() {
+		$key = 'My password is nice and long really it is';
+		$cipher = 'ZmFkMjdmY2U2NjgzOTkwMGZmMWJiMzY0ZDA5ZDUwZmNjYTdjNWVkZThkMzhmNzdiY' .
+			'Tg3ZDFjMzNjNmViMDljMnk9k0LmYpwSZH5eq7GmDozMwHxzh37YaXFQ2TK5gXb5OfTKXv83K+NjAS9lIo/Zvw==';
+		$salt = '';
+
+		$result = $this->crypt->encrypt($txt, $key, $salt);
+		$this->assertEquals('This is a secret message', $result);
+	}
+
+}

+ 93 - 0
tests/TestCase/Utility/Crypto/OpenSslTest.php

@@ -0,0 +1,93 @@
+<?php
+/**
+ * CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
+ * Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
+ *
+ * Licensed under The MIT License
+ * For full copyright and license information, please see the LICENSE.txt
+ * Redistributions of files must retain the above copyright notice.
+ *
+ * @copyright     Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
+ * @link          http://cakephp.org CakePHP(tm) Project
+ * @since         0.10.0
+ * @license       http://www.opensource.org/licenses/mit-license.php MIT License
+ */
+namespace Cake\Test\TestCase\Utility\Crypto;
+
+use Cake\TestSuite\TestCase;
+use Cake\Utility\Crypto\OpenSsl;
+
+/**
+ * Openssl engine tests.
+ */
+class OpenSslTest extends TestCase {
+
+/**
+ * Setup function.
+ *
+ * @return void
+ */
+	public function setUp() {
+		parent::setUp();
+		$this->skipIf(!function_exists('openssl_encrypt'), 'No openssl skipping tests');
+		$this->crypt = new OpenSsl();
+	}
+
+/**
+ * testRijndael method
+ *
+ * @expectedException \LogicException
+ * @return void
+ */
+	public function testRijndael() {
+		$txt = 'The quick brown fox jumped over the lazy dog.';
+		$key = 'DYhG93b0qyJfIxfs2guVoUubWwvniR2G0FgaC9mi';
+
+		$this->crypt->rijndael($txt, $key, 'encrypt');
+	}
+
+/**
+ * Test encrypt/decrypt.
+ *
+ * @return void
+ */
+	public function testEncryptDecrypt() {
+		$txt = 'The quick brown fox';
+		$key = 'This key is enough bytes';
+		$result = $this->crypt->encrypt($txt, $key);
+		$this->assertNotEquals($txt, $result, 'Should be encrypted.');
+		$this->assertNotEquals($result, $this->crypt->encrypt($txt, $key), 'Each result is unique.');
+		$this->assertEquals($txt, $this->crypt->decrypt($result, $key));
+	}
+
+/**
+ * Test that changing the key causes decryption to fail.
+ *
+ * @return void
+ */
+	public function testDecryptKeyFailure() {
+		$txt = 'The quick brown fox';
+		$key = 'This key is enough bytes';
+		$result = $this->crypt->encrypt($txt, $key);
+
+		$key = 'Not the same key.';
+		$this->assertFalse($this->crypt->decrypt($txt, $key), 'Modified key will fail.');
+	}
+
+/**
+ * Test that decrypt fails when there is an hmac error.
+ *
+ * @return void
+ */
+	public function testDecryptHmacFailure() {
+		$txt = 'The quick brown fox';
+		$key = 'This key is long enough';
+		$salt = 'this is a delicious salt!';
+		$result = $this->crypt->encrypt($txt, $key, $salt);
+
+		// Change one of the bytes in the hmac.
+		$result[10] = 'x';
+		$this->assertFalse($this->crypt->decrypt($result, $key, $salt), 'Modified hmac causes failure.');
+	}
+
+}