Browse Source

Bugfix: Composer.json was not working; Updating code to use PHP namespaces; Reorganizing filesystem for better usability

Curtis Farnham 10 years ago
parent
commit
0008f8daad

+ 5 - 0
.gitignore

@@ -0,0 +1,5 @@
+phpunit.xml
+/vendor
+composer.phar
+composer.lock
+.DS_Store

+ 1 - 1
CREDITS

@@ -6,4 +6,4 @@ Guysung Kim - PHP decryption function
 
 Curtis Farnham - Converting procedural PHP encrypt and decrypt functions to Object-Oriented classes.
 				 Adding PHPUnit test suite
-				 Adding support for schemas 0 and 1
+				 Adding support for schemas 0, 1, and 3

+ 5 - 5
README

@@ -1,10 +1,10 @@
 RNCryptor PHP
 -------------
 
-This implementation is fully compatible with Rob Napier's iOS implementation of
-RNCryptor.  It supports both encryption and decryption of all RNCryptor schema
-versions through version 2, with experimental support for version 3.  Due to 
-security concerns with schemas 0 and 1, it is strongly recommended to use 
-schema 2 wherever possible.  This is the default if none is specified.
+This implementation strives to be fully compatible with Rob Napier's
+Objective-C implementation of RNCryptor.  It supports both encryption and
+decryption of all RNCryptor schema versions through version 3.  Due to security
+concerns with schemas 0 through 2, it is strongly recommended to use schema 3
+wherever possible.  This is the default if none is specified.
 
 Basic usage is seen in the examples folder.

+ 14 - 0
autoload.php

@@ -0,0 +1,14 @@
+<?php
+
+/*
+ * This file is part of the RNCryptor package.
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+require __DIR__.'/lib/RNCryptor/Autoloader.php';
+
+RNCryptor\Autoloader::register();
+
+require_once __DIR__ . '/functions.php';

+ 9 - 4
composer.json

@@ -1,6 +1,9 @@
 {
-    "name": "rncryptor/rncryptor-php",
+	"name": "rncryptor/rncryptor-php",
+    "type": "library",
     "description": "PHP implementation of RNCryptor",
+    "keywords": ["encryption", "crypto"],
+    "homepage": "https://github.com/RNCryptor/RNCryptor-php",
     "license": "MIT",
     "authors": [
         {
@@ -17,11 +20,13 @@
         }
     ],
     "require": {
+        "php": ">=5.3.2",
         "ext-mcrypt": "*"
     },
+    "require-dev": {
+		"rncryptor/rncrpytor-spec": "master"
+    },
     "autoload": {
-        "psr-4": {
-            "RNCryptor\\": ""
-        }
+        "psr-0": {"RNCryptor": "lib/"}
     }
 }

+ 2 - 2
examples/decrypt.php

@@ -1,11 +1,11 @@
 <?php
 
-require_once __DIR__ . '/../RNDecryptor.php';
+require __DIR__.'/../autoload.php';
 
 $password = "myPassword";
 $base64Encrypted = "AgGXutvFqW9RqQuokYLjehbfM7F+8OO/2sD8g3auA+oNCQFoarRmc59qcKJve7FHyH9MkyJWZ4Cj6CegDU+UbtpXKR0ND6UlfwaZncRUNkw53jy09cgUkHRJI0gCfOsS4rXmRdiaqUt+ukkkaYfAJJk/o3HBvqK/OI4qttyo+kdiLbiAop5QQwWReG2LMQ08v9TAiiOQgFWhd1dc+qFEN7Cv";
 
-$cryptor = new RNDecryptor();
+$cryptor = new \RNCryptor\Decryptor();
 $plaintext = $cryptor->decrypt($base64Encrypted, $password);
 
 echo "Base64 Encrypted:\n$base64Encrypted\n\n";

+ 2 - 2
examples/encrypt.php

@@ -1,11 +1,11 @@
 <?php
 
-require_once __DIR__ . '/../RNEncryptor.php';
+require __DIR__.'/../autoload.php';
 
 $password = "myPassword";
 $plaintext = "Here is my test vector. It's not too long, but more than a block and needs padding.";
 
-$cryptor = new RNEncryptor();
+$cryptor = new \RNCryptor\Encryptor();
 $base64Encrypted = $cryptor->encrypt($plaintext, $password);
 
 echo "Plaintext:\n$plaintext\n\n";

+ 62 - 0
lib/RNCryptor/Autoloader.php

@@ -0,0 +1,62 @@
+<?php
+
+/*
+ * This file is part of the Predis package.
+ *
+ * (c) Daniele Alessandri <suppakilla@gmail.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace RNCryptor;
+
+/**
+ * Implements a lightweight PSR-0 compliant autoloader.
+ *
+ * @author Eric Naeseth <eric@thumbtack.com>
+ * @author Daniele Alessandri <suppakilla@gmail.com>
+ */
+class Autoloader
+{
+    private $directory;
+    private $prefix;
+    private $prefixLength;
+
+    /**
+     * @param string $baseDirectory Base directory where the source files are located.
+     */
+    public function __construct($baseDirectory = __DIR__)
+    {
+        $this->directory = $baseDirectory;
+        $this->prefix = __NAMESPACE__ . '\\';
+        $this->prefixLength = strlen($this->prefix);
+    }
+
+    /**
+     * Registers the autoloader class with the PHP SPL autoloader.
+     *
+     * @param bool $prepend Prepend the autoloader on the stack instead of appending it.
+     */
+    public static function register($prepend = false)
+    {
+        spl_autoload_register(array(new self, 'autoload'), true, $prepend);
+    }
+
+    /**
+     * Loads a class from a file using its fully qualified name.
+     *
+     * @param string $className Fully qualified name of a class.
+     */
+    public function autoload($className)
+    {
+        if (0 === strpos($className, $this->prefix)) {
+            $parts = explode('\\', substr($className, $this->prefixLength));
+            $filepath = $this->directory.DIRECTORY_SEPARATOR.implode(DIRECTORY_SEPARATOR, $parts).'.php';
+
+            if (is_file($filepath)) {
+                require($filepath);
+            }
+        }
+    }
+}

