0

Is there some way to generate different output for same given string, here is example:

echo md5('test');

That always generates same fb469d7ef430b0baf0cab6c436e70375 for the given input. How do I generate different encrypted text each time and be able to decrypt it later if needed ?

I have seen functions such as md5, base64_encode, crypt, sha1, etc but they generate same output and secondly I cannot decrypt later if needed.

P.S: I know I can go with one way encryption and compare encrypted texts but for a particular scenario, I have requirement to be able to decrypt text completely if needed later however I am not able to figure out if there is some way or function in php for it.

Any help will be greatly appreciated. Thanks

Dev01
  • 4,082
  • 5
  • 29
  • 45
  • whats the point of hashing if you can reverse it to its original state again – Kevin Sep 29 '14 at 13:39
  • 1
    You are confusing `encryption` algorithms with `hash` algorithms. `MD5` and `SHA1` are `one-way hash` algorithms and are not meant to be "decrypted". You should use an `encryption` algorithm like `3DES`, `AES`, `TwoFish`, etc. – Sani Huttunen Sep 29 '14 at 13:40
  • `md5` and `sha1` are ***not*** encryption functions, they're hashing algorithms, and the whole point of them is that they're one-way only. Good hashes cannot be _"decrypted"_ – Elias Van Ootegem Sep 29 '14 at 13:40
  • @SaniHuttunen: Oh sorry about that, yes i want to be able to encrypt given text and decrypt it later but condition is that encrypted text should be different even for same given string. – Dev01 Sep 29 '14 at 13:41
  • @EliasVanOotegem: Then use an `encryption` algorithm. Each algorithm will take a `key` (which you can define or choose randomly). This `key` is used to encrypt the data and also to decrypt it. The same `plaintext` will result in different `ciphertext` if you use different `keys`. – Sani Huttunen Sep 29 '14 at 13:44
  • What are you trying to hash? Is it a password? If so, use a password hash. – Ja͢ck Sep 29 '14 at 13:47
  • @SaniHuttunen: Is there way i can use same key ? – Dev01 Sep 29 '14 at 13:47
  • @Ja͢ck: no it is not password, it is some text which is not needed to be necessarily secure like passwords – Dev01 Sep 29 '14 at 13:48
  • Perhaps [this answer](http://stackoverflow.com/questions/10916284/how-to-encrypt-decrypt-data-in-php/10945097#10945097) will be useful for you. – Ja͢ck Sep 29 '14 at 13:50
  • @SaniHuttunen: You don't need to explain the difference to me, I commented that hashing and encryption algo's aren't the same thing – Elias Van Ootegem Sep 29 '14 at 14:23
  • @EliasVanOotegem: Wasn't meant for you sorry (was meant for Dev01). Must have pressed E + Tab instead of D + Tab. – Sani Huttunen Sep 29 '14 at 14:35

3 Answers3

1

To encrypt the same plaintext so that it generates different ciphertext you change the key (and/or Initialization Vector (IV) depending on the mode of the algorithm, like CBC).

Example:

$string = 'Some Secret thing I want to encrypt'; 
$iv = '12345678'; 
$passphrase = '8chrsLng'; 

$encryptedString = encryptString($string, $passphrase, $iv); 
// Expect: 7DjnpOXG+FrUaOuc8x6vyrkk3atSiAf425ly5KpG7lOYgwouw2UATw== 

function encryptString($unencryptedText, $passphrase, $iv) { 
  $enc = mcrypt_encrypt(MCRYPT_BLOWFISH, $passphrase, $unencryptedText, MCRYPT_MODE_CBC, $iv); 
  return base64_encode($enc); 
}

Both the same IV and the passphrase must be used when decrypting in CBC mode. The passphrase MUST be kept a secret (from eavesdroppers) while the IV can be transmitted in the clear.

You CAN (but should not) use the same passphrase for every message/data but you should ALWAYS change the IV for each message/data.

This is the basics of encryption but depending on you needs you may need to modify your architecture to keep the system secure.

Sani Huttunen
  • 23,620
  • 6
  • 72
  • 79
  • $iv value should always be 8 characters long ? because if i increase it, i get error of blocksize to be same – Dev01 Sep 29 '14 at 13:57
  • 1
    @Dev01: The `IV` must always be of the same length as the `block size` of the algorithm. In this case the `block size` in 64 bits (8 characters). – Sani Huttunen Sep 29 '14 at 14:43
  • I would upvote this if you could generate and prepend a random IV and use AES (`MCRYPT_RIJNDAEL_128`) in your code. – Maarten Bodewes Sep 29 '14 at 15:50
  • marking this answer as correct cause it gave the idea. I have created a class for the purpose as shown in my answer. – Dev01 Sep 30 '14 at 10:02
0

md5 is a hash method, not an encryption.

in short. there is no "good" way back from md5.

base64_encode and base64_decode and be used to transport messages, but it is no decryption.

please google on the topic RSA, ROT-13 or basic encryption with php.

Benjamin Eckstein
  • 884
  • 2
  • 9
  • 19
0

I have created this class (Thanks to @Sani Huttunen for the idea) for the purpose. It allows to have differ text generated each time even for same input text and decodes it successfully as well.

class Encoder
{
    private static $prefix = '@!@';

    public static function php_aes_encrypt($text, $key)
    {
        if (!trim($text)) {
            return '';
        }

        $iv = self::generateRandomString();
        $key = self::mysql_aes_key($key);

        $pad_value = 16 - (strlen($text) % 16);
        $text = str_pad($text, (16 * (floor(strlen($text) / 16) + 1)), chr($pad_value));
        $ciphertext = mcrypt_encrypt(
           MCRYPT_RIJNDAEL_128,
           $key,
           $text,
           MCRYPT_MODE_CBC,
           $iv
        );

        $ciphertext = self::getPrefix() . base64_encode($ciphertext . $iv);
        return $ciphertext;
    }

    public static function php_aes_decrypt($text, $key)
    {
        $text = str_replace(self::getPrefix(), '', $text);
        $text = base64_decode($text);

        if (!trim($text)) {
            return '';
        }

        $iv = substr($text, -16);
        $text = str_replace($iv, '', $text);

        $key = self::mysql_aes_key($key);
        $text = mcrypt_decrypt(
           MCRYPT_RIJNDAEL_128,
           $key,
           $text,
           MCRYPT_MODE_CBC,
           $iv
        );

        return rtrim($text, "\0..\16");
    }

    private static function mysql_aes_key($key)
    {
        $new_key = str_repeat(chr(0), 16);

        for ($i = 0, $len = strlen($key); $i < $len; $i ++) {
            $new_key[$i % 16] = $new_key[$i % 16] ^ $key[$i];
        }

        return $new_key;
    }

    private static function getPrefix()
    {
        return base64_encode(self::$prefix);
    }

    public static function isEncrypted($ciphertext)
    {
        $isEncrypted = (false !== strpos($ciphertext, self::getPrefix()));
        return $isEncrypted;
    }

    private static function generateRandomString()
    {
        return substr(sha1(rand()), 0, 16);
    }
}

Usage:

$encrypted = Encoder::php_aes_encrypt('my test string', 'key');
echo $encrypted . '<br>';
echo Encoder::php_aes_decrypt($encrypted, 'key');
Dev01
  • 4,082
  • 5
  • 29
  • 45