Browse Source

Merge pull request #11 from JavaMachine/master

Improvements Related [Issue #9]  Thanks @JavaMachine.
Curtis Farnham 8 years ago
parent
commit
a56a1459d9
2 changed files with 51 additions and 10 deletions
  1. 14 0
      lib/RNCryptor/Cryptor.php
  2. 37 10
      lib/RNCryptor/Decryptor.php

+ 14 - 0
lib/RNCryptor/Cryptor.php

@@ -123,6 +123,11 @@ class Cryptor {
 		return $this->_generateKey($salt, $password);
 	}
 
+	public function generateSalt($version = self::DEFAULT_SCHEMA_VERSION) {
+		$this->_configureSettings($version);
+		return $this->_generateIv($this->_settings->saltLength);
+	}
+
 	protected function _generateKey($salt, $password) {
 
 		if ($this->_settings->truncatesMultibytePasswords) {
@@ -133,4 +138,13 @@ class Cryptor {
 		return hash_pbkdf2($this->_settings->pbkdf2->prf, $password, $salt, $this->_settings->pbkdf2->iterations, $this->_settings->pbkdf2->keyLength, true);
 	}
 
+	private function _generateIv($blockSize) {
+		if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') {
+			$randomSource = MCRYPT_RAND;
+		} else {
+			$randomSource = MCRYPT_DEV_URANDOM;
+		}
+		return mcrypt_create_iv($blockSize, $randomSource);
+	}
+
 }

+ 37 - 10
lib/RNCryptor/Decryptor.php

@@ -26,7 +26,7 @@ class Decryptor extends Cryptor {
 		}
 
 		$key = $this->_generateKey($components->headers->encSalt, $password);
-
+		$plaintext = null;
 		switch ($this->_settings->mode) {
 			case 'ctr':
 				$plaintext = $this->_aesCtrLittleEndianCrypt($components->ciphertext, $key, $components->headers->iv);
@@ -41,22 +41,41 @@ class Decryptor extends Cryptor {
 		return $plaintext;
 	}
 
-	private function _unpackEncryptedBase64Data($encryptedBase64Data) {
+	public function decryptWithArbitraryKeys($encryptedBase64Data, $encKey, $hmacKey) {
+		$components = $this->_unpackEncryptedBase64Data($encryptedBase64Data, false);
+		if (!$this->_hmacIsValid($components, $hmacKey, false)) {
+			return false;
+		}
+		$plaintext = null;
+		switch ($this->_settings->mode) {
+			case 'ctr':
+				$plaintext = $this->_aesCtrLittleEndianCrypt($components->ciphertext, $encKey, $components->headers->iv);
+				break;
+			case 'cbc':
+				$paddedPlaintext = mcrypt_decrypt($this->_settings->algorithm, $encKey, $components->ciphertext, 'cbc', $components->headers->iv);
+				$plaintext = $this->_stripPKCS7Padding($paddedPlaintext);
+				break;
+		}
+		return $plaintext;
+	}
+
+	private function _unpackEncryptedBase64Data($encryptedBase64Data, $isPasswordBased = true) {
 
 		$binaryData = base64_decode($encryptedBase64Data);
 
 		$components = new \stdClass();
-		$components->headers = $this->_parseHeaders($binaryData);
+		$components->headers = $this->_parseHeaders($binaryData, $isPasswordBased);
 
 		$components->hmac = substr($binaryData, - $this->_settings->hmac->length);
 
 		$headerLength = $components->headers->length;
+
 		$components->ciphertext = substr($binaryData, $headerLength, strlen($binaryData) - $headerLength - strlen($components->hmac));
 
 		return $components;
 	}
 
-	private function _parseHeaders($binData) {
+	private function _parseHeaders($binData, $isPasswordBased = true) {
 
 		$offset = 0;
 
@@ -68,11 +87,15 @@ class Decryptor extends Cryptor {
 		$optionsChr = $binData[1];
 		$offset += strlen($optionsChr);
 
-		$encSalt = substr($binData, $offset, $this->_settings->saltLength);
-		$offset += strlen($encSalt);
+		$encSalt = null;
+		$hmacSalt = null;
+		if($isPasswordBased) {
+			$encSalt = substr($binData, $offset, $this->_settings->saltLength);
+			$offset += strlen($encSalt);
 
-		$hmacSalt = substr($binData, $offset, $this->_settings->saltLength);
-		$offset += strlen($hmacSalt);
+			$hmacSalt = substr($binData, $offset, $this->_settings->saltLength);
+			$offset += strlen($hmacSalt);
+		}
 
 		$iv = substr($binData, $offset, $this->_settings->ivLength);
 		$offset += strlen($iv);
@@ -94,8 +117,12 @@ class Decryptor extends Cryptor {
 		return substr($plaintext, 0, strlen($plaintext) - $padLength);
 	}
 
-	private function _hmacIsValid($components, $password) {
-		$hmacKey = $this->_generateKey($components->headers->hmacSalt, $password);
+	private function _hmacIsValid($components, $password, $isPasswordBased = true) {
+		$hmacKey = null;
+		if($isPasswordBased)
+			$hmacKey = $this->_generateKey($components->headers->hmacSalt, $password);
+		else
+			$hmacKey = $password;
 		return hash_equals($components->hmac, $this->_generateHmac($components, $hmacKey));
 	}