Solved

Rijndael 128 bit Encryption with Delphi and PHP

Posted on 2010-08-13
58
4,239 Views
Last Modified: 2013-11-19
Hi.

I'm sending some parameters (string) from my PC using delphi to a PHP script on my website server using the POST method.

The parameters im using should be encrypted. So my delphi program encrypts and sends the encrypted string (parameters) to my PHP script that exists on my website server, and my PHP script should decrypt the parameters. I prefer using rijndael 128 bit encryption but if there's any other encryption method it would be fine. The main point is i want my delphi to encrypt and my PHP script to decrypt the string that delphi encrypted.

I found this package: http://www.cityinthesky.co.uk/cryptography.html it has a  rijndael 128 encryption vcl component for delphi.

It also provides an example on how to encrypt using delphi and php in this link: http://www.cityinthesky.co.uk/files/PHPEncryption.zip.

However, when i test the demo they have, the encrypted string is different in the delphi app than the string in php script.
0
Comment
Question by:JealousyPrince
  • 16
  • 15
  • 9
  • +6
58 Comments
 
LVL 108

Expert Comment

by:Ray Paseur
Comment Utility
Why not do it the easy way and use the conventionally chosen solution, HTTPS?  Writing your own encryption is a little like reinventing, if not the wheel, maybe the gearshift.  Given that all hundreds of billions of dollars of online banking transactions are able to rely on HTTPS, it should be good enough for most of our needs.

If it is useful to you, I can show you the PHP encryption technique.  Please see the code snippet for that.  Can't help with the Delphi part of this, sorry.

Best regards, ~Ray
<?php // RAY_encrypt_decrypt.php
error_reporting(E_ALL);

// MAN PAGE: http://us.php.net/manual/en/ref.mcrypt.php

class Encryption
{
    private $eot;
    private $key;
    private $ivs;
    private $iv;

    public function __construct()
    {
        // END OF TEXT DELIMITER
        $this->eot = '___EOT';
        
        // KEY - MUST BE KNOWN TO BOTH PARTS OF THE ALGORITHM
        $this->key = 'quay';
        
        // INITIALIZATION VECTOR - MUST BE KNOWN TO BOTH PARTS OF THE ALGORITHM
        $this->ivs = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_ECB);
        $this->iv  = mcrypt_create_iv($this->ivs);
    }

    public function Encrypt($text)
    {
        // APPEND END OF TEXT DELIMITER
        $text .= $this->eot; 
        
        // ENCRYPT THE DATA
        $data = mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $this->key, $text, MCRYPT_MODE_ECB, $this->iv);
        
        // MAKE IT base64() STRING SAFE FOR STORAGE AND TRANSMISSION
        $data = base64_encode($data);
        return $data;
    }

    public function Decrypt($text)
    {
        // DECODE THE DATA INTO THE BINARY ENCRYPTED STRING
        $text = base64_decode($text);
        
        // DECRYPT THE STRING
        $data = mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $this->key, $text, MCRYPT_MODE_ECB, $this->iv);
        
        // REMOVE END OF TEXT DELIMITER
        $data = explode($this->eot, $data); 
        return $data[0];
    }
}

// INSTANTIATE THE CLASS
$crypt = new Encryption();

// INITIALIZE VARS FOR LATER USE IN THE HTML FORM
$encoded = '';
$decoded = '';

// IF ANYTHING WAS POSTED
if (!empty($_POST["clearstring"]))
{
    $encoded = $crypt->Encrypt($_POST["clearstring"]);
    echo "<br/>{$_POST["clearstring"]} YIELDS "; var_dump($encoded);
}

if (!empty($_POST["cryptstring"]))
{
    $decoded = $crypt->Decrypt($_POST["cryptstring"]);
    echo "<br/>{$_POST["cryptstring"]} YIELDS "; var_dump($decoded);
}

?>
<form method="post">
<input name="clearstring" value="<?=$decoded?>" />
<input type="submit" value="ENCRYPT" />
<br/>
<input name="cryptstring" value="<?=$encoded?>" />
<input type="submit" value="DECRYPT" />
</form>

Open in new window

0
 
LVL 30

Expert Comment

by:Marco Gasi
Comment Utility
Hi. I had the same problem, with the same package and the same example. The strange thing is that for some period it worked fine! Suddenly, it has began to work not at all. I made sevewral trying, I alse wrote to the author, but without result. I don't know if you are intereted in, but I solved completely changing logic: I've used md5 to hash a certain string and I passed md5 hash to my php application. PHP produces its own hash for the string that it finds in a database and compares hashes. But this only works if the string to encrypt/hash can be in a database (I used this code to validate users). So, if you can use this trick depends by what you are doing.

Hope this helps. Good luck
0
 

Author Comment

by:JealousyPrince
Comment Utility
The problem is that the delphi program sends the computer name and version to the php script and the php script posts the details to the database. Its something like
www.mysite.com/myscript.php and it has two parameters which are computer name and version.

I want the parameters encrypted so that whoever is using the program doesnt play with the parameters and simply change his computer name or version resulting in entering invalid data to the database. margusG Your solution isnt applicable in my case because the database is empty and is willng to accept any computer name and version. I mean i dont have any hash in my database to be compared to. My delphi program will be used by many users.
0
 
LVL 108

Expert Comment

by:Ray Paseur
Comment Utility
Let's step back from this a little bit... can you explain how you validate the information in the "computer name" and "version" data strings?  I am not clear how encryption helps in this case.  Please tell us a little more about the application from the "50,000 foot view" - not the technical details, just what you're trying to do, what data you need to extract and protect, etc.  Thanks.
0
 
LVL 30

Expert Comment

by:Marco Gasi
Comment Utility
Maybe you are interested to read this http://www.experts-exchange.com/Programming/Languages/Pascal/Delphi/Internet/Q_23910465.html?sfQueryTermInfo=1+10+30+delphi+form+php
Here it seems to find a solution to pass some variables from Delphi to PHP using POST method: this way you could avoid to encrypt them because data would not appear in the url. Solution seeems to be ICS components you can find here: http://www.overbyte.be/frame_index.html?redirTo=/products/ics.html I've not tested, so I can't be more descriptive, but you could look at examples to view if truely these components allow to do such a thing.

Bye
0
 
LVL 33

Expert Comment

by:Slick812
Comment Utility
greetings JealousyPrince, , I looked at the code in the -
http://www.cityinthesky.co.uk/files/PHPEncryption.zip
and the PHP uses some out of date (to me) encryption functions, it use 2 different "Modes" for the rijndael 128 encryption, ecb and cbc. Using a different mode will change the output encryption, and if I understand the setup of these, you MUST use the same mode for decryption. I looked at the Delphi code in uMain.pas from the zip file, and it uses the Cipher.EncryptCBC( ) function from the TDCP_rijndael. So I would guess you must use the CBC mode for the for the PHP to have reversible encryptions. I saw marqusG comment and it seemed like something must have changed in a version upgrade (version of "Delphi Cryptography Package", or Delphi version, or PHP version) so I looked at the code in the "Delphi Cryptography Package" for the rijndael 128 in the DCPrijndael.pas cipher definitions. And I could NOT find a EncryptCBC( ) function, it only has a EncryptECB( ) function in that class. I do not have time to figure this out (where the CBC mode function may be), so if I where fishing for a possible working solution, I would use the ECB mode in the delphi and php code, and I would use a KEY that is exactly the block size for the rijndael 128, that is 32 bytes. You might try and use some portion of Ray_Paseur's code in post ID:33436596, but on my servers the IVS is completely ignored in the ECB mode and this works for me -
$data = mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $this->key, $text, MCRYPT_MODE_ECB, '66');

From using some different encryption, I would guess that the way data array blocks are padded (with 0, with spaces, etc) may be why there are differences in Delphi and PHP (maybe marqusG comment is due to padding changes from one version to another?), so you might consider doing your own block size padding in both PHP and delphi for your pre-encrypted string to have exchangeable encryption.
0
 
LVL 33

Expert Comment

by:Slick812
Comment Utility
I'll add, , that the rijndael encryption is considered one of the more recent and more difficult, to hack out a run around. From your description, I would not think you need really good and high secure encryption. You might consider doing your own simple encryption in PHP and Delphi, with a few XOR, a few byte rotations and a couple bit shifts. It seems like you are less worried about a hacker "decrypting" your sends, but a hacker sending up a false ID.
0
 

Author Comment

by:JealousyPrince
Comment Utility
Slick812
" It seems like you are less worried about a hacker "decrypting" your sends, but a hacker sending up a false ID." >> Thats exactly the case but im not really good in encryption programming. Can you please give me an example of how i can encode a string in delphi and decode it using php?
0
 

Author Comment

by:JealousyPrince
Comment Utility
marqusG:
" it seems to find a solution to pass some variables from Delphi to PHP using POST method: this way you could avoid to encrypt them because data would not appear in the url" >> Thats true but any packet sniffer can still read the contents of the parameters.

Ray_Paseur:
I cant simplify it any further, the whole point is i want a delphi function to encrypt a string, and a php function to decrypt that string which was encrypted with delphi.
0
 
LVL 32

Expert Comment

by:DrDamnit
Comment Utility
JealousyPrince:

