Page 1 of 1

Encryption class

Posted: Sat Aug 04, 2007 6:00 am
by neel_basu
Hi! all if you dont have mCrypt you can use this Encryption class
(based on XOR Encryption)
Plese post if you find any bugs.

Code: Select all

class crytpo{
/*
Encryptor Class without mcrypt
Author Neel basu
This is a Pre release beta of Zogmoyd's next version's Level 1 Encryption Class
Made on july 15 2007. Its Under GPL Licence
Please see GNU GPL before using it. 
you can Use it Untill the above message is intact.
*/
private $val;
public function __construct(){
	if(!defined('BLOCK_SIZE')){define('BLOCK_SIZE', 4);}
	if(!defined('BLOCK_JUNK')){define('BLOCK_JUNK', 5);}
	if(!defined('ENC_BIN')){define('ENC_BIN', true);}
	if(!defined('ENC_DEC')){define('ENC_DEC', false);}
	$this->val = array(' ', '+', '_', '*', '&', ':', '-', '@', '=', '%');
}
private function blockise($str){
	if(strlen($str) >= BLOCK_SIZE*2){return $str;}
	while(strlen($str) < BLOCK_SIZE*2){
		$str .= chr(BLOCK_JUNK);
	}
	return $str;
}
private function dblockise($str){
	for($i=strlen($str)-1;$i>=strlen($str)-1-8;$i--){
		if($str[$i] != chr(BLOCK_JUNK)){break;}
		$str = substr($str, 0, $i);
	}
	return $str;
}
private function psubstr($str, $start, $len){
	if($start < 0){$tmp = "";return $tmp;};
	return substr($str, $start, $len);
}
private function get_block($str, $i){return $this->psubstr($str, $i, BLOCK_SIZE);}
private function x_enc($string, $key){
  for($i=0; $i<=strlen($string)-1; $i++){
    for($j=0; $j<=strlen($key)-1; $j++){
      $string[$i] = $string[$i]^$key[$j];
    }
		if($i != 0 && $i != strlen($string)-1){
			$string[$i] = $string[$i]^$string[$i-1]^$string[$i+1];
		}
  }
 return $string;
}
private function x_dcd($string, $key){
	  for($i=strlen($string)-1; $i>=0; $i--){
		  if($i == 0 || $i == strlen($string)-1){
		    for($j=0; $j<=strlen($key)-1; $j++){
		      $string[$i] = $string[$i]^$key[$j];
		    }
		  }else{
		  	$string[$i] = $this->x_enc($string[$i], $key)^$string[$i-1]^$string[$i+1];
		  }
	 }
	return $string;
}
private function enc($str, $key){
	$str = base64_encode($this->blockise($str));
	for($i=0;$i<=strlen($str)-1;$i+=BLOCK_SIZE){
		if($i == 0 || $i == (strlen($str)-BLOCK_SIZE)){
			$repl = $this->x_enc($this->psubstr($str, $i, BLOCK_SIZE), $key);
			$str = substr_replace($str, $repl, $i, BLOCK_SIZE);
		}else{
			if($i == BLOCK_SIZE){
				$b = $this->x_enc($this->get_block($str, $i), $key);
			}
			$repl = $this->x_enc($this->get_block($str, $i+BLOCK_SIZE), $this->get_block($str, $i-BLOCK_SIZE));
			$str = substr_replace($str, $repl, $i, BLOCK_SIZE);
		}
	}
	$str .= $b;
	return $str;
}
private function dcd($str, $key){
	$b = $this->x_dcd($this->get_block($str, strlen($str)-BLOCK_SIZE), $key);
	$str = substr($str, 0, strlen($str)-BLOCK_SIZE);
	for($i=strlen($str)-BLOCK_SIZE;$i>=0;$i-=BLOCK_SIZE){
		if($i == 0 || $i == (strlen($str)-BLOCK_SIZE)){
			$repl = $this->x_dcd($this->psubstr($str, $i, BLOCK_SIZE), $key);
			$str = substr_replace($str, $repl, $i, BLOCK_SIZE);
		}else{
			if($i == BLOCK_SIZE){
				$str = substr_replace($str, $b, $i, BLOCK_SIZE);
			}else{
				$repl = $this->x_dcd($this->psubstr($str, $i-BLOCK_SIZE, BLOCK_SIZE), $this->psubstr($str, $i-(BLOCK_SIZE*2), BLOCK_SIZE));
				$str = substr_replace($str, $repl, $i, BLOCK_SIZE);
			}
		}
	}
	return $this->dblockise(base64_decode($str));
}
public function encode($str, $key, $mode = ENC_BIN){
	if($mode == ENC_BIN){
		return $this->enc($this->enc($str, $key), md5($key));
	}elseif($mode == ENC_DEC){
		return $this->dec_encode($this->enc($this->enc($str, $key), md5($key)));
	}
	trigger_error("Invalid MODE SPecified", E_ERROR);
	return false;
}
public function decode($str, $key, $mode = ENC_BIN){
	if($mode == ENC_BIN){
		return $this->dcd($this->dcd($str, md5($key)), $key);
	}elseif($mode == ENC_DEC){
		return $this->dcd($this->dcd($this->dec_decode($str), md5($key)),$key);
	}
	trigger_error("Invalid MODE SPecified", E_ERROR);
	return false;
}
private function dec_decode($salted){
		$key = array(0,1,2,3,4,5,6,7,8,9);$ret = '';
    $val = $this->val;
    $str = str_replace($val, $key, $salted);
    for($i=0;$i<=strlen($str)-1;$i+=3){
  		$current_group = $str[$i].$str[$i+1].$str[$i+2];
  		$tmp_int = (int)($current_group);
  		$ret .= chr($tmp_int);
  	}
    return base64_decode($ret);
	}
private function dec_encode($salt){
		$str = base64_encode($salt);$tmp = '';
	  for($i=0;$i<=strlen($str)-1;$i++){
      if(ord($str[$i]) < 100){
        if(ord($str[$i]) > 0 && ord($str[$i]) < 10){
          $num = "00".ord($str[$i]);
        }
        elseif(ord($str[$i]) >= 10 && ord($str[$i]) < 100){
          $num = "0".ord($str[$i]);
        }
      }
      else{
        $num = ord($str[$i]);
      }
      $tmp .= $num;
    }
   $key = array(0,1,2,3,4,5,6,7,8,9);
   $val = $this->val;
   $ret = str_replace($key, $val, $tmp);
   return $ret;
	}
}
------------------------- USAGE ----------------------------------

