首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >PHP AES加密/解密

PHP AES加密/解密
EN

Stack Overflow用户
提问于 2010-08-06 18:08:11
回答 10查看 268.9K关注 0票数 61

我找到了一个用PHP对字符串进行en/解码的示例。一开始它看起来很好,但它不会工作:-(

有人知道问题出在哪里吗?

代码语言:javascript
复制
$Pass = "Passwort";
$Clear = "Klartext";

$crypted = fnEncrypt($Clear, $Pass);
echo "Encrypted: ".$crypted."</br>";

$newClear = fnDecrypt($crypted, $Pass);
echo "Decrypted: ".$newClear."</br>";

function fnEncrypt($sValue, $sSecretKey) {
    return trim(base64_encode(mcrypt_encrypt(MCRYPT_RIJNDAEL_256, $sSecretKey, $sDecrypted, MCRYPT_MODE_ECB, mcrypt_create_iv(mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_ECB), MCRYPT_RAND))));
}

function fnDecrypt($sValue, $sSecretKey) {
    return trim(mcrypt_decrypt(MCRYPT_RIJNDAEL_256, $sSecretKey, base64_decode($sEncrypted), MCRYPT_MODE_ECB, mcrypt_create_iv(mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_ECB), MCRYPT_RAND)));
}

结果是:

加密:boKRNTYYNp7AiOvY1CidqsAn9wX4ufz/D9XrpjAOPk8=

解密:—‚(ÑÁ ^ yË~F'¸®Ó–í œð2Á_B‰Â—

EN

回答 10

Stack Overflow用户

回答已采纳

发布于 2010-08-06 18:12:15

$sDecrypted$sEncrypted在您的代码中未定义。查看有效的解决方案(但不安全!):

停!

这个例子是不安全的!请勿使用它!

代码语言:javascript
复制
$Pass = "Passwort";
$Clear = "Klartext";        

$crypted = fnEncrypt($Clear, $Pass);
echo "Encrypred: ".$crypted."</br>";

$newClear = fnDecrypt($crypted, $Pass);
echo "Decrypred: ".$newClear."</br>";        

function fnEncrypt($sValue, $sSecretKey)
{
    return rtrim(
        base64_encode(
            mcrypt_encrypt(
                MCRYPT_RIJNDAEL_256,
                $sSecretKey, $sValue, 
                MCRYPT_MODE_ECB, 
                mcrypt_create_iv(
                    mcrypt_get_iv_size(
                        MCRYPT_RIJNDAEL_256, 
                        MCRYPT_MODE_ECB
                    ), 
                    MCRYPT_RAND)
                )
            ), "\0"
        );
}

function fnDecrypt($sValue, $sSecretKey)
{
    return rtrim(
        mcrypt_decrypt(
            MCRYPT_RIJNDAEL_256, 
            $sSecretKey, 
            base64_decode($sValue), 
            MCRYPT_MODE_ECB,
            mcrypt_create_iv(
                mcrypt_get_iv_size(
                    MCRYPT_RIJNDAEL_256,
                    MCRYPT_MODE_ECB
                ), 
                MCRYPT_RAND
            )
        ), "\0"
    );
}

但是在这段代码中还有其他问题使得它不安全,特别是使用ECB (它不是模式,只能在其上定义加密模式的构建块)。有关最严重问题的快速修复,请参阅 ;有关如何正确执行此操作,请参阅

票数 60
EN

Stack Overflow用户

发布于 2015-05-11 19:06:52

请使用现有的secure PHP encryption library

除非你有破解别人的密码学实现的经验,否则编写自己的密码学通常是一个坏主意。

这里的示例都不是authenticate the ciphertext,这使得它们容易受到位重写攻击。

如果你能安装PECL扩展,libsodium会更好

代码语言:javascript
复制
<?php
// PECL libsodium 0.2.1 and newer

/**
 * Encrypt a message
 * 
 * @param string $message - message to encrypt
 * @param string $key - encryption key
 * @return string
 */
function safeEncrypt($message, $key)
{
    $nonce = \Sodium\randombytes_buf(
        \Sodium\CRYPTO_SECRETBOX_NONCEBYTES
    );

    return base64_encode(
        $nonce.
        \Sodium\crypto_secretbox(
            $message,
            $nonce,
            $key
        )
    );
}

/**
 * Decrypt a message
 * 
 * @param string $encrypted - message encrypted with safeEncrypt()
 * @param string $key - encryption key
 * @return string
 */
function safeDecrypt($encrypted, $key)
{   
    $decoded = base64_decode($encrypted);
    $nonce = mb_substr($decoded, 0, \Sodium\CRYPTO_SECRETBOX_NONCEBYTES, '8bit');
    $ciphertext = mb_substr($decoded, \Sodium\CRYPTO_SECRETBOX_NONCEBYTES, null, '8bit');

    return \Sodium\crypto_secretbox_open(
        $ciphertext,
        $nonce,
        $key
    );
}    

然后进行测试:

代码语言:javascript
复制
<?php
// This refers to the previous code block.
require "safeCrypto.php"; 

// Do this once then store it somehow:
$key = \Sodium\randombytes_buf(\Sodium\CRYPTO_SECRETBOX_KEYBYTES);
$message = 'We are all living in a yellow submarine';

$ciphertext = safeEncrypt($message, $key);
$plaintext = safeDecrypt($ciphertext, $key);

var_dump($ciphertext);
var_dump($plaintext);

这可用于向客户端传递数据的任何情况(例如,没有服务器端存储的会话的加密cookie、加密的URL参数等)。并且具有终端用户不能破译或可靠地篡改它的相当高的确定性。

由于libsodium is cross-platform,这也使得从Java applet或原生移动应用程序与PHP进行通信变得更容易。

注意:如果你特别需要在你的应用程序中添加由library驱动的加密cookie,我的雇主Paragon Initiative Enterprises正在开发一个名为Halite的库,它可以为你完成所有这些工作。

票数 88
EN

Stack Overflow用户

发布于 2017-10-22 17:31:23

如果你不想对15行代码就能解决的事情使用重依赖,那么可以使用内置的OpenSSL函数。大多数PHP安装都带有OpenSSL,它在PHP中提供了快速、兼容和安全的AES加密。好吧,只要你遵循最佳实践,它就是安全的。

以下代码:

  • 在CBC模式下使用AES256,并且与其他AES实现方式兼容,但不能使用mcrypt,因为mcrypt使用hmac而不是来自所提供密码的密钥,使用SHA256

  • generates加密数据的hmac散列来保证完整性每个check

  • generates IV (16字节)和散列(32字节) to ciphertext

  • should be

IV是公共信息,对于每条消息都需要是随机的。散列确保数据没有被篡改。

代码语言:javascript
复制
function encrypt($plaintext, $password) {
    $method = "AES-256-CBC";
    $key = hash('sha256', $password, true);
    $iv = openssl_random_pseudo_bytes(16);

    $ciphertext = openssl_encrypt($plaintext, $method, $key, OPENSSL_RAW_DATA, $iv);
    $hash = hash_hmac('sha256', $ciphertext . $iv, $key, true);

    return $iv . $hash . $ciphertext;
}

function decrypt($ivHashCiphertext, $password) {
    $method = "AES-256-CBC";
    $iv = substr($ivHashCiphertext, 0, 16);
    $hash = substr($ivHashCiphertext, 16, 32);
    $ciphertext = substr($ivHashCiphertext, 48);
    $key = hash('sha256', $password, true);

    if (!hash_equals(hash_hmac('sha256', $ciphertext . $iv, $key, true), $hash)) return null;

    return openssl_decrypt($ciphertext, $method, $key, OPENSSL_RAW_DATA, $iv);
}

用法:

代码语言:javascript
复制
$encrypted = encrypt('Plaintext string.', 'password'); // this yields a binary string

echo decrypt($encrypted, 'password');
// decrypt($encrypted, 'wrong password') === null

编辑:更新为使用hash_equals,并在散列中添加了IV。

票数 65
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/3422759

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档