We need to understand what you're protecting yourself against before we can help you.

For transport security (guarding against man in the middle attacks, etc...) Ray is correct when he says HTTPS is sufficient. Your problem appears to not be a transport encryption issue, but rather a spoof attack issue.

Correct me if I am wrong, but it appears you are trying to encrypt some strings (what it is doesn't really matter) so that people cannot sniff your traffic, see that you're putting the computer name and version in the sends, and then spoof that from other machines to either 1) circumvent copy protection or 2) destroy your database.

if that is the case, I strongly suggest that you use public and private key encryption. Research GnuPG. You'll need to generate a public key that can be distributed with your application and a private key that is held on the server. Thus, you don't have to reinvent the wheel with encryption, and can use something that is strong enough that no one in their right mind will try to decipher it.

Here are the GnuPG components for Delphi:
http://sourceforge.net/projects/gpgcomp/

Here is how to do it on the php side (you must have gpg installed on the server):
http://devzone.zend.com/article/1265

Now a further word on best practices: if you are worried about information being accidentally inserted into your database, you need to seriously consider creating sanitation routines that gaurd against SQL injections among other mal-formed data.

I can't help you with the delphi side of this, but the encryption side I know inside and out, and between Ray and I and the others, I am sure we can help you get this working.
0
 
LVL 108

Expert Comment

by:Ray Paseur
Comment Utility
"I cant simplify it any further"

Sure you can!  Imagine that you do not have Delphi or PHP or anything else.  Give it to us like this, "I need a way to be sure that bogus data does not pollute my data base." Or maybe, "How do I authenticate the client, to be sure only trusted individuals are sending me data?"
0
 
LVL 45

Expert Comment

by:aikimark
Comment Utility
0
 
LVL 33

Expert Comment

by:Slick812
Comment Utility
For my security concerns I always try to figure what a hacker would get as a reward for bypassing my encryption, if it is a password to a million dollar account I would try and use the better security (actually, I would not even try to code for that level, since real security hackers are much better than me at this sort of thing, , I would let someone else handle it), but if it is something to discourage user pranks - frustrations, and there's no money reward for bypassing, I will use some of my own code, although there are very many encryption methods for every platform, crossing platforms may have problems with the default settings in the coding.

I will offer the tested code below as a demo of what you can do, this is all PHP, but I believe if you have an fair understanding of PHP, you can translate this to pascal Delphi. Now I do not have time to even try to do a pascal version.
If you have trouble understanding the encryption functions, then this may not be a way for you, ask questions if I am unclear somewhere
<html><head><title>PHP Simple Crypt</title><style type="text/css">.rd{color:#b00;}</style></head><body BGCOLOR="#E3F7FF"><h2>Test for PHP Simple Crypt</h2>
<p>
<?php
define("VALIDBB", chr(2).chr(247).chr(15).chr(128).chr(255).chr(3));
// no ascii charaters helps for unique

//define("VALIDBB", '*k0~M-');// if you would rather use ascii text


//  NONE of the encryption methods here are up to any decent level of modern encryption
//  but can offer a mild preventive for hiding data

function aryXOR($In,$ary){$len = strlen($In);
// this uses an array of arrays with TWO values to XOR all of the text
for($a = 0; $a < count($ary); ++$a){for($i = 0; $i < $len; ++$i){
	$xor = ord($In{$i}) ^ $ary[$a][$i & 1];
	$In[$i] = chr($xor);}
	}
return $In;}

function byteRotate($In,$aryIn,$en=true){$len = strlen($In);
// this rotates the text values an the mods 256 out the result
$aryKey=array(227,79,13,162,244,31,126,65,62,250,21,3,99,211,104,111,145,222,44,81,99,203,50,100,200);// 25 count
$aryKey = array_merge($aryIn, $aryKey);
$kLen = count($aryKey);
if ($len > $kLen) for($i = $kLen; $i < $len; ++$i) $aryKey[] = $i % 256;
for($i = 0; $i < $len; ++$i){
	$xor = ord($In{$i});
	if ($en) $In[$i] = chr(($xor + $aryKey[$i]) % 256); else
	$In[$i] = chr((($xor + 256) - $aryKey[$i]) % 256);
	}
return $In;}

function shift3($In,$en=true){$len = strlen($In);
// this right shifts all text valus 3 bit position, and left shift for decrypt
$On = array();
for($i = 0; $i < $len; ++$i) $On[] = ord($In{$i});
if ($en) {$In[0] = chr((($On[0] & 31) << 3) | (($On[$len-1] & 224) >> 5));
	  for($i = 1; $i < $len; ++$i) {$In[$i] = chr((($On[$i-1] & 224) >> 5) | (($On[$i] & 31) << 3));}} else
    {$hd = ($On[1] & 7)<<5; for ($i = 1; $i < $len-1; ++$i) {$In[$i] = chr((($On[$i] & 248) >> 3) | (($On[$i+1] & 7) << 5));}
	$In[$len-1] = chr((($On[0] & 7) << 5) | (($On[$len-1] & 248) >> 3)); $In[0] = chr($hd + (($On[0] & 248)>>3));}
return $In;}

function hex2text($In){$Out='';
//$In=str_replace(' ', '', $In);
for($i=0; $i<strlen($In); $i+=2) $Out.=chr(hexdec(substr($In, $i, 2)));
return($Out);}

// // // // // // // end of functions, beginning of encrypt

$First1 = 'User Name-Version';// This is the string to be encrypted
	echo 'This is the Input, Before encryption- <b>'.$First1.'</b><br /><br />';
	/*
IMPORTANT - in my view -
	To ensure that any old falsely encrypted data will NOT be used
	I will make the first 6 bytes (characters) a special "unique" byte
	block that will identify all entry's as being valid or not.
	I use the VALIDBB defined above.
	Remember any byte block that is put in will be decrypted,
	no matter if it is valid or NOT
*/
$Test1 = VALIDBB.$First1;// add validation to beginning of Input
$ary1 = array(array(35,121),array(114,123),array(74,129),array(94,240),array(221,7));// ALL numbers are between 1 and 255
$Test1 = aryXOR($Test1,$ary1);
$ary1 = array(7,222,147,200,123,4);// ALL numbers are between 1 and 255
$Test1 = byteRotate($Test1,$ary1);
$Test1 = shift3($Test1);
$ary1 = array(array(145,36),array(14,227),array(114,239),array(184,30),array(116,231),array(99,177));
$Test1 = aryXOR($Test1,$ary1);
$ary1 = array(111,17,88);// ALL numbers are between 1 and 255
$Test1 = byteRotate($Test1,$ary1);
$ary1 = strlen($Test1);
$Test1 = substr($Test1.$Test1[0],1,$ary1);
$Test1 = shift3($Test1);

// End of Encryption

$order = array('<', '>');
$replace = array('&lt;', '&gt;');
$ary1 = str_replace($order, $replace, $Test1);
echo 'Encrypted string = '.$ary1.'<br />';

//I like to use the the HEX for web data because I can scramble the hex
$Test1 = bin2hex($Test1);
$ary1 = strlen($Test1);
$Test1 = substr($Test1.$Test1[0],1,$ary1);
// by changing One character a hex read will use the wrong pairing of hex
echo 'Encrypted HEX string used for web = '.$Test1.'<br /><br />';

// Begin Decrypt
// for WEB you should do a regex to ensure all characters are HEX
$ary1 = strlen($Test1);
$Test1 = substr($Test1[$ary1-1].$Test1,0,$ary1);
$Test1 = hex2text($Test1);
$Test1 = shift3($Test1,false);
$ary1 = strlen($Test1);
$Test1 = substr($Test1[$ary1-1].$Test1,0,$ary1);
$ary1 = array(111,17,88);
$Test1 = byteRotate($Test1,$ary1,false);

// IMPORTANT you must reverse the array order for the aryXOR function decrypt
$ary1 = array(array(99,177),array(116,231),array(184,30),array(114,239),array(14,227),array(145,36));
$Test1 = aryXOR($Test1,$ary1);
$Test1 = shift3($Test1,false);
$ary1 = array(7,222,147,200,123,4);
$Test1 = byteRotate($Test1,$ary1,false);
$ary1 = array(array(221,7),array(94,240),array(74,129),array(114,123),array(35,121));// ALL numbers are between 1 and 255
$Test1 = aryXOR($Test1,$ary1);

	//GET THE VALIDATION BLOCK and test it
$ary1 =  substr($Test1,0,6);
if ($ary1 == VALIDBB) echo 'VALIDBB is VALID '; else echo 'error VALIDBB is NOT VALID ';
$ary1 = strlen($Test1);
$Test1 =  substr($Test1,6,$ary1);
echo '+ Decrypted string = <b>'.$Test1.'</b><br />';
?>
<h3>End of Test for PHP Simple Crypt</h3>
</body></html>

Open in new window

0
 

Author Comment

by:JealousyPrince
Comment Utility
If i knew how to translate ur php encryption code to delphi i wouldnt have posted here :)

TPLockBox works great, but still, the result differs than the encrypted string in php..

I'll try DrDamnit's solution tonight :)
0
 

Author Comment

by:JealousyPrince
Comment Utility
DrDamnit ur soluiton didnt work. i think my host doesnt support pgp..