Code: Select all

<?php
$str = "1111111111111111111111111111111";
$key = "neel";
$crypto = new crytpo();
$e = $crypto->encode($str, $key);
echo "Encrypted \t[".$e."] Length \t".strlen($e)."\n\n";
$d = $crypto->decode($e, $key);
flush();//This is not needed at all.
echo "Decrypted \t[".$d."] Length ".strlen($d)."\n";
?>
Output wrote:Encrypted [
P5q#Qqn_<1gvOkqno4QrjztwFeQ
*T)
bQQvi:j2<] Length 68

Decrypted [1111111111111111111111111111111] Length 31

Code: Select all

<?php
$str = "1111111111111111111111111111111";
$key = "neel";
$crypto = new crytpo();
$e = $crypto->encode($str, $key, ENC_DEC);
echo "Encrypted \t[".$e."] Length \t".strlen($e)."\n\n";
$d = $crypto->decode($e, $key, ENC_DEC);
flush();//This is not needed at all.
echo "Decrypted \t[".$d."] Length ".strlen($d)."\n";
?>
Output wrote:Encrypted [ -@+_ &% =+ @= =_ @* =% %% =* @@ -: =: == @ ++@ @_ --++-+ _ = -: %%+_ -=++%+ ++ @++ &+_ : =& : ++-+_ %=+ % :-+ @= @ @ +_+ %@++ ++_ &=+ +_ + * =: =_+ % =- =_ @ -:++- :* %=++ @& % %%+ @ =%++* =- -: @@ @: @: =_++_+ : =: =_ @@ @@ -- &% @ : %@ =&++_++* @@+ -++% -+] Length 276

Decrypted [1111111111111111111111111111111] Length 31
ENC_DEC is an optional argument that again encrypts the encrypted string with 10 characters

Code: Select all

$this->val = array(' ', '+', '_', '*', '&', ':', '-', '@', '=', '%');
near line 15 . You can change these characters to customize it.
------------------------------ SECURITY --------------------------------------
See here we are encrypting 1111111111111111111111111111 a repetative character string
But see the encrypted String there is no repetation
If you use ENC_DEC the hacker will need to know 11 things
the keyword and that 10 Characters
Thats hardly possible.

Posted: Tue Aug 07, 2007 7:46 am
by Mordred
You broke the first rule for writing home-brew encryption code: Don't.

Encryption is a serious matter, which should be studied long before starting to design and implement algorythms. I haven't studied it even remotely as long as required, but even so can spot problems with your encryption scheme. Moreover your code is written badly, is grossly inefficient and is severely undocumented (which is quite important if you want other people to understand and follow and check your code).

I won't discuss the PHP errors, you're not new to PHP and I'm sure you can read the docs for yourself. The "encryption" though is bad.
First, it has key strength of about 14 bits (theoretical maximum, would be less in real situations) - ~6 bits for the md5 of the key and 8 bits from the key itself, which means bruteforcing is possible in less than 16384 tries. Also, actually only the first and the last chars in a block are encrypted with the key. Which leads to the third problem that if we have a known plaintext in the beginning or the end of a block (quite possible having in mind the low size of the blocks) we can probably recover the unknown bits and decrypt right away.

I'm sorry for the harsh words, but I think you should throw this away, read some books on the subject and start again from scratch, preferably by implementing a known and proven algorythm.

