2014-09-29 72 views
0

是否有某种方式来产生相同的字符串给出不同的输出,是例如:PHP:这里怎么产生不同的输出相同的字符串

echo md5('test'); 

总是产生给定的输入相同fb469d7ef430b0baf0cab6c436e70375。我如何每次生成不同的加密文本,并在需要时能够解密它?

我看到的功能,如md5base64_encodecryptsha1等,但它们产生相同的输出,其次,如果需要我不能后来解密。 PS:我知道我可以使用单向加密和比较加密文本,但对于特定场景,我有要求能够彻底解密文本,如果需要稍后但是我无法弄清楚是否有一些方式或功能在它的PHP。

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

+0

什么散列如果你能再次扭转到原来的状态 – Ghost 2014-09-29 13:39:45

+1

你混淆了'hash'算法'encryption'算法的点。 'MD5'和'SHA1'是'单向哈希'算法,并不意味着被“解密”。你应该使用'3DES','AES','TwoFish'等加密算法。 – 2014-09-29 13:40:25

+0

'md5'和'sha1'都不是***加密函数,它们是散列算法,它们的重点在于它们只是单向的。好的哈希不能被“解密”_ – 2014-09-29 13:40:57

回答

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

两个相同IVpassphrase必须CBC模式解密时使用。 passphrase必须保密(来自窃听者),而IV可以透明传送。

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

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

+0

$ iv的值应该总是8个字符?因为如果我增加它,我得到块大小错误是相同的 – Dev01 2014-09-29 13:57:35

+1

@ Dev01:'IV'必须总是与算法的'块大小'相同的长度。在这种情况下,“块大小”为64位(8个字符)。 – 2014-09-29 14:43:15

+0

如果你可以生成并预先设置一个随机IV并在你的代码中使用AES('MCRYPT_RIJNDAEL_128'),我会赞成这个。 – 2014-09-29 15:50:48

0

md5是一种散列方法,而不是加密。

简而言之。从MD5没有“好”的方式。

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

请谷歌的话题RSA,ROT-13或基本加密与PHP。

0

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

class Encoder 
{ 
    private static $prefix = '@[email protected]'; 

    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'); 
相关问题