Can't someone just create a function to encrypt a string with delphi, and a php function to decrypt it :(
0
 
LVL 32

Expert Comment

by:DrDamnit
Comment Utility
>>Can't someone just create a function to encrypt a string with delphi, and a php function to decrypt it :(

We can help you find a solution, but we are not here to code functions for you. That's what hiring a professional programmer is for.

Ask your host to install gpg. See if they'll do it.
0
 
LVL 45

Expert Comment

by:aikimark
Comment Utility
Is there a salt involved?  Perhaps PHP is using a salt and Delphi is not (or vice versa)
0
 
LVL 32

Expert Comment

by:DrDamnit
Comment Utility
aikimark:

To which solution are you referring?
0
 
LVL 45

Expert Comment

by:aikimark
Comment Utility
@DrD

I'm catching up to this conversation.  I was responding to the comment that TPLockbox doesn't generate the same value as PHP.
0
 
LVL 32

Expert Comment

by:DrDamnit
Comment Utility
@aikimark:

I have had that problem before. It most likely is a result of the salt being generated differently in Delphi versus PHP. I once wrote a key generater for some software that I wrote in VB6. I remember that I had a problem with the keys being generated inconsistently when I was referencing DLLs in Windows versus trying to accomplish the same thing with PHP on the linux side. (for when customers wanted to register on the website... I had to give them a key to activate my software).

For instance, generating an MD5 hash in Windows may or may not generate the same hash in Linux. It depends on what you're using as the source generator. This is one of the reasons I always use gnu core utils for windows rather than just some random hash generator. You can download md5sum.exe from the internet to your heart's content, but unless it is the GNU version, it won't generate the same hashes as the standard md5sum binary on a Linux box.
JealousyPrince
The asker is having the same problem.

The solution is that he has to translate his code into PHP, and the encryption has to be done from scratch. He can't use a DLL on the Windows box unless it produces the EXACT SAME outputs as the Linux version. that's hard to do unless you use a GNU dll / binary or something that has been standardized.

God forbid he's using Borland. They do everything their own way and are just flat obstinate.

Of course, if he IS using Borland... he should be able to compile his encryption code on Linux, then he can use shell_execute from PHP to generate it.... .that's a thought.

What say you, JealousyPrince? Can you compile a quick binary on Linux so we can use shell_execute from PHP?
0
 
LVL 45

Expert Comment

by:aikimark
Comment Utility
If the two operating systems are little-endian and big-endian, the algorithms need to accommodate that difference.

In this case, TPLockbox is not (legacy) Borland code.  It comes from the former TurboPower.
0
 
LVL 32

Expert Comment

by:DrDamnit
Comment Utility
Yeah. What you said. :-)
0
 

Author Comment

by:JealousyPrince
Comment Utility
I'm using delphi on windows, and my web server and php are running on linux. I can't compile any binary on linux because im not using it. My webserver is hosted on bluehost.com.
0
 
LVL 32

Expert Comment

by:DrDamnit
Comment Utility
I use bluehost too. They're pretty good.

Are you on a dedicated server or a shared one?

Unless you're on a dedicated box, we are down to translating your code to PHP.
0
 

Author Comment

by:JealousyPrince
Comment Utility
I'm on a shared one :)
0
 
LVL 32

Expert Comment

