php:如何为同一个字符串生成不同的输出

时间:2014-09-29 13:35:51

标签: php string encryption random

是否有某种方法可以为同一个给定的字符串生成不同的输出,例如:

echo md5('test');

对于给定的输入,它总是生成相同的fb469d7ef430b0baf0cab6c436e70375。如何在每次生成不同的加密文本并在以后需要时解密?

我见过md5base64_encodecryptsha1等功能,但它们生成相同的输出,其次,如果需要,我无法解密。

PS:我知道我可以使用单向加密并比较加密文本但是对于特定情况,我要求能够在以后需要时完全解密文本但是我无法弄清楚是否有某种方式或者在php中运行它。

任何帮助将不胜感激。感谢

3 个答案:

答案 0 :(得分:1)

要加密相同的plaintext,以便生成不同的ciphertext,您可以更改密钥(和/或Initialization Vector (IV),具体取决于算法的模式,如CBC)。

示例:

$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); 
}

IV模式下解密时,必须使用相同的passphraseCBCpassphrase必须保密(来自窃听者),而IV可以明确传输。

您可以(但不应该)对每条消息/数据使用相同的passphrase,但您应该始终为每条消息/数据更改IV

这是加密的基础知识,但根据您的需要,您可能需要修改架构以保证系统安全。

答案 1 :(得分:0)

md5是哈希方法,而不是加密方法。

简而言之。从md5回来没有“好”的方式。

base64_encode和base64_decode用于传输消息,但它不是解密。

请关注主题RSA,ROT-13或使用php进行基本加密。

答案 2 :(得分:0)

为此,我创建了这个课程(感谢@Sani Huttunen的想法)。它允许每次生成不同的文本,即使是相同的输入文本,也可以成功解码。

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);
    }
}

用法:

$encrypted = Encoder::php_aes_encrypt('my test string', 'key');
echo $encrypted . '<br>';
echo Encoder::php_aes_decrypt($encrypted, 'key');