Posted: Tue Aug 07, 2007 8:53 am
by TheMoose

Code: Select all

return $this->enc($this->enc($str, $key), md5($key));
Read the article on security [viewtopic.php?t=62782] and why double hashing things is bad practice.

Posted: Tue Aug 07, 2007 9:13 am
by Mordred
@TheMoose: He's not double-hashing, he's double encrypting. Since his algorythm is flawed and uses only 8 bits from the provided key, double encrypting using the MD5 of the key actually "improves" the security, as it also adds ~6 bits for the MD5(key).

Posted: Tue Aug 07, 2007 9:26 am
by TheMoose
Mordred wrote:@TheMoose: He's not double-hashing, he's double encrypting. Since his algorythm is flawed and uses only 8 bits from the provided key, double encrypting using the MD5 of the key actually "improves" the security, as it also adds ~6 bits for the MD5(key).
Yeah I just skimmed to see what I could find quickly, I didn't look at the formula behind the encryption portion itself.

Posted: Tue Aug 07, 2007 10:27 am
by neel_basu
Mordred wrote:which means bruteforcing is possible in less than 16384 tries
No You left out this line

Code: Select all

$this->enc($this->enc($str, $key), md5($key));
in your calculation.
Mordred wrote:@TheMoose: He's not double-hashing, he's double encrypting. Since his algorythm is flawed and uses only 8 bits from the provided key, double encrypting using the MD5 of the key actually "improves" the security, as it also adds ~6 bits for the MD5(key).
I've no intension to compeat mcrypt. I was just goping to Implement 3DES but due to lack of time . I made this. I had only 2.5 hrs then. Is it possible to do more than this in 2.5 hrs ??
I think you have understood Its a Chaining encryption algo
and to Its number of brute force is more than 16384 and
Mordred wrote:Also, actually only the first and the last chars in a block are encrypted with the key. Which leads to the third problem that if we have a known plaintext in the beginning or the end of a block (quite possible having in mind the low size of the blocks) we can probably recover the unknown bits and decrypt right away.
Ya I know that and thats why its double encrypted.

Posted: Tue Aug 07, 2007 10:29 am
by Z3RO21
neel_basu wrote:
Mordred wrote:which means bruteforcing is possible in less than 16384 tries
No You left out this line

Code: Select all

$this->enc($this->enc($str, $key), md5($key));
in your calculation.
Mordred wrote:@TheMoose: He's not double-hashing, he's double encrypting. Since his algorythm is flawed and uses only 8 bits from the provided key, double encrypting using the MD5 of the key actually "improves" the security, as it also adds ~6 bits for the MD5(key).
I've no intension to compeat mcrypt. I was just goping to Implement 3DES but due to lack of time . I made this. I had only 2.5 hrs then. Is it possible to do more than this in 2.5 hrs ??
I think you have understood Its a Chaining encryption algo
and to Its number of brute force is more than 16384 and
Mordred wrote:Also, actually only the first and the last chars in a block are encrypted with the key. Which leads to the third problem that if we have a known plaintext in the beginning or the end of a block (quite possible having in mind the low size of the blocks) we can probably recover the unknown bits and decrypt right away.
Ya I know that and thats why its double encrypted.
I am learning about cryptography and after learning and understanding the math behind the algorithms it was not hard to implement. I got a blowfish implementation done in under an hour.

And as Mordred said that algorithm not only could be brute force attacked with very few attempts but it is as he said not operating on all the bytes and leaving an open invitation to be decrypted. Start with blowfish it is a very good algorithm to learn it deals with key management, and xor / swap encoding

Posted: Tue Aug 07, 2007 3:09 pm
by Mordred
neel_basu wrote:
Mordred wrote:which means bruteforcing is possible in less than 16384 tries
No You left out this line

Code: Select all

$this->enc($this->enc($str, $key), md5($key));
in your calculation.
On the contrary, I didn't leave it out. Without this line, it's less than 256 tries. You need to understand what you wrote, as you obviously don't see it. So, please write down (with words) what the x_enc() function does.
neel_basu wrote:
Mordred wrote:Also, actually only the first and the last chars in a block are encrypted with the key. Which leads to the third problem that if we have a known plaintext in the beginning or the end of a block (quite possible having in mind the low size of the blocks) we can probably recover the unknown bits and decrypt right away.
Ya I know that and thats why its double encrypted.
I find it quite astonishing that you understand the problem with the first and last chars, and yet insist that double encryption would help. Again, explain the x_enc() function with words and hopefully you'll see it.

I understand that you didn't invest much time in this class, but encryption (and security in general) doesn't care about time spent, it cares only about being thorough. That's why homebrew encryption sucks by definition (unless you're called Bruce Schneier I suppose ;))

Posted: Tue Aug 07, 2007 5:47 pm
by Z3RO21
Mordred wrote:That's why homebrew encryption sucks by definition (unless you're called Bruce Schneier I suppose ;))
:lol: