PHP 中 AES
加密和解密的原理主要基于对称加密算法。对称加密算法使用相同的密钥进行加密和解密操作,常见的对称加密算法包括 AES
、DES
、3DES
等。
在 PHP 中,你可以使用 OpenSSL
扩展来实现 AES
加密和解密。AES
加密算法采用分组密码的方式,将明文分成固定长度的数据块,然后对每个数据块使用相同的密钥进行加密。解密时使用相同的密钥对密文进行解密,还原出原始的明文。
具体的加密和解密过程如下:
IV
),长度为 16 字节(128 位)。padding
方式对明文进行补齐,以确保明文的长度符合要求。常见的 padding
方式有 PKCS7
、PKCS5
等。padding
方式对解密后的数据进行处理,以确保还原的明文符合要求。需要注意的是,在实际应用中,为了确保数据的安全性,通常会在传输过程中对数据进行加密,并在接收端进行解密。同时,为了防止重复攻击和篡改攻击,还需要对数据进行校验和签名等操作。
对于这个,我们可以生成一个随机字符串,长度为 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 字节的,根据我们需要去选择即可。
注意:在我们的应用中,不需要每次调用加密解密函数都去生成一个新的密钥。而是在整个应用的生命周期中,只使用同一个密钥。除非我们的密钥泄漏了,才需要去更换。
因为密钥需要用来加密,但是也需要使用同一个密钥来进行解密。
下面是一个加密的函数:
// 加密函数
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
转换为字节流来进行传输。
下面是一个解密的函数:
// 解密函数
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
(Initialization Vector
,初始化向量)是在对称加密算法中使用的一种辅助输入,主要作用是增加密码算法的强度和安全性。
在 AES
加密中,IV
是一个随机生成的固定长度的二进制串,通常与密钥一起用于初始化加密算法。每次使用相同密钥进行加密时,可以使用不同的 IV
。IV
的主要作用包括:
破解抵抗性: 在相同的密钥下,使用不同的 IV
加密相同的明文,可以产生不同的密文。这使得攻击者难以分析并找到明文和密文之间的模式。如果每次加密都使用相同的 IV
,那么相同的明文会产生相同的密文,这样就容易受到攻击。
防止密码分析: 使用不同的 IV
可以避免在密码分析中出现的一些问题,比如对相同明文的多次加密产生相同的密文。IV
的引入使得相同明文在不同的加密操作中产生不同的密文。
增加密码强度: IV
的随机性和不可预测性有助于增加密码算法的强度。攻击者无法通过事先知道的信息来预测 IV
的值,从而增加了密码的安全性。
总的来说,IV
的引入有助于防止对称加密算法中的一些攻击,并提高密码算法的安全性。在实际应用中,IV
的生成应当是随机的且不可预测的,以达到最佳的安全效果。
上述 PHP 代码演示了在 PHP 中使用 AES
加密和解密的原理。AES
是一种对称加密算法,使用相同的密钥进行加密和解密。在 PHP 中,使用 OpenSSL
扩展实现了 AES
加密和解密。
AES
加密的原理包括选择合适的密钥和初始化向量(IV
),将明文分成数据块,使用密钥和 IV
对每个数据块进行加密,最后合并成最终的密文。解密则是相反的过程,使用相同的密钥和 IV 对密文进行解密,还原出原始的明文。
示例代码中还包括了生成随机密钥和加密解密函数的实现。密钥的安全性对于加密算法的安全至关重要,因此建议在实际应用中采用足够安全的方法生成和管理密钥。
最后,解释了初始化向量(IV
)的作用,它在对称加密中用于增加算法的强度和安全性,防止密码分析和提高密码强度。 IV
的生成应当是随机的和不可预测的,以提高安全性。