简单的PHP加密/解密(Mcrypt,AES)

3
我正在寻找一个简单而又具有加密强度的PHP实现AES,使用Mcrypt。
希望将其简化为一对简单的函数,$garble = encrypt($key, $payload)$payload = decrypt($key, $garble)

一旦我完成这个,我也会非常感兴趣实现一个兼容的JavaScript版本。 - ChaseMoskal
有一些php/js的实现:2011/08/matching-php-and-js-encryption。此外,aes-php.html - Ryan Vincent
PHP/JavaScript 组合听起来像是 TLS(SSL的后继者)/ HTTPS 的典型用例。 - Perseids
我有一个类在这里玩耍(http://codereview.stackexchange.com/questions/49267/mcrypt-are-there-any-flaws-or-areas-for-improvement-in-this-class)。我并不建议使用它(因此在codereview上),但可能会给你一些灵感。 - Luke
@ilovecode,抱歉,我并没有以任何方式批评你的代码!我只是试图解释其他人对安全性的担忧。'twofish'虽然安全,但已经有些老了。不,GUID和'uniqid()'不同。GUID:这个在线GUID生成器可能会有用。 - Ryan Vincent
显示剩余3条评论
4个回答

12

我最近在学习这个主题,并将这个答案作为社区维基来分享我的知识,同时也欢迎纠正。

据我了解,使用以下常量选项可以通过Mcrypt实现AES加密:

MCRYPT_RIJNDAEL_128     // as cipher
MCRYPT_MODE_CBC         // as mode
MCRYPT_MODE_DEV_URANDOM // as random source (for IV)

在加密过程中,应使用随机的非秘密初始化向量(IV)来随机化每个加密结果(以确保相同的加密结果不会产生相同的乱码)。该IV应附加到加密结果中,以便在解密过程中使用。

结果应进行Base 64编码以实现简单的兼容性。

实施:

<?php

define('IV_SIZE', mcrypt_get_iv_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_CBC));

function encrypt ($key, $payload) {
  $iv = mcrypt_create_iv(IV_SIZE, MCRYPT_DEV_URANDOM);
  $crypt = mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $key, $payload, MCRYPT_MODE_CBC, $iv);
  $combo = $iv . $crypt;
  $garble = base64_encode($iv . $crypt);
  return $garble;
}

function decrypt ($key, $garble) {
  $combo = base64_decode($garble);
  $iv = substr($combo, 0, IV_SIZE);
  $crypt = substr($combo, IV_SIZE, strlen($combo));
  $payload = mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $key, $crypt, MCRYPT_MODE_CBC, $iv);
  return $payload;
}


//:::::::::::: TESTING ::::::::::::


$key = "secret-key-is-secret";
$payload = "In 1435 the abbey came into conflict with the townspeople of Bamberg and was plundered.";

// ENCRYPTION
$garble = encrypt($key, $payload);

// DECRYPTION
$end_result = decrypt($key, $garble);

// Outputting Results
echo "Encrypted: ", var_dump($garble), "<br/><br/>";
echo "Decrypted: ", var_dump($end_result);

?>

输出看起来像这样:
Encrypted: string(152) "4dZcfPgS9DRldq+2pzvi7oAth/baXQOrMmt42la06ZkcmdQATG8mfO+t233MyUXSPYyjnmFMLwwHxpYiDmxvkKvRjLc0qPFfuIG1VrVon5EFxXEFqY6dZnApeE2sRKd2iv8m+DiiiykXBZ+LtRMUCw==" 

Decrypted: string(96) "In 1435 the abbey came into conflict with the townspeople of Bamberg and was plundered."