by:DrDamnit
Comment Utility
Translation it is. :-(
0
 
LVL 8

Expert Comment

by:GeneralTackett
Comment Utility
I can provide the delphi side encryption routines and they could also be as a soap service but the php side I dont have code for.  if interested let me know.
0
 
LVL 33

Expert Comment

by:Slick812
Comment Utility
JealousyPrince, I have little time now to do any code work, I copy and pasted the PHP code I posted from earlier work of mine, however when I tried to figure a Delphi translation, it will take some time because I have not done any crypt in delphi before. But any crypt code is not an easy, short time endeavor. If you do not find a solution before, , maybe this weekend I can see if I can find time to try a delphi encrypt function. But I have many work and personal commitments, and EE will have to wait.
0
Free Trending Threat Insights Every Day

Enhance your security with threat intelligence from the web. Get trending threat insights on hackers, exploits, and suspicious IP addresses delivered to your inbox with our free Cyber Daily.

 

Author Comment

by:JealousyPrince
Comment Utility
So far no complete solution :(
0
 

Author Comment

by:JealousyPrince
Comment Utility
Some info that might be useful... Even the basic base 64 encode function in php does not generate the same value generated by any base 64 encode function in delphi..

So its not about any Salt involved or about the complexity of encryptions, its even in the basics.. This is really starting to puzzle me...
0
 
LVL 32

Expert Comment

by:DrDamnit
Comment Utility
As aikimark pointed out in a previous post:

"If the two operating systems are little-endian and big-endian, the algorithms need to accommodate that difference."

Just using the basic functions is not going to produce the same output. It's like taking a spanish word and translating it in chinese. The thing is still the thing, but the word itself is VERY different.
0
 

Author Comment

by:JealousyPrince
Comment Utility
hmmmmm.. but I understand from this page http://en.wikipedia.org/wiki/Endianness that linux and windows are both running on little endian architecture
0
 
LVL 45

Expert Comment

by:aikimark
Comment Utility
If you read down further...

[quote]Big-endian operating systems:

AIX on POWER
AmigaOS on PowerPC and 680x0
HP-UX on Itanium and PA-RISC
Linux on MIPS, SPARC, PA-RISC, POWER, PowerPC, and 680x0
Mac OS on PowerPC and 680x0
Solaris on SPARC[/quote]

==============
The endian-ness of Linux depends on the hardware on which it runs.
0
 
LVL 33

Assisted Solution

by:Slick812
Slick812 earned 500 total points
Comment Utility
OK, what a growling Bear this was to code, and I've got the claw marks to prove it, I completely take back what I said - "you can translate this to pascal Delphi" with no trouble, LOL. ? ? I had more trouble in cross process trouble shouting, And then rewriting code and forgetting the different platform syntax and putting . for + in strings, ,  and { for begin , , Ha Ha. . BUT, I got something that works for me on my systems. I was hoping to have both an Encryption and Decryption function in both platforms, but I just got tired and did only what was required.

Since there is some talk about platform differences and corresponding "same" coding producing different results. I have done work in several platforms and I believe that the main differences have nothing to do with the endian order of byte placement, since Intel and AMD produce almost all of the processors. The Free code (open source) translated to Pascal and PHP was originally in some form of C code, and trying to hammer and beat C++ code into other platforms (or even in a C code platform) requires adjustments for the platform syntax, you can get it to function in your platform and think you got Identical performance, but as I have been frustrated with here, to whip it to Identical results in a second platform, takes additional effort for some small stuff I would have never considered.

I looked at the Pascal code for - "Delphi Cryptography Package" and the pascal code for "LockBox", I believe these both to be from the same open source repositories, But they used different ways to implement the same source. The lockBox stuff looks more creative and recent. I'm not sure that these would give identical results even on the same platform.

OK I have two code mixes, the first is the  Cryptoe.pas  unit for Delphi, It has only One function -
function InCrypt(Plain: String): TReCrypt;
You have a single in put as plain text and it will return a TReCrypt with the Good as true for success and false for failure. The Out1 will have Encrypted Hex Text on success and Error message on failure. I have limited the Input Plain string to 120 characters, it will fail for longer strings, and fail for no character in Plain. a button click I used for testion

procedure TForm1.Button5Click(Sender: TObject);
var
aStr: String;
CryptRe: TReCrypt;
begin
aStr := 'Good 4 Nothin';
Label1.Caption := aStr;
CryptRe := InCrypt(aStr);
if CryptRe.Good then
    begin
    Edit1.Text := CryptRe.Out1;// copy and paste Edit text to PHP test page
    Label2.Caption := 'The InCrypt was a Success';
    end else
    begin
    Label3.Caption := CryptRe.Out1;
    Label2.Caption := 'FAILURE InCrypt Did NOT Work';
    end;
end;
unit Cryptoe;

interface

type
  PReCrypt = ^TReCrypt;
  TReCrypt = record
    Good: Boolean;
    Out1: String;
    end;

function InCrypt(Plain: String): TReCrypt;
//function UnCrypt(HexIn: String): TReCrypt;

implementation

uses Windows, SysUtils;

const
Verfy: array[0..3] of Byte = (2,15,255,3);

function hexRota(InStr:String;en:Boolean=true):String;
var
i, len, len2: LongInt;
Chr1: Char;
Coy: String;
begin
len := Length(InStr);
len2 := len div 2;
if not en then
    begin
    Coy:= InStr;
    Chr1 := InStr[1];
    for i := 1 to Pred(len) do InStr[i] := Coy[i+1];
    InStr[len] := Chr1;
    end;
for i := 1 to len2 do
    begin
    if i and 1 = 0 then continue;
    Chr1 := InStr[i];
    InStr[i] := InStr[len - (i-1)];
    InStr[len - (i-1)] := Chr1;
    end;
if en then
    begin
    Coy:= InStr;
    InStr[1] := Coy[len];
    for i := 2 to len do InStr[i] := Coy[i-1];
    end;
Result := UpperCase(InStr);
end;


procedure cRoto(pIn:PByte; len: LongInt; en:Boolean=true; odd:Boolean=false);
var
pRef, pPos: PByte;
i, skip, len2: LongInt;
hd, bit1, tib1, bit2, tib2: Byte;
begin
if len < 4 then Exit;
pRef := pIn;
len2 := (len-(len and 1)) div 2;

if len and 1 = 1 then
    begin
    pPos := PByte(LongInt(pRef)+len2);
    bit1 := (pPos^ and 3) shl 2;
    tib1 := (pPos^ and 12) shr 2;
    pPos^ := (pPos^ and 240)+tib1+bit1;
    end;

if not odd then Inc(pIn);
for i := 0 to Pred(len2) do
    begin
    if odd then skip := i and 1 else skip := 1-(i and 1);
    if skip = 1 then continue; 
    pPos := PByte(LongInt(pRef)+(len-(i+1)));

    bit1 := (pPos^ and 12) shr 2;
    tib1 := (pIn^ and 12) shr 2;
    bit2 := (pPos^ and 3) shl 2;
    tib2 := (pIn^ and 3) shl 2;
    if en then
        begin
        pPos^ := (pPos^ and 240)+tib1+bit2;
        pIn^ := (pIn^ and 240)+bit1+tib2;
        end else
        begin
        pPos^ := (pPos^ and 240)+tib2+bit1;
        pIn^ := (pIn^ and 240)+bit2+tib1;
        end;
    hd := pIn^;
    pIn^ := pPos^;
    pPos^ := hd;
    Inc(pIn,2);
    end;
end;


procedure transBit(pIn:PByte; len: LongInt; en:Boolean=true);
var
pMem, pRef, pDup, pDup2, pDup3: PByte;
i: LongInt;
begin
pRef := pIn;
GetMem(pMem, len+8);
CopyMemory(pMem, pIn, len);
pDup := pMem;
pDup2 := pDup;
Inc(pDup2);
pDup3 := pDup2;
Inc(pDup3);
PByte(LongInt(pMem)+len)^ := pDup^;
Inc(pDup);
PByte(LongInt(pMem)+len+1)^ := pDup^;
Dec(pDup);
if en then
    begin
    for i := 0 to Pred(len) do
        begin
        pIn^ := (pDup^ and 64) or (pDup2^ and 137) or (pDup3^ and 54);
        Inc(pIn);
        Inc(pDup);
        Inc(pDup2);
        Inc(pDup3);
        end;
    end else
    begin
    for i := 0 to Pred(len) do
        begin
        pIn^ := (pDup3^ and 64) or (pDup2^ and 137) or (pDup^ and 54);
        Inc(pIn);
        Inc(pDup);
        Inc(pDup2);
        Inc(pDup3);
        end;
    CopyMemory(pMem, pRef, len);
    CopyMemory(pRef, PByte(LongInt(pMem)+(len-2)), 2);
    CopyMemory(PByte(LongInt(pRef)+2), pMem, len-2);
    end;
FreeMem(pMem);
end;


procedure shift3(pIn:PByte; len: LongInt; en:Boolean=true);
var
pMem, pDup, pRef: PByte;
i: LongInt;
hd: Byte;
begin
GetMem(pMem, len+4);
CopyMemory(pMem, pIn, len);
pDup := pMem;
pRef := pIn;
hd := PByte(LongInt(pMem)+(len-1))^;
if en then
    begin
    pIn^ := ((pDup^ and 31) shl 3) or ((hd and 224) shr 5);
    Inc(pIn);
    for i := 1 to Pred(len) do // len-1
        begin
        pIn^ := ((pDup^ and 224) shr 5);
        Inc(pDup);
        pIn^ := pIn^ or ((pDup^ and 31) shl 3);
        Inc(pIn);
        end;
    end else
    begin
    for i := 2 to len do
        begin
        pIn^ := ((pDup^ and 248) shr 3);
        Inc(pDup);
        pIn^ := pIn^ or ((pDup^ and 7) shl 5);
        Inc(pIn);
        end;
    PByte(LongInt(pRef)+(len-1))^ := ((pMem^ and 7) shl 5) or ((hd and 248) shr 3);
    hd := (pDup^ and 7) shl 5;
    pMem^ := hd + ((pMem^ and 248) shr 3);
        end;
FreeMem(pMem);
end;

procedure byteRotate(pIn:PByte; pAry: PByte; len: LongInt; count: LongInt; en:Boolean=true);
const
aryK: array[0..25] of Byte =(227,79,13,162,244,31,126,65,62,250,21,3,99,211,104,111,145,222,44,81,99,203,50,100,200,5);
var
pMem, pKey: PByte; //, pRef
i: LongInt;
hd, a: Byte;
begin
//pRef := pIn;
GetMem(pMem, len+count+28);
pKey := pMem;
CopyMemory(pMem, pAry, count);
Inc(pKey,count);
//a := 0;
//for i := count to len-1 do begin pKey^ := aryK[a]; Inc(a); Inc(pKey); end;
CopyMemory(pKey, @aryK, 26);
Inc(pKey,26);
if len > count+26 then for i := count+26 to len-1 do begin pKey^ := i; Inc(pKey); end;
pKey := pMem;
Dec(pKey);
Inc(pIn);
hd := pIn^;
if en then pIn^ := (hd+33) mod 256 else begin hd := ((hd+256)-33) mod 256; pIn^ := hd; end;
if hd = 0 then hd := 31;
Dec(pIn,2);
for i := 0 to len-1 do
    begin
    Inc(pIn);
    Inc(pKey);
    if i<>1 then begin
        a := pIn^;
        if en then pIn^ := (a + pKey^ +hd) mod 256 else //
        pIn^ := ((a + 256) - (pKey^ +hd)) mod 256; //+hd aryKey[i]
        end;
    end;
FreeMem(pMem);
end;

Procedure aryXOR(pIn:PByte; pAry: PByte; len: LongInt; count: LongInt);
var
i,a,nu: LongInt;
pOn: PByte;
sBy: Byte;
begin
Dec(len);
Dec(count);
pOn := pIn;
for i := 0 to count do
    begin
    nu := 0;
    for a := 0 to len do
        begin
        sBy := pOn^;
        pOn^ := sBy xor pAry^;
        Inc(pOn);
        if (a and 1) = 1 then Dec(pAry) else Inc(pAry);
        nu := a;
        end;
    pOn := pIn;
    if nu and 1 = 1 then Inc(pAry,2) else Inc(pAry);
    end;
end;

function InCrypt(Plain: String): TReCrypt;
const
Verfy: array[0..3] of Byte = (2,15,255,3);
var
len, i: LongInt;
pMem,pBary: PByte;
hx: String;
Rary: array[0..8] of Byte;
xAry: array[0..6] of Word;
aryRan: array[0..3] of Byte;
do1:Boolean;
RanW: Word;
begin
Result.Good := false;
Result.Out1 := 'ERROR - String Length is less than one';
len := Length(Plain);
if len < 1 then exit;
if len > 120 then begin Result.Out1 := 'ERROR - String Length is More than 120'; exit; end;
GetMem(pMem, len+16);
Randomize;
aryRan[0] := 1+Random(254);
aryRan[1] := 1+Random(254);
aryRan[2] := 255-aryRan[0];
aryRan[3] := 255-aryRan[1];
CopyMemory(pMem, @Verfy[0], 4);
pBary := pMem;
for i := 0 to 3 do
    begin
    pBary^ := (pBary^ +aryRan[i]) mod 256;//Ran1
    Inc(pBary);
    end;
CopyMemory(pBary, PChar(Plain), len);
Inc(len,4);
pBary := pMem;
RanW := (aryRan[0] shl 8) +aryRan[1];
xAry[0] := $FFFF;// 255,255  0000
xAry[1] := $AA55;// 85,170
xAry[2] := $0000F00F;// 15,440
xAry[3] := $0000C003; // 3,192
xAry[4] := RanW;
RanW := (aryRan[1] shl 8) +((aryRan[1]+aryRan[0]) mod 256);
xAry[5] := RanW;
aryXOR(pBary,PByte(@xAry[0]),len,6);
Rary[0] := (aryRan[0]-aryRan[1]) mod 256;
Rary[1] := 172;
Rary[2] := aryRan[1];
Rary[3] := aryRan[3];
Rary[4] := aryRan[2];
Rary[5] := aryRan[0];
Rary[6] := (aryRan[0]+aryRan[1]) mod 256;
byteRotate(pBary,PByte(@Rary),len,7,true);
Inc(pBary,len);
pBary^ := aryRan[0];
Inc(len);
pBary := pMem;
shift3(pBary, len);
transBit(pBary,len);
do1 := (len and 1) = 0;
cRoto(pBary, len,true,do1);
transBit(pBary,len);
shift3(pBary, len);
xAry[0] := $3021;//33,48
xAry[1] := $F00F;// 15,240
xAry[2] := $7CA3;//163,124
RanW := (aryRan[1] shl 8) +(aryRan[3]);
xAry[3] := RanW;
aryXOR(pBary,PByte(@xAry[0]),len,4);

Inc(pBary,len);
pBary^ := aryRan[1];
Inc(len);
pBary := pMem;

Rary[0] := 31;
Rary[1] := 195;
Rary[2] := 8;
Rary[3] := 14;
Rary[4] := 237;
Rary[5] := 209;
byteRotate(pBary,PByte(@Rary),len,6,true);
for i := 0 to len -1 do begin hx := hx+IntToHex(pBary^,2);Inc(pBary); end;
hx := hexRota(hx,true);

Result.Good := true;
Result.Out1 := hx;
end;

{function UnCrypt(HexIn: String): String;
var
len, i: LongInt;
pMem: PByte;
begin
len := Length(HexIn);
end;}

end.

Open in new window

0
 
LVL 33

Assisted Solution

by:Slick812
Slick812 earned 500 total points
Comment Utility
OK this second code mess is for the PHP I have it in cryptoe.php, The function you want to use is -
$array1 = function UnCrypt($HexIn);
this returns an array, the first array element [0] is true or false, true for success. . . The second is the DeCrypted Text if success, or error message on failure. This fails if the input string is less than 14 charaters, or if the input is NOT hex characters. Also, more important, If the Verification byte block does NOT match, it will fail.
I did not have time to do very many tests, but the ones I did worked for me.

Since no provisions were in the design specs, I have placed a Verification byte block, that will give the input as being the Real thing. Also for encryption improvement I have included two Random Bytes that are use in XOR and byte rotations, so the output can have at least 65,000 different outputs for the same input.

I used several ways to mitigate and mix the text for encryption. I personally feel that to transfer bits of one byte to another and then mix bytes and transfer different bits again several times, ,  so a byte has no original bits in it (along with XOR and rotations) is a good way to do it. So I have a couple of methods for bit transfer. Also, very few that use encryption for web transfer know diddly about encryption, and have it in encode64 or Hex text. I have scrambled the output Hex, many that might try to do statistical analysis to brech encryption, will not at first think that the hex is molested, and do time consuming analysis on the flapjack hex I produce before they realize they have to analyze the hex also.

JealousyPrince, I hope this works for you, I get some sleep tonight, zzzzzzzzzzzzzzzzzzzzzz

<?php

function letRev($In){
$len = strlen($In);
$len2 = ($len-($len & 1)) / 2;
for($i = 0; $i < $len2; $i+=2){$On = $In[$i]; $In[$i]=$In[$len-($i+1)]; $In[$len-($i+1)]=$On;}
return $In;}

function byteRotate($On,$aryIn,$en=true){$len = count($On);
$aryKey=array(227,79,13,162,244,31,126,65,62,250,21,3,99,211,104,111,145,222,44,81,99,203,50,100,200,5);// 26 count
$aryKey = array_merge($aryIn, $aryKey);
$kLen = count($aryKey);
if ($len > $kLen) for($i = $kLen; $i < $len; ++$i) $aryKey[] = $i % 256;
$hd = $On[1];
if ($en) $On[1] = ($hd+33)% 256; else {$hd = (($hd+256)-33)% 256; $On[1] = $hd;}
if($hd ==0)$hd = 31;
for($i = 0; $i < $len; ++$i){if($i==1)continue;$A = $On{$i};
	if ($en) $On[$i] = ($A + $aryKey[$i]+$hd) % 256; else
	$On[$i] = (($A + 256) - ($aryKey[$i]+$hd)) % 256;}
return $On;}

function aryXOR($On,$ary){$len = count($On);
// this uses an array of arrays with TWO values to XOR all of the text
for($a = 0; $a < count($ary); ++$a){for($i = 0; $i < $len; ++$i) $On[$i] = $On{$i} ^ $ary[$a][$i & 1];}
return $On;}

function shift3($In,$en=true){$len = count($In);
$On = array();
for($i = 0; $i < $len; ++$i) $On[] = $In[$i];
if ($en) {$In[0] = (($On[0] & 31) << 3) | (($On[$len-1] & 224) >> 5);
	for($i = 1; $i < $len; ++$i) {$In[$i] = (($On[$i-1] & 224) >> 5) | (($On[$i] & 31) << 3);}} else
    {$hd = ($On[1] & 7)<<5; for ($i = 1; $i < $len-1; ++$i) {$In[$i] = (($On[$i] & 248) >> 3) | (($On[$i+1] & 7) << 5);}
	$In[$len-1] = (($On[0] & 7) << 5) | (($On[$len-1] & 248) >> 3); $In[0] = $hd + (($On[0] & 248)>>3);}
return $In;}


function transBit($In,$en=true){$len = count($In);
$On = array();
for($i = 0; $i < $len; ++$i) $On[] = $In[$i];
$On[] = $In[0]; $On[] = $In[1];
//137- 1,128,8  54-32,16,4,2
if ($en) {for($i = 0; $i < $len; ++$i) {$In[$i] = ($On[$i] & 64) | ($On[$i+1] & 137) | ($On[$i+2] & 54);}} else
    {for ($i = 0; $i < $len; ++$i) {$In[$i] = ($On[$i+2] & 64) | ($On[$i+1] & 137) | ($On[$i] & 54);}
	$A = array_pop($In); $On = array_pop($In); $In= array_merge(array($On,$A), $In);}
return $In;}


function cRoto($In,$en=true,$odd=false){$len = count($In);//5
$len2 = ($len-($len & 1)) / 2;//2
if ($len > 3) {
//if (!$en) {if ($len & 1) {$On = $In[0]; $In[0] = $In[$len2]; $In[$len2] =$On;}
//	{$On = $In[2]; $In[2] = $In[1]; $In[1] = $On;}}
if ($len & 1) {$bit1 = ($In[$len2] & 3) << 2;
	$tib1 = ($In[$len2] & 12) >> 2;
	$In[$len2] = ($In[$len2] & 240)+$tib1+$bit1;
	//$On = $In[0]; $In[0] = $In[$len2]; $In[$len2] =$On;
	}
	
for($i = 0; $i < $len2; ++$i) {if ($odd) $pos=$i & 1;else $pos=!($i & 1);
if ($pos) continue; $pos=$len-($i+1); $On = $In[$pos]; $On2 = $In[$i];
$bit1 = ($On & 12)>>2;  $tib1 = ($On2 & 12)>>2;  $bit2 = ($On & 3)<<2; $tib2 = ($On2 & 3)<<2;
if ($en){$On = ($On & 240)+$tib1+$bit2; $On2 = ($On2 & 240)+$bit1+$tib2;}else{
$On = ($On & 240)+$tib2+$bit1; $On2 = ($On2 & 240)+$bit2+$tib1;}
$In[$pos] = $On2; $In[$i] = $On;}

//if ($en) {$On = $In[1]; $In[1] = $In[2]; $In[2] = $On;
//if ($len & 1) {$On = $In[0]; $In[0] = $In[$len2]; $In[$len2] =$On;}}
}
return $In;}

function hex2text($In){$Out='';
//$In=str_replace(' ', '', $In);
for($i=0; $i<strlen($In); $i+=2) $Out.=chr(hexdec(substr($In, $i, 2)));
return($Out);}

// / / / / / / / / / end of crypt functions


function UnCrypt($HexIn) {$outAry = array(false,'ERROR - String Length is less than 14');
$len = strlen($HexIn);
if ($len < 14) return $outAry;
if (preg_match('/[^a-fA-F0-9]/', $HexIn) < 1) {$HexIn = substr($HexIn.$HexIn[0],1,$len);
$HexIn = letRev($HexIn);
$HexIn = hex2text($HexIn);
$len = strlen($HexIn);
$Bary = array(); for($i = 0; $i < $len; ++$i) $Bary[] = ord($HexIn{$i});
echo 'len= '.$len.'<br />';
$ary2 = array(31,195,8,14,237,209);// ALL numbers are between 1 and 255
$Bary = byteRotate($Bary,$ary2,false);
$aryRan = array(); $aryRan[1] = $Bary[$len-1];
$aryRan[3] = 255-$aryRan[1];
unset($Bary[$len-1]);
$len = count($Bary);
echo $len.' Ran2 is '.$aryRan[1].'<br />';

$ary1 = array(array($aryRan[3],$aryRan[1]),array(163,124),array(15,240),array(33,48));
$Bary = aryXOR($Bary,$ary1);
$Bary = shift3($Bary,false);
$Bary = transBit($Bary,false);
$Bary = cRoto($Bary,false,!($len & 1));// 
$Bary = transBit($Bary,false);
$Bary = shift3($Bary,false);

$aryRan[0] = $Bary[$len-1];
unset($Bary[$len-1]);
$len = count($Bary);
$aryRan[2] = 255-$aryRan[0];
echo $len.' Ran1 is '.$aryRan[0].'<br />';
$ary2 = array(($aryRan[0]-$aryRan[1]) % 256,172,$aryRan[1],$aryRan[3],$aryRan[2],$aryRan[0],($aryRan[0]+$aryRan[1]) % 256);
$Bary = byteRotate($Bary,$ary2,false);
$ary1 = array(array(($aryRan[1]+$aryRan[0]) % 256,$aryRan[1]),array($aryRan[1],$aryRan[0]),array(3,192),array(15,240),array(85,170),array(255,255));
$Bary = aryXOR($Bary,$ary1);
$ary2 = array(2,15,255,3);
$ary1 = true;
for($i = 0; $i < 4; ++$i) {$Bary[$i] = (($Bary[$i]+256)- $aryRan[$i]) % 256; if ($ary2[$i] != $Bary[$i]) $ary1 = false;}
 //else { $HexIn = 
$HexIn = 'K';	
$len = count($Bary);
for($i = 4; $i < $len; ++$i) $HexIn[$i-4] = chr($Bary[$i]);
//echo $HexIn.'<br />';
if (!$ary1) $outAry[1] = 'ERROR - Verification is WRONG'; else {$outAry[0] =true; $outAry[1] =$HexIn;}
//}
} else $outAry[1] = 'ERROR - Invalid Hex Charaters in string';
return $outAry;}

?>

Open in new window

0
 

Author Comment

by:JealousyPrince
Comment Utility
Slick, I really appreciate your time and work..

I don't really want to tell u this, but still, the php code u wrote generated a different value than the delphi function u wrote lol.. By the way, on the delphi example, For the same string, whenever i click on the button, it generates a different encrypted value.. So a new encrypted value would be generated on every click :S
0
 
LVL 33

Expert Comment

by:Slick812
Comment Utility
OK, the encryption function uses RANDOM bytes to change the output every time, as I said, these different outputs ALL wuold give the correct decryption in the PHP function in my tests

sorry that all I can do to day, tomorrow is another head wack
0
 
LVL 33

Expert Comment

by:Slick812
Comment Utility
JealousyPrince, , I re-read your last post, and I am not able to understand when you said -
"the php code u wrote generated a different value than the delphi function u wrote"

So, I guess I'll ask these -

in my post ID:33506867 I gave delphi code for unit Cryptoe, I guess that this compiled and ran in your delphi version? Did you look at the output in a TLabel or TEdit to see the hex text generated from InCrypt() ? Did the TReCrypt returned have the "Good" as true?

in my post ID:33507002 I gave PHP code for the UnCrypt( ) function, I do not see that the php UnCrypt( ) and the delphi InCrypt( ) will ever have the same output ( generated a different value ).

Perhaps in my state, I did not explain well (my usual here at EE), The InCrypt() does the Encryption - and the UnCrypt( ) does the Decryption of hex only from the delphi InCrypt()

I did not give you an example of how to use the php UnCrypt($hex) function, so here some php I used to test this stuff -

<?php
require 'cryptoe.php';

$bo1 = (empty($_POST['bo1'])) ? '+' : $_POST['bo1'];

// get the UnCrypt input string however you like in php $_GET  $_POST or any other way,
// to get the hex string from the delphi  InCrypt()

if ($bo1 != '+'){
$deCr = UnCrypt($bo1);
if($deCr[0]) echo $deCr[1]; else echo 'Failure '.$deCr[1];
}
?>

so, in your testing of the UnCrypt($bo1);  is the $deCr[0] true, if true is the $deCr[1] the string you put into the delphi  InCrypt() ?
if $deCr[0] is false, what is the error message in $deCr[1]

sorry, I just noticed that I forgot to comment out a couple of debug echo statements in php UnCrypt( ).


0
 

Author Comment

by:JealousyPrince
Comment Utility
Ok Slick, Its 50% working :o

In delphi, it showed me that incrypt function "was a success"

In php, this was generated:
hhelen= 19
18 Ran2 is 97
17 Ran1 is 128
Good 4

So the word Nothin is missing, in delphi, Good 4 Nothin was encrypted while in php it was decrypted to Good 4 ... without Nothin..
0
 

Author Comment

by:JealousyPrince
Comment Utility
I encrypted "JealousyPrince" in delphi it was a success.
In php, again this showed:
hhelen= 20
19 Ran2 is 127
18 Ran1 is 148
Jealous


Some letters are missing...
0
 
LVL 45

Expert Comment

by:aikimark
Comment Utility
@JealousyPrince

I haven't posted in a while, but think it worth asking what version of Delphi are you using?
0
 

Author Comment

by:JealousyPrince
Comment Utility
I'm using delphi 2010
0
 
LVL 45

Expert Comment

by:aikimark
Comment Utility
let me ask the code-posting experts if the default string type (unicode) in D2010 might be cause of the difference in the results.
0
 
LVL 33

Expert Comment

by:Slick812
Comment Utility
I too am not sure about the string length, But It is encoding and decoding correctly the words you can see. I do not send any data length info embedded in the encrypted hex. . . The PHP just translates the hex to byte blocks (characters) and takes the length from that (always half of the hex length). .  I do add Six bytes  (characters)  to all string Input, 4 Verification and two random keys
the  debug echo of
len= 20
says that the input string is the correct length for "JealousyPrince"

if you feel like it, at the very end of the code for the PHP function UnCrypt($HexIn), please add this ONE echo line -

$HexIn = 'K';      
$len = count($Bary);
echo 'len= '.$len.'<br />';
0
 
LVL 33

Expert Comment

by:Slick812
Comment Utility
you might also Un comment the line
//echo $HexIn.'<br />';
to see the full decrypted string (also near the end of the function code.
0
 

Author Comment

by:JealousyPrince
Comment Utility
Okay i did what you told me..Here's the output:
hhelen= 20
19 Ran2 is 127
18 Ran1 is 148
len= 18
Jealous
Jealous
0
 
LVL 33

Expert Comment

by:Slick812
Comment Utility
The "len= 18" length is correct at 2 less than the first len of 20, if you take 4 off for the Verification length then the output string length should have 14 characters. But the output has half of that, as if the length limit in the for loop to convert the array of numbers to characters in a string has been changed - -
for($i = 4; $i < $len; ++$i) $HexIn[$i-4] = chr($Bary[$i]);

this looks like a straight forward (simple) "for loop" to me, although there is a [$i-4] this should not effect the ($i < $len;) for the loop limiter which seem to be opting out at 10 instead of 17, , I do not have this problem on my server for some reason?

let me do another "for loop method" for byte to character conversion and see if I can figure a way out of this.
will post again in an hour or less.
0
 
LVL 33

Accepted Solution

by:
Slick812 earned 500 total points
Comment Utility
this works for me, , , if you want to, you can comment OUT the for loop and put in these code changes at the end of cryptoe- -


$HexIn = 'OK';// change this line      
$len = count($Bary);
//for($i = 4; $i < $len; ++$i) $HexIn[$i-4] = chr($Bary[$i]); // Comment Out old for loop
for($i = 0; $i < $len; ++$i) $HexIn[$i] = chr($Bary[$i]); // new for loop
$HexIn = substr($HexIn, 4, $len); // chop off begining
echo strlen($HexIn).' '.$HexIn.'<br />'; // change echo debug, old line was echo $HexIn.'<br />';
0
 
LVL 33

Expert Comment

by:Slick812
Comment Utility
I want to thank those for the links to the delphi encryption pages at -
http://www.cityinthesky.co.uk/cryptography.html

http://sourceforge.net/projects/tplockbox/

I had a chance to go through alot of the code that they use for encryption in different algorithms and open source like Blowfish, the Lockbox guys even had some of their own algorithms. I was able to see what is meant By the "Modes" that can be added to stuff like Rijndael 128 etc. It appears all the modes do is encrypt the key so the used key characters are more diverse in there number values. The newer algorithms were to complex for me to understand their methods, but the Cryptography - City in the Sky code had some older ones like Tea and Prc. which I could translate. For this question I figured the Tea (Tiny encryption algorithm) was enough to do the job. The original code for tea (on Wikipedia) is in C code and used 32 bit blocks, I translated it to 8 bit and changed their "block" access methods, so it deals only with two bytes to use a cross byte reference to get a rotation value that is changed by 3 values in each rotation.
I do not use any Random values in these, and each function is self contained, as it does not need any other of my functions to do the job.

php code I used to test

$bo1 = (empty($_POST['hx1'])) ? '+' : $_POST['hx1'];

if ($bo1 != '+'){
$aryK = array(13,234,27,162,90,215,193,5);
$aryVr = array(139,21,222);

$ReAry = TeaDecrypt($bo1,$aryK,$aryVr);
if ($ReAry[0] == 0) echo 'Tea De- '.$ReAry[1].'<br />'; else
      echo 'Tea De-FAILED EC '.$ReAry[0].' '.$ReAry[1].'<br />';
// PHP Code for both the encryption and decryption functions
    // both functions return and array with an error code and output string
    // both functions need an Array with 8 bytes (1 to 255) for the KEY values $aryKey
    // both functions need an Array with 3 bytes for the Verify code to make sure it's real $VerAry


function TeaEncrypt($InStr, $aryKey, $VerAry){$len = strlen($InStr);
if ($len < 1) return array(101,'ERROR Input String is empty');
if ($len > 123) return array(102,'ERROR - the Input String has more than 123 characters');
$orx = ord($InStr[0]); $VerAry[1] = ($VerAry[1]+$orx) %256;
$VerAry[0] = $VerAry[0]^$orx;//
$len2 = chr($VerAry[0]).$InStr[0].chr($VerAry[1]);
if ($len > 1) {$orx = ord($InStr[1]); $VerAry[2] = ($VerAry[2]+$orx) %256;//$VerAry[2] ^= $orx; 
$len2 .= $InStr[1].chr($VerAry[2]);} else $len2 .= chr($VerAry[2] ^(255-$orx));
if ($len > 2) $InStr = $len2.substr($InStr,2,$len); else $InStr = $len2;
$len +=3;
if ($len & 1) {$x = ord($InStr[$len-1]);
	$x = (($x ^ $aryKey[1])+ $orx)%256;
	$x = (($x ^ $aryKey[5])+ $aryKey[2]) %256;
	$x = $x ^ $aryKey[$orx & 7];
	$InStr[$len-1] = chr($x);}
for ($i = 0; $i < $len-($len & 1); $i+=2){$x = ord($InStr[$i]);
	$y = ord($InStr[$i+1]);
	$sum = 0;
	for ($g = 0; $g < 8; ++$g){
	if ($g & 1) {$gs = 1 << $g;
			$bx = $x & $gs;
			$by = $y & $gs;
			$x = ($x & (255 - $gs))+$by;
			$y = ($y & (255 - $gs))+$bx;
			} else{$bx = $x & 7;
			$y = $y ^ $aryKey[$bx];
			$bx = $y & 7;
			$x = $x ^ $aryKey[$bx];}
		$sum+=7;
		$orx = ($y & 7) ^ ($sum & 7);
		$x=($x+($aryKey[$g] ^ $y) + ($sum ^ ($y >> ($sum & 3)))+$aryKey[$orx])%256;
		$sum+=7;
		$orx = ($x&7) ^ ($sum & 7);
		$y=($y+($aryKey[7-$g] ^$x) + ($sum ^ ($x >> ($sum & 3)))+$aryKey[$orx])%256;	
		}
	$InStr[$i] = chr($x);
	$InStr[$i+1] = chr($y);
	}
$InStr = bin2hex($InStr);
$len *= 2;
--$len;
$sum = $InStr[$len];
$InStr = $sum.substr($InStr, 0, $len);
return array(0,$InStr);}



function TeaDecrypt($HexStr, $aryKey, $VerAry){$len = strlen($HexStr);
if ($len < 8) return array(101,'ERROR - the Input Hex String is less than 8 charaters');
if ($len & 1) return array(102,'ERROR - the Input Hex String has an Odd number of charaters');
if (preg_match('/[^a-fA-F0-9]/', $HexStr) > 0) return array(103,'ERROR - the Input Hex String has Non-Hex charaters');
$sum = $HexStr[0];
$HexStr = substr($HexStr, 1, $len).$sum;
$sum = '';
for($i=0; $i<$len; $i+=2) {$sum.=chr(hexdec(substr($HexStr, $i, 2)));}
$HexStr=$sum;
$len = strlen($HexStr);
for ($i = 0; $i < $len-($len & 1); $i+=2){$x = ord($HexStr[$i]);
	$y = ord($HexStr[$i+1]);
	$sum = 112;
	for ($g = 7; $g > -1; --$g){$orx = ($x&7) ^ ($sum & 7);
		$y=(($y+256)-((($aryKey[7-$g] ^ $x) +($sum ^ ($x >> ($sum & 3)))+$aryKey[$orx])%256))%256;
		$sum-=7;
		$orx = ($y & 7) ^ ($sum & 7);
		$x=(($x+256)-((($aryKey[$g] ^ $y) +($sum ^ ($y >> ($sum & 3)))+$aryKey[$orx])%256))%256;
		$sum-=7;
		if ($g & 1) {$gs = 1 << $g;
			$bx = $x & $gs;
			$by = $y & $gs;
			$x = ($x & (255 - $gs))+$by;
			$y = ($y & (255 - $gs))+$bx;
			} else{$bx = $y & 7;
			$x = $x ^ $aryKey[$bx];
			$bx = $x & 7;
			$y = $y ^ $aryKey[$bx];}
		}
	$HexStr[$i] = chr($x);
	$HexStr[$i+1] = chr($y);
	}
$gs = 0;
$sum = '';
$sum .= $HexStr[1];
$x = ord($HexStr[1]);
$y = ord($HexStr[0]) ^ $x;
if ($VerAry[0] != $y) $gs = 1;
$y = ord($HexStr[2]);
$y = (($y +256) -$x)%256;
if ($VerAry[1] != $y) $gs = 1;
if ($len > 4) {$sum .= $HexStr[3];
	$x = ord($HexStr[3]);
	if ($len & 1) {$y = ord($HexStr[$len-1]);
		$y = $y ^ $aryKey[$x & 7];
		$y = ((($y + 256)- $aryKey[2])%256) ^ $aryKey[5];
		$y = ((($y + 256)- $x)%256) ^ $aryKey[1];
		$HexStr[$len-1] = chr($y);}
	$y = ord($HexStr[4]);
	$y = (($y +256) -$x)%256;
	if ($VerAry[2] != $y) $gs = 1;
	} else{$y = ord($HexStr[3]); $y =  $y ^ (255-$x); if ($VerAry[2] != $y) $gs = 1;}
if ($len > 5) $sum .= substr($HexStr,5,$len);
if ($gs == 1) {return array(202,'ERROR Verify numbers did not match');} else
	return array(0,$sum);}

Open in new window

0
 
LVL 33

Expert Comment

by:Slick812
Comment Utility
The delphi code is also 2 functions, also self contained and works with the PHP functions above
these also return a record with output info in them, and require the Input arrays for KEY values and Verify values
maybe this will work?

test code for delphi


procedure TForm1.SpeedButton2Click(Sender: TObject);
var
str1:String;
VAry: TAryVerify;
aryKey: TAryKey;
Return1: TTeaRe;

begin
VAry[0] := 139;
VAry[1] := 21;
VAry[2] := 222;

aryKey[0] := 13;
aryKey[1] := 234;
aryKey[2] := 27;
aryKey[3] := 162;
aryKey[4] := 90;
aryKey[5] := 215;
aryKey[6] := 193;
aryKey[7] := 5;

str1 := 'A Test';
Label1.Caption := str1;
Return1 := TeaEncrypt(str1, aryKey, VAry);
Label5.Caption := Return1.Out1;
if Return1.Error = 0 then Edit1.Text := Return1.out1 else
    Label5.Caption := 'Error Code = '+IntToStr(Return1.Error)+': '+Return1.out1;

Return1 := TeaDecrypt(Return1.Out1, aryKey, VAry);
if Return1.Error = 0 then Label2.Caption := Return1.out1 else
    Label2.Caption := 'Error Code = '+IntToStr(Return1.Error)+': '+Return1.out1;
end;
type
  TAryVerify = array[0..2] of Byte;
  TAryKey = array[0..7] of Byte;

  PTeaRe = ^TTeaRe;
  TTeaRe = record
    Error: LongInt;
    Out1: String;
    end;


function TeaEncrypt(InStr: String; aryKey: TAryKey; VerAry: TAryVerify): TTeaRe;
var
i,len,len2,g: LongInt;// ,ke
pIn,pMem,pTa: PByte;
x,y,sum,orx,gs,bx,by: Byte;

begin
Result.Error := 101;
Result.Out1 := 'ERROR - the Input String is Empty';
len := Length(InStr);
if len < 1 then Exit;
if len > 123 then
    begin
    Result.Error := 102;
    Result.Out1 := 'ERROR - the Input String has more than 123 characters';
    Exit;
    end;
GetMem(pMem, len+16);
pIn := pMem;
pTa := PByte(PChar(InStr));
orx := pTa^;
pIn^ := VerAry[0] xor orx;
Inc(pIn);
pIn^ := pTa^;
if len > 1 then
    begin
    Inc(pIn);
    pIn^ := VerAry[1]+ orx;
    Inc(pIn);
    Inc(pTa);
    orx := pTa^;
    pIn^ := pTa^;
    Inc(pIn);
    pIn^ := VerAry[2]+orx;
    end else
    begin
    Inc(pIn);
    pIn^ := VerAry[1]+ orx;
    Inc(pIn);
    pIn^ := VerAry[2] xor (255 - orx);
    end;
if len > 2 then
    begin
    Inc(pIn);
    Inc(pTa);
    CopyMemory(pIn, pTa, len-2);
    end;
Inc(len,3);
if Boolean(len and 1) then
    begin
    pIn := PByte(LongInt(pMem)+(len-1));
    pIn^ := (pIn^ xor aryKey[1])+ orx;
    pIn^ := (pIn^ xor aryKey[5])+ aryKey[2];
    pIn^ := pIn^ xor aryKey[orx and 7];
    Form1.Label4.Caption := IntToStr(orx);
    end;

pIn := pMem;
len2 := ((len-(len and 1)) div 2)-1;
for i := 0 to len2 do
    begin
    x := pIn^;
    Inc(pIn);
    y := pIn^;
    sum := 0;
    for g := 0 to 7 do
        begin
        if Boolean(g and 1) then
            begin
            gs := 1 shl g;
            bx := x and gs;
            by := y and gs;
            x := (x and (255 - gs))+by;
            y := (y and (255 - gs))+bx;
            end else
            begin
            bx := x and 7;
            y := y xor aryKey[bx];
            bx := y and 7;
            x := x xor aryKey[bx];
            end;
        Inc(sum,7);
        orx := (y and 7) xor (sum and 7);
        Inc(x,(aryKey[g] xor y) + ((sum xor (y shr (sum and 3)))+aryKey[orx]));
        Inc(sum,7);
        orx := (x and 7) xor (sum and 7);
        Inc(y,(aryKey[7-g] xor x) + ((sum xor (x shr (sum and 3)))+aryKey[orx]));
        end;
    pIn^ := y;
    Dec(pIn);
    pIn^ := x;
    Inc(pIn,2);
    end;
Result.Error := 0;
Result.Out1 := '';
pIn := pMem;
for i := 0 to Pred(len) do
    begin
    Result.Out1 := Result.Out1+IntToHex(pIn^,2);
    Inc(pIn);
    end;
len := len * 2;
InStr := Result.Out1[len];
Result.Out1 := Copy(Result.Out1, 1, Pred(len));
Result.Out1 := InStr+Result.Out1;
FreeMem(pMem);
end;

function TeaDecrypt(InStr: String; aryKey: TAryKey; VerAry: TAryVerify): TTeaRe;
var
i,len,len2,ke,g:LongInt;//
pIn,pMem,pLast: PByte;
x,y,sum,orx,gs,bx,by: Byte;

begin
Result.Error := 101;
Result.Out1 := 'ERROR - the Input Hex String is less than 8 charaters';
len2 := Length(InStr);
if len2 < 8 then Exit;
if Boolean(len2 and 1) then
    begin
    Result.Error := 102;
    Result.Out1 := 'ERROR - the Input Hex String has an Odd number of charaters';
    Exit;
    end;
Result.Out1 := InStr[1];
InStr := Copy(InStr, 2, len2-1);
InStr := InStr+Result.Out1;
len := len2 div 2;
InStr := UpperCase(InStr);
pLast := PByte(PChar(InStr));
pIn := pLast;
ke := 0;
bx := 0; by := 0;
for i := 1 to len do
    begin
    if pLast^ IN [48..57] then bx:=(pLast^ -48) shl 4 else
        if pLast^ IN [65..70] then bx := (pLast^ -55) shl 4 else
        begin
        ke := 1;
        break;
        end;
    Inc(pLast);
    if pLast^ IN [48..57] then by := pLast^ -48 else
        if pLast^ IN [65..70] then by := pLast^ -55 else
        begin
        ke := 1;
        break;
        end;
    pIn^ := bx + by;
    Inc(pLast);
    Inc(pIn);
    end;
if ke > 0 then
    begin
    Result.Error := 103;
    Result.Out1 := 'ERROR - the Input Hex String has Non-Hex charaters';
    Exit;
    end;
GetMem(pMem, len+16);
pIn := pMem;
CopyMemory(pIn, PChar(InStr), len);
len2 := ((len-(len and 1)) div 2)-1;
for i := 0 to len2 do
    begin
    x := pIn^;
    Inc(pIn);
    y := pIn^;
    sum := 112;
    for g := 7 downto 0 do
        begin
        orx := (x and 7) xor (sum and 7);
        Dec(y,(aryKey[7-g] xor x) + ((sum xor (x shr (sum and 3)))+aryKey[orx]));
        Dec(sum,7);
        orx := (y and 7) xor (sum and 7);
        Dec(x,(aryKey[g] xor y) + ((sum xor (y shr (sum and 3)))+aryKey[orx]));
        Dec(sum,7);
        if Boolean(g and 1) then
            begin
            gs := 1 shl g;
            bx := x and gs;
            by := y and gs;
            x := (x and (255 - gs))+by;
            y := (y and (255 - gs))+bx;
            end else
            begin
            bx := y and 7;
            x := x xor aryKey[bx];
            bx := x and 7;
            y := y xor aryKey[bx];
            end;
        end;
    pIn^ := y;
    Dec(pIn);
    pIn^ := x;
    Inc(pIn,2);
    end;
x := 0;
pIn := pMem;
Inc(pIn);
orx := pIn^;
Result.Out1 := Chr(orx);
Dec(pIn);
pIn^ := pIn^ xor orx;
if pIn^ <> VerAry[0] then Inc(x);
Inc(pIn,2);
pIn^ := (pIn^+256) - orx;
if pIn^ <> VerAry[1] then Inc(x);
Inc(pIn);
if len > 4 then
    begin
    orx := pIn^;
    Result.Out1 := Result.Out1+Chr(orx);
    Inc(pIn);
    if Boolean(len and 1) then
        begin
        pLast := PByte(LongInt(pMem)+(len-1));
        pLast^ := pLast^ xor aryKey[orx and 7];
        pLast^ := ((pLast^ + 256)- aryKey[2]) xor aryKey[5];
        pLast^ := ((pLast^ + 256)- orx) xor aryKey[1];
        end;
    pIn^ := (pIn^+256)-orx;
    if pIn^ <> VerAry[2] then Inc(x);
    Form1.Label4.Caption := Form1.Label4.Caption+' '+IntToStr(pIn^)+' '+IntToStr(VerAry[2]);
    end else
    begin
    pIn^ :=  pIn^ xor (255-orx);
    if pIn^ <> VerAry[2] then Inc(x);
    end;

if x <> 0 then
    begin
    Result.Error := 202;
    Result.Out1 := 'ERROR Verify numbers did not match';
    Form1.Label6.Caption := 'FAILED Verify';
    FreeMem(pMem);
    Exit;
    end else Form1.Label6.Caption := 'Verify was Correct';
Result.Error := 0;
Inc(pIn);
if len > 5 then for i := 0 to len-6 do
    begin
    Result.Out1 := Result.Out1+Chr(pIn^);
    Inc(pIn);
    end;
FreeMem(pMem);
end;

Open in new window

0
 
LVL 45

Expert Comment

by:aikimark
Comment Utility
@Slick812

Thank you for posting that.  

Here is a page with TEA/XTEA links
http://www.shokhirev.com/nikolai/programs/code/Cryptography/TeaSet.html
0
 
LVL 14

Expert Comment

by:systan
Comment Utility
Hello Slick812;
I'm glad to hear you,  I'm one of your delphi fanatics.  I've seen some your good codes.
Sorry for this pluggin, I though Slick was gone a long time ago.
0
 
LVL 33

Expert Comment

by:Slick812
Comment Utility
@systan, thanks for the comp, I am still gone, forever out to lunch, LOL

Yes, I had to switch from Delphi to MS Visual studio and C#, so I had no time to be in Pascal any longer, I haven't done any pascal coding in 5 or 6 years. I was doing this encryption stuff here as a blast from the past and it was some what of a challenge. I had to change over to PHP and web page development, because where I am, there did NOT seem to be any development opportunities except for web related stuff, because of the downturn of the economy.
I was thinking of maybe trying to write an article here at EE about open source (rijndael,3DES, twofish) encryption, since info about how the different components like - modes, IV, key, algorithm, and things to consider for using it are not explained much. Like the "mode" thing, untill I looked at the base code, I knew little (or less) about it, I had not seen an explanation of mode factors in all the junk I had read about encryption (at least in the PHP manual and other encryption "how to" sites). All of the open source are block sector based (usually 16,32,64 bit) for operating system optimization, I saw in the notes of the source code that they tested an encryption function by encrypting an entire hard drive. Seems like over kill for password encryption to use 64 bit blocks for a 14 character password. Maybe next month I can find time to try it, oh it's september already, this month?
0
 
LVL 14

Expert Comment

by:systan
Comment Utility
lol, good luck in your php web dev and .net c# aspx? Ok; its september weekend.
>>encryption function by encrypting an entire hard drive, lol, thats a joke.  bye
0
 

Author Comment

by:JealousyPrince
Comment Utility
Slick812, I really appreciate your help. This helped me a lot.. it is finally working :) I appreciate your time. Thank you very much
0
 
LVL 32

Expert Comment

by:DrDamnit
Comment Utility
Slick812:

Outstanding job. You have gone far above and beyond, and gotten the attention of many of the Zone Advisors and Mods for such a fine contribution.

Kudos to you!
0
 

Expert Comment

by:charin1904
Comment Utility
Hi,
   
       I have same problem as JealousyPrince., I try to compile & test code provide by Slick812 it doesnt work on Delphi 2010.  

       I have source attached both Php & Delphi project.  Expert please help...

PhpAndD2010Encrypt.zip
0

Featured Post

How to improve team productivity

Quip adds documents, spreadsheets, and tasklists to your Slack experience
- Elevate ideas to Quip docs
- Share Quip docs in Slack
- Get notified of changes to your docs
- Available on iOS/Android/Desktop/Web
- Online/Offline

Join & Write a Comment

Suggested Solutions

Part of the Global Positioning System A geocode (https://developers.google.com/maps/documentation/geocoding/) is the major subset of a GPS coordinate (http://en.wikipedia.org/wiki/Global_Positioning_System), the other parts being the altitude and t…
Envision that you are chipping away at another e-business site with a team of pundit developers and designers. Everything seems, by all accounts, to be going easily.
Explain concepts important to validation of email addresses with regular expressions. Applies to most languages/tools that uses regular expressions. Consider email address RFCs: Look at HTML5 form input element (with type=email) regex pattern: T…
This tutorial walks through the best practices in adding a local business to Google Maps including how to properly search for duplicates, marker placement, and inputing business details. Login to your Google Account, then search for "Google Mapmaker…

763 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

6 Experts available now in Live!

Get 1:1 Help Now