PHP中的AES-256加密

mar*_*nnn 24 php security encryption aes encryption-symmetric

我需要一个PHP函数,AES256_encode($dataToEcrypt)加密$data到AES-256,另一个AES256_decode($encryptedData)反过来.有谁知道这个函数应该有什么代码?

Fab*_*bio 16

看看mcrypt模块

AES-Rijndael示例取自此处

$iv_size = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_CBC);
$iv = mcrypt_create_iv($iv_size, MCRYPT_DEV_URANDOM);
$key = pack('H*', "bcb04b7e103a0cd8b54763051cef08bc55abe029fdebae5e1d417e2ffb2a00a3");
# show key size use either 16, 24 or 32 byte keys for AES-128, 192
# and 256 respectively
$key_size =  strlen($key);
echo "Key size: " . $key_size . "\n";
$text = "Meet me at 11 o'clock behind the monument.";
echo strlen($text) . "\n";

$crypttext = mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $key, $text, MCRYPT_MODE_CBC, $iv);
echo strlen($crypttext) . "\n";
Run Code Online (Sandbox Code Playgroud)

这是解密功能

  • -1,AES-256与`RIJNDAEL-256`不同**."AES"中的256表示*key*大小,其中"RIJNDAEL"中的256表示块大小.与256位密钥一起使用时,`AES-256`是`RIJNDAEL-128`. (11认同)
  • @CodesInChaos我根据你的观察编辑了答案.现在答案应该是正确的. (2认同)
  • 我只想强调,如果可以进行主动攻击,MAC非常重要.众所周知的攻击是["padding oracle"](http://en.wikipedia.org/wiki/Padding_oracle_attack),其中收件人的反应泄漏有关明文的信息,允许通过查询逐字节恢复明文收件人. (2认同)
  • PHP 已弃用 `mcrypt` 库,它将在 7.1 之后从 PHP 版本中删除。因此,使用建议 mcrypt 会弃用此答案。见 http://php.net/manual/en/migration71.deprecated.php (2认同)

Sco*_*ski 15

我需要一个PHP函数,AES256_encode($dataToEcrypt)加密$data到AES-256,另一个AES256_decode($encryptedData)反过来.有谁知道这个函数应该有什么代码?

加密和编码之间存在差异.

真的需要AES-256吗?AES-256与AES-128的安全性并不显着; 你更容易搞砸协议层而不是被黑客攻击,因为你使用的是128位分组密码而不是256位分组密码.

重要 - 使用库

PHP用户的流程图

快速而肮脏的AES-256实施

如果你有兴趣建立自己的不是为了在生产中部署它而是为了你自己的教育,我已经包括一个样本AES256

/**
 * This is a quick and dirty proof of concept for StackOverflow.
 * 
 * @ref http://stackoverflow.com/q/6770370/2224584
 * 
 * Do not use this in production.
 */
abstract class ExperimentalAES256DoNotActuallyUse
{
    /**
     * Encrypt with AES-256-CTR + HMAC-SHA-512
     * 
     * @param string $plaintext Your message
     * @param string $encryptionKey Key for encryption
     * @param string $macKey Key for calculating the MAC
     * @return string
     */
    public static function encrypt($plaintext, $encryptionKey, $macKey)
    {
        $nonce = random_bytes(16);
        $ciphertext = openssl_encrypt(
            $plaintext,
            'aes-256-ctr',
            $encryptionKey,
            OPENSSL_RAW_DATA,
            $nonce
        );
        $mac = hash_hmac('sha512', $nonce.$ciphertext, $macKey, true);
        return base64_encode($mac.$nonce.$ciphertext);
    }

    /**
     * Verify HMAC-SHA-512 then decrypt AES-256-CTR
     * 
     * @param string $message Encrypted message
     * @param string $encryptionKey Key for encryption
     * @param string $macKey Key for calculating the MAC
     */
    public static function decrypt($message, $encryptionKey, $macKey)
    {
        $decoded = base64_decode($message);
        $mac = mb_substr($message, 0, 64, '8bit');
        $nonce = mb_substr($message, 64, 16, '8bit');
        $ciphertext = mb_substr($message, 80, null, '8bit');

        $calc = hash_hmac('sha512', $nonce.$ciphertext, $macKey, true);
        if (!hash_equals($calc, $mac)) {
            throw new Exception('Invalid MAC');
        }
        return openssl_decrypt(
            $ciphertext,
            'aes-256-ctr',
            $encryptionKey,
            OPENSSL_RAW_DATA,
            $nonce
        );
    }
}
Run Code Online (Sandbox Code Playgroud)

用法

首先,生成两个键(是的,其中两个)并以某种方式存储它们.

$eKey = random_bytes(32);
$aKey = random_bytes(32);
Run Code Online (Sandbox Code Playgroud)

然后加密/解密消息:

$plaintext = 'This is just a test message.';
$encrypted = ExperimentalAES256DoNotActuallyUse::encrypt($plaintext, $eKey, $aKey);
$decrypted = ExperimentalAES256DoNotActuallyUse::decrypt($encrypted, $eKey, $aKey);
Run Code Online (Sandbox Code Playgroud)

如果你没有random_bytes(),请获取random_compat.

  • 你能解释为什么在生产中使用快速和肮脏的实现不是一个好主意吗? (3认同)
  • 是的,但举例来说,我想处理诸如从 CPP 通过套接字到 PHP 的流加密之类的事情。我个人没有研究过 defuse 的库,但是上面写的通用 AES256 是否有原因不适合?显然不是确切的代码,但就构建密码而言是类似的。 (2认同)

小智 13

MCRYPT_RIJNDAEL_256不等同于AES_256.

使RIJNDAEL从AES解密的方法是使用MCRYPT_RIJNDAEL_128并在加密前填充字符串进行加密

AES-256的BlockSize = 128bit,KeySize = 256bit Rijndael-256的BlockSize = 256bit,KeySize = 256bit

只有AES/Rijndael 128bit是完全相同的.Rijndael-192和Rijndael-256与AES-192和AES-256不同(块大小和轮数不同).

  • 你当然是对的,但这篇文章并没有真正回答这个问题。 (2认同)