PHP AES 加解密示例

PHP 中 AES 加密和解密的原理主要基于对称加密算法。对称加密算法使用相同的密钥进行加密和解密操作,常见的对称加密算法包括 AESDES3DES 等。

AES 加密解密原理

在 PHP 中,你可以使用 OpenSSL 扩展来实现 AES 加密和解密。AES 加密算法采用分组密码的方式,将明文分成固定长度的数据块,然后对每个数据块使用相同的密钥进行加密。解密时使用相同的密钥对密文进行解密,还原出原始的明文。

具体的加密和解密过程如下:

加密过程

  1. 选择一个合适的密钥,长度可以是 128 位、192 位或 256 位。
  2. 选择一个合适的初始化向量(IV),长度为 16 字节(128 位)。
  3. 将明文分成固定长度的数据块,每个数据块的长度与密钥长度相同(128 位)。
  4. 使用密钥对每个数据块进行加密,生成相应的密文。
  5. 可以选择使用 padding 方式对明文进行补齐,以确保明文的长度符合要求。常见的 padding 方式有 PKCS7PKCS5 等。
  6. 将加密后的数据块和初始化向量进行合并,生成最终的密文。

解密过程:

  1. 获取加密过程中使用的密钥和初始化向量。
  2. 将密文分成固定长度的数据块,每个数据块的长度与密钥长度相同(128 位)。
  3. 使用相同的密钥对每个数据块进行解密,还原出相应的明文。
  4. 可以选择使用相同的 padding 方式对解密后的数据进行处理,以确保还原的明文符合要求。
  5. 将解密后的数据块和初始化向量进行合并,生成最终的明文。

需要注意的是,在实际应用中,为了确保数据的安全性,通常会在传输过程中对数据进行加密,并在接收端进行解密。同时,为了防止重复攻击和篡改攻击,还需要对数据进行校验和签名等操作。

示例

1. 创建合适的密钥

对于这个,我们可以生成一个随机字符串,长度为 32 字节就行(也就是 256 位),下面是一个例子:

function randomStr($length = 32)
{
    // 随机数种子
    mt_srand(microtime(true) * 1000000);

    $characters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
    $charactersLength = strlen($characters);
    $randomString = '';
    for ($i = 0; $i < $length; $i++) {
        $randomString .= $characters[rand(0, $charactersLength - 1)];
    }

    return $randomString;
}

在这个例子中,我们默认生成 32 字节的字符串,当然 AES 也支持 16 字节的,根据我们需要去选择即可。

注意:在我们的应用中,不需要每次调用加密解密函数都去生成一个新的密钥。而是在整个应用的生命周期中,只使用同一个密钥。除非我们的密钥泄漏了,才需要去更换。

因为密钥需要用来加密,但是也需要使用同一个密钥来进行解密。

2. 加密

下面是一个加密的函数:

// 加密函数
public static function encrypt($key, $data): string
{
    $ivLength      = openssl_cipher_iv_length('AES-256-CBC');
    $iv            = openssl_random_pseudo_bytes($ivLength);
    $encryptedData = openssl_encrypt($data, 'AES-256-CBC', $key, OPENSSL_RAW_DATA, $iv);

    return base64_encode($iv . $encryptedData);
}

过程如下:

  • 使用 openssl_cipher_iv_length 获取 AES-256-CBC 模式下的初始向量(IV)长度。
  • 使用 openssl_random_pseudo_bytes 生成随机的初始向量 $iv
  • 使用 openssl_encrypt 对数据进行 AES-256-CBC 模式的加密,使用密钥 $key 和初始向量 $iv
  • 最后,将初始向量和加密后的数据拼接在一起,并使用 base64_encode 对结果进行 Base64 编码,返回最终的加密字符串。

注意:openssl_encrypt 得到的是二进制数据,我们一般需要进行 base64 转换为字节流来进行传输。

3. 解密

下面是一个解密的函数:

// 解密函数
public static function decrypt($key, $encryptedData)
{
    $data          = base64_decode($encryptedData);
    $ivLength      = openssl_cipher_iv_length('AES-256-CBC');
    $iv            = substr($data, 0, $ivLength);
    $encryptedData = substr($data, $ivLength);

    return openssl_decrypt($encryptedData, 'AES-256-CBC', $key, OPENSSL_RAW_DATA, $iv);
}

过程如下:

  • 使用 base64_decode 对加密后的字符串进行 Base64 解码,得到包含初始向量和加密数据的二进制字符串 $data
  • 使用 openssl_cipher_iv_length 获取 AES-256-CBC 模式下的初始向量(IV)长度。
  • 使用 substr 将初始向量 $iv 和加密数据 $encryptedData 分别截取出来。
  • 使用 openssl_decrypt 对加密数据进行 AES-256-CBC 模式的解密,使用密钥 $key 和初始向量 $iv
  • 最终,返回解密后的原始数据。

完整代码如下:

class Aes
{
    // 加密函数
    public static function encrypt($key, $data): string
    {
        $ivLength      = openssl_cipher_iv_length('AES-256-CBC');
        $iv            = openssl_random_pseudo_bytes($ivLength);
        $encryptedData = openssl_encrypt($data, 'AES-256-CBC', $key, OPENSSL_RAW_DATA, $iv);

        return base64_encode($iv . $encryptedData);
    }

    // 解密函数
    public static function decrypt($key, $encryptedData)
    {
        $data          = base64_decode($encryptedData);
        $ivLength      = openssl_cipher_iv_length('AES-256-CBC');
        $iv            = substr($data, 0, $ivLength);
        $encryptedData = substr($data, $ivLength);

        return openssl_decrypt($encryptedData, 'AES-256-CBC', $key, OPENSSL_RAW_DATA, $iv);
    }
}

iv 的作用是什么?

我们在上面的代码中看到了有个叫 iv 的东西,那它是什么呢?到底有什么作用呢?

IVInitialization Vector,初始化向量)是在对称加密算法中使用的一种辅助输入,主要作用是增加密码算法的强度和安全性。

AES 加密中,IV 是一个随机生成的固定长度的二进制串,通常与密钥一起用于初始化加密算法。每次使用相同密钥进行加密时,可以使用不同的 IVIV 的主要作用包括:

  1. 破解抵抗性: 在相同的密钥下,使用不同的 IV 加密相同的明文,可以产生不同的密文。这使得攻击者难以分析并找到明文和密文之间的模式。如果每次加密都使用相同的 IV,那么相同的明文会产生相同的密文,这样就容易受到攻击。

  2. 防止密码分析: 使用不同的 IV 可以避免在密码分析中出现的一些问题,比如对相同明文的多次加密产生相同的密文。IV 的引入使得相同明文在不同的加密操作中产生不同的密文。

  3. 增加密码强度: IV 的随机性和不可预测性有助于增加密码算法的强度。攻击者无法通过事先知道的信息来预测 IV 的值,从而增加了密码的安全性。

总的来说,IV 的引入有助于防止对称加密算法中的一些攻击,并提高密码算法的安全性。在实际应用中,IV 的生成应当是随机的且不可预测的,以达到最佳的安全效果。

总结

上述 PHP 代码演示了在 PHP 中使用 AES 加密和解密的原理。AES 是一种对称加密算法,使用相同的密钥进行加密和解密。在 PHP 中,使用 OpenSSL 扩展实现了 AES 加密和解密。

AES 加密的原理包括选择合适的密钥和初始化向量(IV),将明文分成数据块,使用密钥和 IV 对每个数据块进行加密,最后合并成最终的密文。解密则是相反的过程,使用相同的密钥和 IV 对密文进行解密,还原出原始的明文。

示例代码中还包括了生成随机密钥和加密解密函数的实现。密钥的安全性对于加密算法的安全至关重要,因此建议在实际应用中采用足够安全的方法生成和管理密钥。

最后,解释了初始化向量(IV)的作用,它在对称加密中用于增加算法的强度和安全性,防止密码分析和提高密码强度。 IV 的生成应当是随机的和不可预测的,以提高安全性。

你可能感兴趣的:(PHP,php,开发语言)