1
你能指出这段代码与 mcrypt_encrypt 中的 PHP 示例代码有何不同吗? - Maarten Bodewes
@owlstead:在这里,我们定义了一对简单、可重用的函数。这里使用MCRYPT_DEV_URANDOM作为IV源,而不是据称更好的MCRYPT_RAND。我仍在努力确定是否重要对密钥进行哈希处理,甚至加盐。我还想使其与常见的AES JavaScript库互操作,但我还没有确定选择哪一个。 - ChaseMoskal
1
MCRYPT_DEV_URANDOM 在我的看法中比 MCRYPT_RANDOM 更好,所以对于 IV 来说这是可以的。密钥应随机生成(使用示例中的十六进制)。如果你想使用密码,你需要将 PBKDF (例如 bcrypt) 添加到混合中;密码不是密钥。没有所谓的“通用 AES 库”。浏览器中的 JavaScript 加密技术至少是有争议的。 - Maarten Bodewes
请注意,目前似乎还没有 PHP 版本的 RNCryptor - Maarten Bodewes
@owlstead:我意识到你是对的,我必须将密码加盐哈希成密钥。我很快就会添加这个功能,但在此之前,我需要想出最好的bcrypt方法。PHP 5.5+中的password_hash()看起来很不错,但不确定是否有其他方便的方法适用于早期版本的PHP。明天可能会更新这个。谢谢! - ChaseMoskal
显示剩余2条评论

1

添加清除控制字符(�)的功能。

function clean($string) {
return preg_replace('/[\x00-\x09\x0B\x0C\x0E-\x1F\x7F]/', '', $string);

}

echo "Decrypted: ", clean($end_result);

Sentrapedagang.com


0

简单易用:

$text= 'Hi, i am sentence';
$secret = 'RaNDoM cHars!@#$%%^';

$encrypted = simple_encrypt($text,           $secret);
$decrypted = simple_decrypt($encrypted_text, $secret);

代码:

function simple_encrypt($text_to_encrypt, $salt)    { 
    return trim(base64_encode(mcrypt_encrypt(MCRYPT_RIJNDAEL_128,  pack('H*', $salt), $text_to_encrypt, MCRYPT_MODE_CBC, $iv =  mcrypt_create_iv($iv_size = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_CBC), MCRYPT_RAND))));
}

function simple_decrypt($encrypted, $salt)  { 
    return trim(mcrypt_decrypt(MCRYPT_RIJNDAEL_128, pack('H*', $salt), base64_decode($encrypted), MCRYPT_MODE_CBC, $iv = mcrypt_create_iv($iv_size=mcrypt_get_iv_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_CBC), MCRYPT_RAND))); 
}

-1

类 Mycrypt

尝试使用这个类。在这里。你只需要传递密钥和字符串。

class MCrypt
{
    const iv = 'fedcba9876543210';

    /**
 * @param string $str
 * @param bool $isBinary whether to encrypt as binary or not. Default is: false
 * @return string Encrypted data
 */
public static function encrypt($str, $key="0123456789abcdef", $isBinary = false)
{
    $iv = self::iv;
    $str = $isBinary ? $str : utf8_decode($str);
    $td = mcrypt_module_open('rijndael-128', ' ', 'cbc', $iv);
    mcrypt_generic_init($td, $key, $iv);
    $encrypted = mcrypt_generic($td, $str);
    mcrypt_generic_deinit($td);
    mcrypt_module_close($td);
    return $isBinary ? $encrypted : bin2hex($encrypted);
}

/**
 * @param string $code
 * @param bool $isBinary whether to decrypt as binary or not. Default is: false
 * @return string Decrypted data
 */
public static function decrypt($code, $key="0123456789abcdef", $isBinary = false)
{
    $code = $isBinary ? $code : self::hex2bin($code);
    $iv = self::iv;
    $td = mcrypt_module_open('rijndael-128', ' ', 'cbc', $iv);
    mcrypt_generic_init($td, $key, $iv);
    $decrypted = mdecrypt_generic($td, $code);
    mcrypt_generic_deinit($td);
    mcrypt_module_close($td);
    return $isBinary ? trim($decrypted) : utf8_encode(trim($decrypted));
}

private static function hex2bin($hexdata)
{
    $bindata = '';
    for ($i = 0; $i < strlen($hexdata); $i += 2) {
        $bindata .= chr(hexdec(substr($hexdata, $i, 2)));
    }
    return $bindata;
}
   }

如何使用

 $var = json_encode(['name'=>['Savatar', 'Flash']]);
 $encrypted = MCrypt::encrypt();
 $decrypted = MCrypt::decrypt($encrypted);

我不认为更改加密数据的字符编码是相关的。如果我想加密我的诗歌,使俄语、中文和希伯来语韵律相同,会发生什么?我认为你应该将上下文特定的字符编码处理排除在你的密码学范围之外。 - Bigue Nique

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接