I have a class in both PHP and C++ to simply take a value string and salt string to do some salting for privacy. The idea is a PHP script will encrypt a string for a C++ program to receive and decrypt. They use a pre-shared salt string, synchronous mode.
The issue is with what appears to be the same logic they generate a different result for encrypting the same string. This means that decrypting the string either end will not result in the original string it was given.
It is probably something really simple I have missed or made a mistake on. Or possibly it is related to PHP using character encoding where as C++ is a raw bit stream. The PHP script is set to use a plain text output, with ‘us-ascii’ encoding.
Here is the PHP class:
define( 'NUM_STRINGS', 256 );
class CTwEncryption
{
function Crypt( $szValue, $szSalt )
{
$iValueSize = (int)strlen( $szValue );
$iSaltSize = (int)strlen( $szSalt );
$szStrings = array();
$szKeys = array();
$j = 1;
// Init array of 0-255
for ( $i = 0; $i < NUM_STRINGS; $i++ )
$szStrings[ $i ] = $i;
// Init array of 0-255 with a calculated char value
for ( $i = 0; $i < NUM_STRINGS; $i++ )
{
if ( $j > $iSaltSize )
$j = 1;
$szKeys[ $i ] = ord( substr( $szSalt, $j, 1 ) );
$j++;
}
// Shuffle the array values around to give a random value
$j = 0;
for ( $i = 0; $i < NUM_STRINGS; $i++ )
{
$j = ( $j + $szStrings[ $i ] + $szKeys[ $i ] ) % NUM_STRINGS;
$szTemp = $szStrings[ $i ];
$szStrings[ $i ] = $szStrings[ $j ];
$szStrings[ $j ] = $szTemp;
}
// Encrypt/decrypt the string
$szReturnValue = null;
$i = 0;
$j = 0;
for ( $x = 0; $x < $iValueSize; $x++ )
{
$i = ( $i + 1 ) % NUM_STRINGS;
$j = ( $j + $szStrings[ $i ] ) % NUM_STRINGS;
$szTemp = $szStrings[ $i ];
$szStrings[ $i ] = $szStrings[ $j ];
$szStrings[ $j ] = $szTemp;
$t = ( $szStrings[ $i ] + ( $szStrings[ $j ] % NUM_STRINGS ) ) % NUM_STRINGS;
$y = $szStrings[ $t ];
$cCrypt = chr( substr( $szValue, $x, 1 ) ^ $y );
$szReturnValue .= $cCrypt;
}
// Return encrypted/decrypted string
return $szReturnValue;
}
}
Here is the C++ class:
#define NUM_STRINGS 256
class CTwEncryption
{
private:
char *szWorking;
public:
CTwEncryption() { szWorking = NULL; };
~CTwEncryption() { if ( szWorking != NULL ) { delete szWorking; szWorking = NULL; } };
char *Crypt( const char szValue[], const char szSalt[] )
{
const int iValueSize = (int)strlen( szValue );
const int iSaltSize = (int)strlen( szSalt );
if ( iValueSize == 0 || iSaltSize == 0 )
return NULL;
int j = 1;
char *szStrings[ NUM_STRINGS ];
char *szKeys[ NUM_STRINGS ];
// Init array of 0-255
for ( int i = 0; i < NUM_STRINGS; i++ )
{
char *szString = new char[ iValueSize + 1 ];
itoa( i, szString, 10 );
szString[ iValueSize ] = 0;
szStrings[ i ] = szString;
}
// Init array of 0-255 with a calculated char value
for ( int i = 0; i < NUM_STRINGS; i++ )
{
char *szKey = new char[ iValueSize + 1 ];
if ( j > iSaltSize )
j = 1;
itoa( (int)( szSalt[ j ] ), szKey, 10 );
szKey[ iValueSize ] = 0;
szKeys[ i ] = szKey;
j++;
}
// Shuffle the array values around to give a random value
j = 0;
for ( int i = 0; i < NUM_STRINGS; i++ )
{
j = ( j + atoi( szStrings[ i ] ) + atoi( szKeys[ i ] ) ) % NUM_STRINGS;
char *szTemp = szStrings[ i ];
szStrings[ i ] = szStrings[ j ];
szStrings[ j ] = szTemp;
}
// Encrypt/decrypt the string
szWorking = new char[ iValueSize + 1 ];
for ( int i = 0; i <= iValueSize; i++ )
szWorking[ i ] = 0;
int i = 0;
j = 0;
for ( int x = 0; x <= iValueSize; x++ )
{
i = ( i + 1 ) % NUM_STRINGS;
j = ( j + atoi( szStrings[ i ] ) ) % NUM_STRINGS;
char *szTemp = szStrings[ i ];
szStrings[ i ] = szStrings[ j ];
szStrings[ j ] = szTemp;
int t = ( atoi( szStrings[ i ] ) + ( atoi( szStrings[ j ] ) % NUM_STRINGS ) ) % NUM_STRINGS;
int y = atoi( szStrings[ t ] );
char cCrypt = char( (int)( szValue[ x ] ) ^ y );
szWorking[ x ] = cCrypt;
}
// Clean dynamic memory
for ( int i = 0; i < NUM_STRINGS; i++ )
{
delete szStrings[ i ];
delete szKeys[ i ];
szStrings[ i ] = NULL;
szKeys[ i ] = NULL;
}
// Return encrypted/decrypted string
szWorking[ iValueSize ] = 0;
return szWorking;
}
};
Any help here would be appreciated, thanks 🙂
Figured this out. Looks like I need to send input to a PHP script via a HTTP PUT request, and read it using fopen( “php://input”, “rb” ). It appeared that PHP was not hanlding anything in a binary safe fashion. Also both on C++ and PHP I’m treating each character as an integer, which should allow UTF-32 strings to be handled correctly in binary safe mode.
Here is my C++ class, I have mine in “twencrypt.h”:
As it returns a char pointer I recommend you use strcpy() to put it in a safe place. Here is an example, and bare in mind the exact same code is used to decrypt a string too.
Here is my PHP class:
This one is a bit easier to use. It’s simply:
Remember that you should not define $szString or $szSalt (PHP side) via a HTTP GET or POST request. Be safe and use a PUT request, and read it like this:
Enjoy.