+ 10 - 10
RNCryptor.php → lib/RNCryptor/Cryptor.php

@@ -1,7 +1,7 @@
 <?php
-require_once __DIR__ . '/functions.php';
+namespace RNCryptor;
 
-class RNCryptor {
+class Cryptor {
 
 	const DEFAULT_SCHEMA_VERSION = 3;
 
@@ -9,24 +9,24 @@ class RNCryptor {
 
 	public function __construct() {
 		if (!extension_loaded('mcrypt')) {
-			throw new Exception('The mcrypt extension is missing.');
+			throw new \Exception('The mcrypt extension is missing.');
 		}
 	}
 
 	protected function _configureSettings($version) {
 
-		$settings = new stdClass();
+		$settings = new \stdClass();
 
 		$settings->algorithm = MCRYPT_RIJNDAEL_128;
 		$settings->saltLength = 8;
 		$settings->ivLength = 16;
 
-		$settings->pbkdf2 = new stdClass();
+		$settings->pbkdf2 = new \stdClass();
 		$settings->pbkdf2->prf = 'sha1';
 		$settings->pbkdf2->iterations = 10000;
 		$settings->pbkdf2->keyLength = 32;
 		
-		$settings->hmac = new stdClass();
+		$settings->hmac = new \stdClass();
 		$settings->hmac->length = 32;
 
 		switch ($version) {
@@ -67,12 +67,12 @@ class RNCryptor {
 				break;
 
 			default:
-				throw new Exception('Unsupported schema version ' . $version);
+				throw new \Exception('Unsupported schema version ' . $version);
 		}
-		
+
 		$this->_settings = $settings;
 	}
-	
+
 	/**
 	 * Encrypt or decrypt using AES CTR Little Endian mode
 	 */
@@ -92,7 +92,7 @@ class RNCryptor {
 		return $payload ^ mcrypt_encrypt($this->_settings->algorithm, $key, $counter, 'ecb');
 	}
 
-	protected function _generateHmac(stdClass $components, $hmacKey) {
+	protected function _generateHmac(\stdClass $components, $hmacKey) {
 	
 		$hmacMessage = '';
 		if ($this->_settings->hmac->includesHeader) {

+ 3 - 3
RNDecryptor.php → lib/RNCryptor/Decryptor.php

@@ -1,5 +1,5 @@
 <?php
-require_once __DIR__ . '/RNCryptor.php';
+namespace RNCryptor;
 
 /**
  * RNDecryptor for PHP
@@ -7,7 +7,7 @@ require_once __DIR__ . '/RNCryptor.php';
  * Decrypt data interchangeably with Rob Napier's Objective-C implementation
  * of RNCryptor
  */
-class RNDecryptor extends RNCryptor {
+class Decryptor extends Cryptor {
 
 	/**
 	 * Decrypt RNCryptor-encrypted data
@@ -45,7 +45,7 @@ class RNDecryptor extends RNCryptor {
 
 		$binaryData = base64_decode($encryptedBase64Data);
 
-		$components = new stdClass();
+		$components = new \stdClass();
 		$components->headers = $this->_parseHeaders($binaryData);
 
 		$components->hmac = substr($binaryData, - $this->_settings->hmac->length);

+ 9 - 10
RNEncryptor.php → lib/RNCryptor/Encryptor.php

@@ -1,6 +1,5 @@
 <?php
-
-require_once __DIR__ . '/RNCryptor.php';
+namespace RNCryptor;
 
 /**
  * RNEncryptor for PHP
@@ -8,7 +7,7 @@ require_once __DIR__ . '/RNCryptor.php';
  * Encrypt data interchangeably with Rob Napier's Objective-C implementation
  * of RNCryptor
  */
-class RNEncryptor extends RNCryptor {
+class Encryptor extends Cryptor {
 
 	/**
 	 * Encrypt plaintext using RNCryptor's algorithm
@@ -16,10 +15,10 @@ class RNEncryptor extends RNCryptor {
 	 * @param string $plaintext Text to be encrypted
 	 * @param string $password Password to use
 	 * @param int $version (Optional) RNCryptor schema version to use.
-	 * @throws Exception If the provided version (if any) is unsupported
+	 * @throws \Exception If the provided version (if any) is unsupported
 	 * @return string Encrypted, Base64-encoded string
 	 */
-	public function encrypt($plaintext, $password, $version = RNCryptor::DEFAULT_SCHEMA_VERSION) {
+	public function encrypt($plaintext, $password, $version = Cryptor::DEFAULT_SCHEMA_VERSION) {
 
 		$this->_configureSettings($version);
 
@@ -34,7 +33,7 @@ class RNEncryptor extends RNCryptor {
 		return $this->_encrypt($plaintext, $components, $encKey, $hmacKey);
 	}
 
-	public function encryptWithArbitrarySalts($plaintext, $password, $encSalt, $hmacSalt, $iv, $version = RNCryptor::DEFAULT_SCHEMA_VERSION) {
+	public function encryptWithArbitrarySalts($plaintext, $password, $encSalt, $hmacSalt, $iv, $version = Cryptor::DEFAULT_SCHEMA_VERSION) {
 	
 		$this->_configureSettings($version);
 
@@ -49,7 +48,7 @@ class RNEncryptor extends RNCryptor {
 		return $this->_encrypt($plaintext, $components, $encKey, $hmacKey);
 	}
 
-	public function encryptWithArbitraryKeys($plaintext, $encKey, $hmacKey, $iv, $version = RNCryptor::DEFAULT_SCHEMA_VERSION) {
+	public function encryptWithArbitraryKeys($plaintext, $encKey, $hmacKey, $iv, $version = Cryptor::DEFAULT_SCHEMA_VERSION) {
 
 		$this->_configureSettings($version);
 
@@ -63,15 +62,15 @@ class RNEncryptor extends RNCryptor {
 
 	private function _generateInitializedComponents($version) {
 
-		$components = new stdClass();
-		$components->headers = new stdClass();
+		$components = new \stdClass();
+		$components->headers = new \stdClass();
 		$components->headers->version = chr($version);
 		$components->headers->options = chr($this->_settings->options);
 
 		return $components;
 	}
 
-	private function _encrypt($plaintext, stdClass $components, $encKey, $hmacKey) {
+	private function _encrypt($plaintext, \stdClass $components, $encKey, $hmacKey) {
 	
 		switch ($this->_settings->mode) {
 			case 'ctr':

+ 54 - 0
lib/bootstrap.php

@@ -0,0 +1,54 @@
+<?php
+
+require dirname(__FILE__) . '/RNCryptor/Autoloader.php';
+RNCryptor_Autoloader::register();
+
+if (!function_exists('hash_pbkdf2')) {
+
+	/**
+	 * Based on pbkdf2() from https://defuse.ca/php-pbkdf2.htm. Made signature-compatible with hash_pbkdf2() in PHP5.5
+	 *
+	 * PBKDF2 key derivation function as defined by RSA's PKCS #5: https://www.ietf.org/rfc/rfc2898.txt
+	 * $algorithm - The hash algorithm to use. Recommended: SHA256
+	 * $password - The password.
+	 * $salt - A salt that is unique to the password.
+	 * $count - Iteration count. Higher is better, but slower. Recommended: At least 1000.
+	 * $key_length - The length of the derived key in bytes.
+	 * $raw_output - If true, the key is returned in raw binary format. Hex encoded otherwise.
+	 * Returns: A $key_length-byte key derived from the password and salt.
+	 *
+	 * Test vectors can be found here: https://www.ietf.org/rfc/rfc6070.txt
+	 *
+	 * This implementation of PBKDF2 was originally created by https://defuse.ca
+	 * With improvements by http://www.variations-of-shadow.com
+	 */
+	function hash_pbkdf2($algorithm, $password, $salt, $count, $key_length = 0, $raw_output = false)
+	{
+		$algorithm = strtolower($algorithm);
+		if(!in_array($algorithm, hash_algos(), true))
+			die('PBKDF2 ERROR: Invalid hash algorithm.');
+		if($count <= 0 || $key_length <= 0)
+			die('PBKDF2 ERROR: Invalid parameters.');
+
+		$hash_length = strlen(hash($algorithm, "", true));
+		$block_count = ceil($key_length / $hash_length);
+
+		$output = "";
+		for($i = 1; $i <= $block_count; $i++) {
+			// $i encoded as 4 bytes, big endian.
+			$last = $salt . pack("N", $i);
+			// first iteration
+			$last = $xorsum = hash_hmac($algorithm, $last, $password, true);
+			// perform the other $count - 1 iterations
+			for ($j = 1; $j < $count; $j++) {
+				$xorsum ^= ($last = hash_hmac($algorithm, $last, $password, true));
+			}
+			$output .= $xorsum;
+		}
+
+		if($raw_output)
+			return substr($output, 0, $key_length);
+		else
+			return bin2hex(substr($output, 0, $key_length));
+	}
+}

+ 20 - 0
phpunit.xml.dist

@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<phpunit bootstrap="tests/bootstrap.php" colors="true" strict="true">
+    <testsuites>
+        <testsuite name="RNCryptor Test Suite">
+            <directory>tests/RNCryptor/</directory>
+        </testsuite>
+    </testsuites>
+
+    <filter>
+        <whitelist>
+            <directory suffix=".php">lib/RNCryptor/</directory>
+        </whitelist>
+    </filter>
+    
+    <logging>
+        <log type="coverage-html" target="./tests/coverage" charset="UTF-8"
+             yui="true" highlight="false" lowUpperBound="35" highLowerBound="70" />
+    </logging>
+</phpunit>

+ 25 - 32
tests/tests/RNCryptorTest.php → tests/RNCryptor/CryptorTest.php

@@ -1,9 +1,7 @@
 <?php
+namespace RNCryptor;
 
-require_once __DIR__ . '/../../RNDecryptor.php';
-require_once __DIR__ . '/../../RNEncryptor.php';
-
-class RNCryptorTest extends PHPUnit_Framework_TestCase {
+class CryptorTest extends \PHPUnit_Framework_TestCase {
 
 	// relative to __DIR__
 	const TEXT_FILENAME = 'lorem-ipsum.txt';
@@ -19,46 +17,46 @@ class RNCryptorTest extends PHPUnit_Framework_TestCase {
     }
 
   	public function testCanDecryptSelfEncryptedDefaultVersion() {
-  		$encryptor = new RNEncryptor();
+  		$encryptor = new Encryptor();
   		$encrypted = $encryptor->encrypt(self::SAMPLE_PLAINTEXT, self::SAMPLE_PASSWORD);
   		
-  		$decryptor = new RNDecryptor();
+  		$decryptor = new Decryptor();
   		$decrypted = $decryptor->decrypt($encrypted, self::SAMPLE_PASSWORD);
   		$this->assertEquals(self::SAMPLE_PLAINTEXT, $decrypted);
   	}
 
   	public function testCanDecryptSelfEncryptedStringEqualToBlockSizeMultiple() {
-  		$encryptor = new RNEncryptor();
+  		$encryptor = new Encryptor();
   		$encrypted = $encryptor->encrypt(self::SAMPLE_PLAINTEXT_V2_BLOCKSIZE, self::SAMPLE_PASSWORD);
   	
-  		$decryptor = new RNDecryptor();
+  		$decryptor = new Decryptor();
   		$decrypted = $decryptor->decrypt($encrypted, self::SAMPLE_PASSWORD);
   		$this->assertEquals(self::SAMPLE_PLAINTEXT_V2_BLOCKSIZE, $decrypted);
   	}
 
   	public function testCanDecryptSelfEncryptedVersion0() {
-  		$encryptor = new RNEncryptor();
+  		$encryptor = new Encryptor();
   		$encrypted = $encryptor->encrypt(self::SAMPLE_PLAINTEXT, self::SAMPLE_PASSWORD, 0);
   		
-  		$decryptor = new RNDecryptor();
+  		$decryptor = new Decryptor();
   		$decrypted = $decryptor->decrypt($encrypted, self::SAMPLE_PASSWORD);
   		$this->assertEquals(self::SAMPLE_PLAINTEXT, $decrypted);
   	}
 
   	public function testCanDecryptSelfEncryptedVersion1() {
-  		$encryptor = new RNEncryptor();
+  		$encryptor = new Encryptor();
   		$encrypted = $encryptor->encrypt(self::SAMPLE_PLAINTEXT, self::SAMPLE_PASSWORD, 1);
   		
-  		$decryptor = new RNDecryptor();
+  		$decryptor = new Decryptor();
   		$decrypted = $decryptor->decrypt($encrypted, self::SAMPLE_PASSWORD);
   		$this->assertEquals(self::SAMPLE_PLAINTEXT, $decrypted);
   	}
   	
   	public function testCanDecryptSelfEncryptedVersion2() {
-  		$encryptor = new RNEncryptor();
+  		$encryptor = new Encryptor();
   		$encrypted = $encryptor->encrypt(self::SAMPLE_PLAINTEXT, self::SAMPLE_PASSWORD, 2);
   	
-  		$decryptor = new RNDecryptor();
+  		$decryptor = new Decryptor();
   		$decrypted = $decryptor->decrypt($encrypted, self::SAMPLE_PASSWORD);
   		$this->assertEquals(self::SAMPLE_PLAINTEXT, $decrypted);
   	}
@@ -67,61 +65,61 @@ class RNCryptorTest extends PHPUnit_Framework_TestCase {
 
   		$text = file_get_contents(__DIR__ . '/_files/lorem-ipsum.txt');
   	
-  		$encryptor = new RNEncryptor();
+  		$encryptor = new Encryptor();
   		$encrypted = $encryptor->encrypt($text, self::SAMPLE_PASSWORD);
   	
-  		$decryptor = new RNDecryptor();
+  		$decryptor = new Decryptor();
   		$decrypted = $decryptor->decrypt($encrypted, self::SAMPLE_PASSWORD);
   		$this->assertEquals($text, $decrypted);
   	}
 
   	public function testVersion1TruncatesMultibytePasswords() {
   		$password1 = '中文密码';
-  		$encryptor = new RNEncryptor();
+  		$encryptor = new Encryptor();
   		$encrypted = $encryptor->encrypt(self::SAMPLE_PLAINTEXT, $password1, 1);
 
   		// Yikes, it's truncated! So with an all-multibyte password
   		// like above, we can replace the last half of the string
   		// with whatver we want, and decryption will still work.
   		$password2 = '中文中文';
-  		$decryptor = new RNDecryptor();
+  		$decryptor = new Decryptor();
   		$decrypted = $decryptor->decrypt($encrypted, $password2);
   		$this->assertEquals(self::SAMPLE_PLAINTEXT, $decrypted);
   	
-  		$decryptor = new RNDecryptor();
+  		$decryptor = new Decryptor();
   		$decrypted = $decryptor->decrypt($encrypted, $password1);
   		$this->assertEquals(self::SAMPLE_PLAINTEXT, $decrypted);
   	}
 
   	public function testVersion2TruncatesMultibytePasswords() {
   		$password1 = '中文密码';
-  		$encryptor = new RNEncryptor();
+  		$encryptor = new Encryptor();
   		$encrypted = $encryptor->encrypt(self::SAMPLE_PLAINTEXT, $password1, 2);
 
   		// Yikes, it's truncated! So with an all-multibyte password
   		// like above, we can replace the last half of the string
   		// with whatver we want, and decryption will still work.
   		$password2 = '中文中文';
-  		$decryptor = new RNDecryptor();
+  		$decryptor = new Decryptor();
   		$decrypted = $decryptor->decrypt($encrypted, $password2);
   		$this->assertEquals(self::SAMPLE_PLAINTEXT, $decrypted);
 
-  		$decryptor = new RNDecryptor();
+  		$decryptor = new Decryptor();
   		$decrypted = $decryptor->decrypt($encrypted, $password1);
   		$this->assertEquals(self::SAMPLE_PLAINTEXT, $decrypted);
   	}
 
   	public function testVersion3AcceptsMultibytePasswords() {
   		$password1 = '中文密码';
-  		$encryptor = new RNEncryptor();
+  		$encryptor = new Encryptor();
   		$encrypted = $encryptor->encrypt(self::SAMPLE_PLAINTEXT, $password1, 3);
 
   		$password2 = '中文中文';
-  		$decryptor = new RNDecryptor();
+  		$decryptor = new Decryptor();
   		$decrypted = $decryptor->decrypt($encrypted, $password2);
   		$this->assertFalse($decrypted);
 
-  		$decryptor = new RNDecryptor();
+  		$decryptor = new Decryptor();
   		$decrypted = $decryptor->decrypt($encrypted, $password1);
   		$this->assertEquals(self::SAMPLE_PLAINTEXT, $decrypted);
   	}
@@ -129,13 +127,13 @@ class RNCryptorTest extends PHPUnit_Framework_TestCase {
   	public function testCannotUseWithUnsupportedSchemaVersions() {
   		$fakeSchemaNumber = 57;
   		$encrypted = $this->_generateEncryptedStringWithUnsupportedSchemaNumber($fakeSchemaNumber);
-  		$decryptor = new RNDecryptor();
+  		$decryptor = new Decryptor();
   		$this->setExpectedException('Exception');
   		$decryptor->decrypt($encrypted, self::SAMPLE_PASSWORD);
   	}
 
   	private function _generateEncryptedStringWithUnsupportedSchemaNumber($fakeSchemaNumber) {
-  		$encryptor = new RNEncryptor();
+  		$encryptor = new Encryptor();
   		$plaintext = 'The price of ice is nice for mice';
   		$encrypted = $encryptor->encrypt($plaintext, self::SAMPLE_PASSWORD);
 
@@ -144,8 +142,3 @@ class RNCryptorTest extends PHPUnit_Framework_TestCase {
   		return base64_encode($encryptedBinary);
   	}
 }
-
-if (!defined('PHPUnit_MAIN_METHOD') || PHPUnit_MAIN_METHOD == 'RNCryptorTest::main') {
-	RNCryptorTest::main();
-}
-

+ 14 - 25
tests/tests/RNDecryptorTest.php → tests/RNCryptor/DecryptorTest.php

@@ -1,8 +1,7 @@
 <?php
+namespace RNCryptor;
 
-require_once __DIR__ . '/../../RNDecryptor.php';
-
-class RNDecryptorTest extends PHPUnit_Framework_TestCase {
+class DecryptorTest extends \PHPUnit_Framework_TestCase {
 
 	const IOS_PASSWORD = 'mypassword123$!';
 
@@ -30,86 +29,76 @@ class RNDecryptorTest extends PHPUnit_Framework_TestCase {
 	const PLAINTEXT_V2_NON_BLOCK_INTERVAL = 'Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do...';
 	const IOS_ENCRYPTED_V2_NON_BLOCK_INTERVAL = 'AgG8X+ixN6HN9zFnuK1NMJAPntIuC0+WPsmFhGL314zLuq1T9xWDHYzpnzW8EqDz81Amj36+EqrjazQ1gO9ao6bpMwUKdT2xY4ZUrhtCQm3LD2okbEIGjj5dtMJtB3i759WdnmNf8K0ULDWNzNQHPzdNDcEE2BPh+2kRaqVzWyBOzJppJoD5n+WdglS7BEBU+4U=';
 
-	public static function main() {
-		$suite  = new PHPUnit_Framework_TestSuite(get_called_class());
-		$result = PHPUnit_TextUI_TestRunner::run($suite);
-	}
-
   	public function testCanDecryptIosEncryptedVersion0WithPlaintextLengthLessThanOneBlock() {
-  		$decryptor = new RNDecryptor();
+  		$decryptor = new Decryptor();
   		$decrypted = $decryptor->decrypt(self::IOS_ENCRYPTED_V0_LESS_THAN_ONE_BLOCK, self::IOS_PASSWORD);
   		$this->assertEquals(self::PLAINTEXT_V0_LESS_THAN_ONE_BLOCK, $decrypted);
   	}
 
   	public function testCanDecryptIosEncryptedVersion0WithPlaintextReallyLong() {
-  		$decryptor = new RNDecryptor();
+  		$decryptor = new Decryptor();
   		$decrypted = $decryptor->decrypt(file_get_contents(__DIR__ . '/_files/lorem-ipsum-encrypted-base64-schema0.txt'), self::IOS_PASSWORD);
   		$this->assertEquals(file_get_contents(__DIR__ . '/_files/lorem-ipsum.txt'), $decrypted);
   	}
 
   	public function testCanDecryptIosEncryptedVersion0WithPlaintextLengthExactlyOneBlock() {
-  		$decryptor = new RNDecryptor();
+  		$decryptor = new Decryptor();
   		$decrypted = $decryptor->decrypt(self::IOS_ENCRYPTED_V0_EXACTLY_ONE_BLOCK, self::IOS_PASSWORD);
   		$this->assertEquals(self::PLAINTEXT_V0_EXACTLY_ONE_BLOCK, $decrypted);
   	}
 
   	public function testCanDecryptIosEncryptedVersion0WithPlaintextLengthExactlyTwoBlocks() {
-  		$decryptor = new RNDecryptor();
+  		$decryptor = new Decryptor();
   		$decrypted = $decryptor->decrypt(self::IOS_ENCRYPTED_V0_EXACTLY_TWO_BLOCKS, self::IOS_PASSWORD);
   		$this->assertEquals(self::PLAINTEXT_V0_EXACTLY_TWO_BLOCKS, $decrypted);
   	}
   	
   	public function testCanDecryptIosEncryptedVersion0WithPlaintextLengthNotOnBlockInterval() {
-  		$decryptor = new RNDecryptor();
+  		$decryptor = new Decryptor();
   		$decrypted = $decryptor->decrypt(self::IOS_ENCRYPTED_V0_NON_BLOCK_INTERVAL, self::IOS_PASSWORD);
   		$this->assertEquals(self::PLAINTEXT_V0_NON_BLOCK_INTERVAL, $decrypted);
   	}
 
   	public function testCanDecryptIosEncryptedVersion1WithPlaintextReallyLong() {
-  		$decryptor = new RNDecryptor();
+  		$decryptor = new Decryptor();
   		$decrypted = $decryptor->decrypt(file_get_contents(__DIR__ . '/_files/lorem-ipsum-encrypted-base64-schema1.txt'), self::IOS_PASSWORD);
   		$this->assertEquals(file_get_contents(__DIR__ . '/_files/lorem-ipsum.txt'), $decrypted);
   	}
 
   	public function testCanDecryptIosEncryptedVersion1WithPlaintextLengthExactlyOneBlock() {
-  		$decryptor = new RNDecryptor();
+  		$decryptor = new Decryptor();
   		$decrypted = $decryptor->decrypt(self::IOS_ENCRYPTED_V1_EXACTLY_ONE_BLOCK, self::IOS_PASSWORD);
   		$this->assertEquals(self::PLAINTEXT_V1_EXACTLY_ONE_BLOCK, $decrypted);
   	}
 
   	public function testCanDecryptIosEncryptedVersion1WithPlaintextLengthNotOnBlockInterval() {
-  		$decryptor = new RNDecryptor();
+  		$decryptor = new Decryptor();
   		$decrypted = $decryptor->decrypt(self::IOS_ENCRYPTED_V1_NON_BLOCK_INTERVAL, self::IOS_PASSWORD);
   		$this->assertEquals(self::PLAINTEXT_V1_NON_BLOCK_INTERVAL, $decrypted);
   	}
 
   	public function testCanDecryptIosEncryptedVersion2WithPlaintextReallyLong() {
-  		$decryptor = new RNDecryptor();
+  		$decryptor = new Decryptor();
   		$decrypted = $decryptor->decrypt(file_get_contents(__DIR__ . '/_files/lorem-ipsum-encrypted-base64-schema2.txt'), self::IOS_PASSWORD);
   		$this->assertEquals(file_get_contents(__DIR__ . '/_files/lorem-ipsum.txt'), $decrypted);
   	}
 
   	public function testCanDecryptIosEncryptedVersion2WithPlaintextLengthExactlyOneBlock() {
-  		$decryptor = new RNDecryptor();
+  		$decryptor = new Decryptor();
   		$decrypted = $decryptor->decrypt(self::IOS_ENCRYPTED_V2_EXACTLY_ONE_BLOCK, self::IOS_PASSWORD);
   		$this->assertEquals(self::PLAINTEXT_V2_EXACTLY_ONE_BLOCK, $decrypted);
   	}
 
   	public function testCanDecryptIosEncryptedVersion2WithPlaintextLengthNotOnBlockInterval() {
-  		$decryptor = new RNDecryptor();
+  		$decryptor = new Decryptor();
   		$decrypted = $decryptor->decrypt(self::IOS_ENCRYPTED_V2_NON_BLOCK_INTERVAL, self::IOS_PASSWORD);
   		$this->assertEquals(self::PLAINTEXT_V2_NON_BLOCK_INTERVAL, $decrypted);
   	}
 
   	public function testDecryptingWithBadPasswordFails() {
-  		$decryptor = new RNDecryptor();
+  		$decryptor = new Decryptor();
   		$decrypted = $decryptor->decrypt(self::IOS_ENCRYPTED_V2_NON_BLOCK_INTERVAL, 'bad-password');
   		$this->assertEquals(false, $decrypted);
   	}
   	
 }
-
-if (!defined('PHPUnit_MAIN_METHOD') || PHPUnit_MAIN_METHOD == 'RNDecryptorTest::main') {
-	RNDecryptorTest::main();
-}
-

+ 9 - 20
tests/tests/RNEncryptorTest.php → tests/RNCryptor/EncryptorTest.php

@@ -1,65 +1,54 @@
 <?php
+namespace RNCryptor;
 
-require_once __DIR__ . '/../../RNEncryptor.php';
-
-class RNEncryptorTest extends PHPUnit_Framework_TestCase {
+class EncryptorTest extends \PHPUnit_Framework_TestCase {
 
 	const SAMPLE_PLAINTEXT = 'Hello, how are you today?  I am doing fine.';
 	const SAMPLE_PASSWORD = 'keep-out-123';
 
-    public static function main() {
-        $suite  = new PHPUnit_Framework_TestSuite(get_called_class());
-        $result = PHPUnit_TextUI_TestRunner::run($suite);
-    }
-
     public function testCanEncryptWithDefaultVersion() {
-    	$encryptor = new RNEncryptor();
+    	$encryptor = new Encryptor();
     	$encrypted = $encryptor->encrypt(self::SAMPLE_PLAINTEXT, self::SAMPLE_PASSWORD);
     	$this->assertNotEmpty($encrypted);
     }
 
     public function testCanEncryptWithVersion0() {
-    	$encryptor = new RNEncryptor();
+    	$encryptor = new Encryptor();
     	$encrypted = $encryptor->encrypt(self::SAMPLE_PLAINTEXT, self::SAMPLE_PASSWORD, 0);
     	$this->assertNotEmpty($encrypted);
     }
     
     public function testCanEncryptWithVersion1() {
-    	$encryptor = new RNEncryptor();
+    	$encryptor = new Encryptor();
     	$encrypted = $encryptor->encrypt(self::SAMPLE_PLAINTEXT, self::SAMPLE_PASSWORD, 1);
     	$this->assertNotEmpty($encrypted);
     }
     
     public function testCanEncryptWithVersion2() {
-    	$encryptor = new RNEncryptor();
+    	$encryptor = new Encryptor();
     	$encrypted = $encryptor->encrypt(self::SAMPLE_PLAINTEXT, self::SAMPLE_PASSWORD, 2);
     	$this->assertNotEmpty($encrypted);
     }
 
     public function testSelfEncryptedVersion0VectorIsVersion0() {
-    	$encryptor = new RNEncryptor();
+    	$encryptor = new Encryptor();
     	$encrypted = $encryptor->encrypt(self::SAMPLE_PLAINTEXT, self::SAMPLE_PASSWORD, 0);
     	$actualVersion = ord(substr(base64_decode($encrypted), 0, 1));
     	$this->assertEquals(0, $actualVersion);
     }
     
     public function testSelfEncryptedVersion1VectorIsVersion1() {
-    	$encryptor = new RNEncryptor();
+    	$encryptor = new Encryptor();
     	$encrypted = $encryptor->encrypt(self::SAMPLE_PLAINTEXT, self::SAMPLE_PASSWORD, 1);
     	$actualVersion = ord(substr(base64_decode($encrypted), 0, 1));
     	$this->assertEquals(1, $actualVersion);
     }
 
     public function testSelfEncryptedVersion2VectorIsVersion2() {
-    	$encryptor = new RNEncryptor();
+    	$encryptor = new Encryptor();
     	$encrypted = $encryptor->encrypt(self::SAMPLE_PLAINTEXT, self::SAMPLE_PASSWORD, 2);
     	$actualVersion = ord(substr(base64_decode($encrypted), 0, 1));
     	$this->assertEquals(2, $actualVersion);
     }
 
 }
-
-if (!defined('PHPUnit_MAIN_METHOD') || PHPUnit_MAIN_METHOD == 'RNEncryptorTest::main') {
-	RNEncryptorTest::main();
-}
-

+ 7 - 9
tests/tests/VectorTest.php → tests/RNCryptor/VectorTest.php

@@ -1,22 +1,20 @@
 <?php
+namespace RNCryptor;
 
-require_once __DIR__ . '/../../RNDecryptor.php';
-require_once __DIR__ . '/../../RNEncryptor.php';
-
-class VectorBase extends PHPUnit_Framework_TestCase {
+class VectorBase extends \PHPUnit_Framework_TestCase {
 
 	/**
 	 * Base directory for the test vector files,
 	 * relative to __DIR__
 	 */
-	const VECTOR_DIR = '/../../../vectors';
+	const VECTOR_DIR = '/../../vendor/rncryptor/rncryptor-spec/vectors/CURRENT';
 
 	public function testKdfVectors() {
 
 		$vectors = $this->_getVectors('kdf');
 		foreach ($vectors as $vector) {
 	
-			$cryptor = new RNCryptor();
+			$cryptor = new Cryptor();
 			$key = $cryptor->generateKey(
 				$this->_prettyHexToBin($vector['salt_hex']),
 				$vector['password'],
@@ -35,7 +33,7 @@ class VectorBase extends PHPUnit_Framework_TestCase {
 		$vectors = $this->_getVectors('key');
 		foreach ($vectors as $vector) {
 	
-			$encryptor = new RNEncryptor();
+			$encryptor = new Encryptor();
 			$encryptedB64 = $encryptor->encryptWithArbitraryKeys(
 				$this->_prettyHexToBin($vector['plaintext_hex']),
 				$this->_prettyHexToBin($vector['enc_key_hex']),
@@ -56,7 +54,7 @@ class VectorBase extends PHPUnit_Framework_TestCase {
 		$vectors = $this->_getVectors('password');
 		foreach ($vectors as $vector) {
 
-			$encryptor = new RNEncryptor();
+			$encryptor = new Encryptor();
 			$encryptedB64 = $encryptor->encryptWithArbitrarySalts(
 				$this->_prettyHexToBin($vector['plaintext_hex']),
 				$vector['password'],
@@ -92,7 +90,7 @@ class VectorBase extends PHPUnit_Framework_TestCase {
 
 		$absolutePath = __DIR__ . '/' . self::VECTOR_DIR . '/' . $filename;
 		if (!file_exists($absolutePath)) {
-			throw new Exception('No such file: ' . $absolutePath);
+			throw new \Exception('No such file: ' . $absolutePath);
 		}
 
 		$index = -1;

+ 0 - 0
tests/tests/_files/lorem-ipsum-encrypted-base64-schema0.txt → tests/RNCryptor/_files/lorem-ipsum-encrypted-base64-schema0.txt


+ 0 - 0
tests/tests/_files/lorem-ipsum-encrypted-base64-schema1.txt → tests/RNCryptor/_files/lorem-ipsum-encrypted-base64-schema1.txt


+ 0 - 0
tests/tests/_files/lorem-ipsum-encrypted-base64-schema2.txt → tests/RNCryptor/_files/lorem-ipsum-encrypted-base64-schema2.txt


+ 0 - 0
tests/tests/_files/lorem-ipsum.txt → tests/RNCryptor/_files/lorem-ipsum.txt


+ 16 - 13
tests/bootstrap.php

@@ -1,17 +1,20 @@
 <?php
-error_reporting(E_ALL | E_STRICT);
 
-if (!function_exists('hex2bin')) {
+/*
+ * This file is part of the RNCryptor package.
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
 
-	/**
-	 * If the PHP version being used is earlier than 5.4.0, we need to
-	 * make up for the lack of a hex2bin() function.
-	 */
-	function hex2bin($data) {
-		$bin = '';
-		foreach (str_split($data, 2) as $pair) {
-			$bin .= chr(hexdec($pair));
-		}
-		return $bin;
-	}
+if (file_exists(__DIR__.'/../autoload.php')) {
+    require __DIR__.'/../autoload.php';
+
+} else if (@include('RNCryptor/Autoloader.php')) {
+    RNCryptor\Autoloader::register();
+
+} else {
+    die('ERROR: Unable to find a suitable mean to register RNCryptor\Autoloader.');
 }
+
+require_once __DIR__ . '/functions.php';

+ 16 - 0
tests/functions.php

@@ -0,0 +1,16 @@
+<?php
+
+if (!function_exists('hex2bin')) {
+
+	/**
+	 * If the PHP version being used is earlier than 5.4.0, we need to
+	 * make up for the lack of a hex2bin() function.
+	 */
+	function hex2bin($data) {
+		$bin = '';
+		foreach (str_split($data, 2) as $pair) {
+			$bin .= chr(hexdec($pair));
+		}
+		return $bin;
+	}
+}

+ 0 - 1
tests/phpunit

@@ -1 +0,0 @@
-pear/phpunit

+ 0 - 14
tests/phpunit.xml

@@ -1,14 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<phpunit bootstrap="./bootstrap.php" colors="true">
-
-    <testsuite name="RNCryptor PHP - Test Suite">
-        <directory>./tests/</directory>
-    </testsuite>
-
-    <logging>
-        <log type="coverage-html" target="./coverage" charset="UTF-8"
-             yui="true" highlight="false" lowUpperBound="35" highLowerBound="70" />
-    </logging>
-
-</phpunit>
-