Two-way encryption in PHP

I found two quite interesting examples at Stack Overflow about two-way encrytion / hashing in PHP. While two-way encryption is never as secure as one-way version (some claim, that two-way encryption methods are not secure at all), it is still a good alternative to not using encryption at all. For certain simple tasks, you may find it quite useful.

Here are some examples, modified from mentioned examples.

Stack Overflow solution

If you need to use them in many places, it is better to declare some reusable functions (or even class methods), as I found at Stack Overflow's first example:

const KEY = 'salt';

function encrypt($string)
{
    $encrypted = base64_encode(mcrypt_encrypt(MCRYPT_RIJNDAEL_256, md5(KEY), $string, MCRYPT_MODE_CBC, md5(md5(KEY))));
    return $encrypted;
}

function decrypt($encrypted)
{
    $decrypted = rtrim(mcrypt_decrypt(MCRYPT_RIJNDAEL_256, md5(KEY), base64_decode($encrypted), MCRYPT_MODE_CBC, md5(md5(KEY))), "");
    return $decrypted;
}

If you need to use it directly, then second example sounds better:

const KEY = 'salt';
$string = 'string to be encrypted';

$encrypted = base64_encode(mcrypt_encrypt(MCRYPT_RIJNDAEL_256, md5(KEY), $string, MCRYPT_MODE_CBC, md5(md5(KEY))));
$decrypted = rtrim(mcrypt_decrypt(MCRYPT_RIJNDAEL_256, md5(KEY), base64_decode($encrypted), MCRYPT_MODE_CBC, md5(md5(KEY))), "");

var_dump($encrypted);
var_dump($decrypted);

I don't actually know why, but I don't like solution based on base64_encode / base64_decode. That ending = character pisses me off really hard. It alerts potential intruder, what kind of algorithm he or she is dealing with.

But in these examples this is unavoidable, because without these two functions, you could end up with some non-Latin characters. Quite hard to use, when dealing with strings. And certainly very not good idea when transecting such data over some text-based protocols, like HTTP.

My old alternative

I have searched my old notes and found some other functions, that I last time used in 2009. They aren't too pretty. Actually, because they're using chr and ord, they're not pretty at all. But, if for any reasons, you can't use above examples, maybe these two will suit you better.

Here is an encoding function:

const KEY = 'salt';

function encode($string)
{
    $hash = '';
    $key = sha1(KEY);

    $strLen = strlen($string);
    $keyLen = strlen($key);

    $j = 0;

    for ($i = 0; $i < $strLen; $i++)
    {
        $ordStr = ord(substr($string, $i, 1));

        if($j == $keyLen) $j = 0;

        $ordKey = ord(substr($key,$j,1));
        $j++;

        $hash .= strrev(base_convert(dechex($ordStr + $ordKey), 16, 36));
    }

    return $hash;
}

And here is the decoding one:

function decode($string)
{
    $hash = '';
    $key = sha1(KEY);

    $strLen = strlen($string);
    $keyLen = strlen($key);

    $j = 0;

    for ($i = 0; $i < $strLen; $i+=2)
    {
        $ordStr = hexdec(base_convert(strrev(substr($string, $i, 2)), 36, 16));

        if($j == $keyLen) $j = 0;

        $ordKey = ord(substr($key, $j, 1));
        $j++;

        $hash .= chr($ordStr - $ordKey);
    }

    return $hash;
}

My even older alternative

There is another solution, shorter, that also dates back to 2009, that I don't -- again -- recall at all:

function _enc($s)
{
    for($i = 0; $i < strlen($s); $i++) $r[] = ord($s[$i]) + 2;

    return implode('.', $r);
}

function _dec($s)
{
    $s = explode(".", $s);

    for($i = 0; $i < count($s); $i++) $s[$i] = chr($s[$i] - 2);

    return implode('', $s);
}

Conclusion

Let's be honest. You would have to actually drink a lot of cheap alcohol to these functions a "encryption and decryption set"! They're simple like a hell, extremely easy to break, awful bit shifting, that has nothing to do with real encryption or security.

Thus, use it only, if you work with moron-customer, which you want to bill twice: first for application design and second, for implementation of better security routines.

In real world and serious project, don't use these at all!

Leave a Reply