AES 5种加密模式 && 初始向量的影响

本文详细介绍了AES的五种工作模式:ECB、CBC、CFB、OFB和CTR,以及它们对初始向量(IV)的依赖。在CBC、CFB和OFB模式中,IV只影响数据的前16字节,而在CTR模式中,IV影响整个数据。文章通过PHP代码示例展示了这些模式的加密和解密过程,并指出在已知密钥情况下,IV的安全作用有限,推荐使用CTR模式。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

引言

写这篇文章是由于,关于如何使用AES的文章很多,大多都是API调用,但是关于IV初始向量的作用好像没几个文章有写,IV初始向量CBCCFB模式下,仅影响前16字节(128位加密方式)的块,推荐使用CTR模式。

AES的工作模式

AES的工作模式(ECBCBCCFBOFBCTR)。

  • OPENSSL_ZERO_PADDING
    你可以使用OPENSSL_ZERO_PADDINGflag,让它自动填充0x00(使用自动填充返回的内容就直接是base64编码过的了,并不是二进制数据),虽然也可以再base64Decode变会二进制数据,但是这样做感觉像是多此一举,但是由于php不建议使用OPENSSL_ZERO_PADDING,实际上会无效,还是需要你手动补齐,它唯一的作用就是直接返回base64格式的编码。
  • OPENSSL_NO_PADDING
    推荐使用OPENSSL_NO_PADDING手动填充,我们可以自写填充函数,好处是我们可以自己选择需要二进制数据还是base64数据。
  • OPENSSL_RAW_DATA
    OPENSSL_RAW_DATA不填充数据。

ECB模式(电子密码本模式:Electronic codebook)

加密前根据加密块大小分成若干块,之后将每块使用相同的密钥单独加密,解密同理。

<?php
	
$data = '0123456789abcdefghijklmnopqrstuvwxyz';
$key = "0123456789abcdef";

$encode = base64_encode(openssl_encrypt($data,"AES-128-ECB",$key,OPENSSL_RAW_DATA));
$decode = openssl_decrypt(base64_decode($encode),"AES-128-ECB",$key,OPENSSL_RAW_DATA);

echo $encode.PHP_EOL;
echo $data.PHP_EOL;
echo $decode.PHP_EOL;

?>

输出内容:

shellcnJ+iB7c/QEApxhoeQm1ZcZmX1z/d7UC1tQtnJD7Dk38io1fHY85My7I/tQPjI3b

0123456789abcdefghijklmnopqrstuvwxyz
0123456789abcdefghijklmnopqrstuvwxyz

CBC模式(密码分组链接:Cipher-block chaining)

CBC模式对于每个待加密的密码块在加密前会先与前一个密码块的密文异或然后再用加密器加密第一个明文块初始向量数据块异或
这里的初始向量第二重保障,让开头的16字节(128位加密方式)初始向量异或具体看下面的栗子。

这里正好演示一下flag,手动补齐0x00之类的。

<?php
function PadZero($data, $blocksize = 16)
{
	$pad = $blocksize - (strlen($data) % $blocksize);
	return $data . str_repeat("\0", $pad);
}
	
$data = '0123456789abcdefghijklmnopqrstuvwxyz';
$key = "0123456789abcdef";
$iv = '8NONwyJtHesysWpM';
$iv2 = 'gergergertqqwerw';

$encode = base64_encode(openssl_encrypt(PadZero($data),"AES-128-CBC",$key,OPENSSL_NO_PADDING,$iv));
//OPENSSL_ZERO_PADDING自动填充,由于php的问题,还是需要手动补齐,但是返回的直接是base64编码
$encode2 = openssl_encrypt(PadZero($data),"AES-128-CBC",$key,OPENSSL_ZERO_PADDING,$iv);

// 解密
$decode = openssl_decrypt(base64_decode($encode),"AES-128-CBC",$key,OPENSSL_NO_PADDING,$iv2);

//解密还是需要OPENSSL_NO_PADDING
$decode2 = openssl_decrypt(base64_decode($encode2),"AES-128-CBC",$key,OPENSSL_NO_PADDING,$iv2);
echo $encode.PHP_EOL;
echo $encode2.PHP_EOL;
echo $data.PHP_EOL;
echo $decode.PHP_EOL;
echo $decode2.PHP_EOL;
?>

输出内容:
最后那十二个方框实际上是0x00,因为我们加密时补齐了0,我只是写出来让你们看的更明白。

k2GXq52ijs28l14F1JOBFDB2YiEX0BmKpES8bsce9JXpL4FtfHsYldzVt1w3UbSb
k2GXq52ijs28l14F1JOBFDB2YiEX0BmKpES8bsce9JXpL4FtfHsYldzVt1w3UbSb
0123456789abcdefghijklmnopqrstuvwxyz
o&>&(cjgVg\ghijklmnopqrstuvwxyz□□□□□□□□□□□□
o&>&(cjgVg\ghijklmnopqrstuvwxyz□□□□□□□□□□□□

结论,CBC的初始向量只影响数据头部16字节(128位加密方式),所以也没有特别安全。只是加密过程更安全,但是在得知密钥的情况下,IV初始向量作用不大

CFB模式(密文反馈:Cipher feedback)

将前一段加密得到的密文再加密,将第一步加密得到的数据与当前段的明文异或。不要求与16字节(128位加密方式)对齐

<?php
	
$data = '0123456789abcdefghijklmnopqrstuvwxyz';
$key = "0123456789abcdef";
$iv = '8NONwyJtHesysWpM';
$iv2 = 'gergergertqqwerw';

$encode = base64_encode(openssl_encrypt($data,"AES-128-CFB",$key,OPENSSL_RAW_DATA,$iv));


// 解密
$decode = openssl_decrypt(base64_decode($encode),"AES-128-CFB",$key,OPENSSL_RAW_DATA,$iv2);

echo $encode.PHP_EOL;
echo $data.PHP_EOL;
echo $decode.PHP_EOL;

?>

输出内容:

5MuwKWvcGaXaKfenTlK9IX2GpGr3AtFW9qPB8L0ZtOwZ6lPm
0123456789abcdefghijklmnopqrstuvwxyz
KB�����Ǻ�w	~&@ghijklmnopqrstuvwxyz

结论,CFB的初始向量只影响数据头部16字节(128位加密方式),所以同样没有特别安全。同样在得知密钥的情况下,IV初始向量作用不大

OFB模式(输出反馈:Output feedback)

OFB是先用块加密器生成密钥流(Keystream),然后再将密钥流与明文流异或得到密文流解密是先用块加密器生成密钥流,再将密钥流与密文流异或得到明文,由于异或操作对称性所以加密解密流程一样

<?php
$data = '0123456789abcdefghijklmnopqrstuvwxyz';
$key = "0123456789abcdef";
$iv = '8NONwyJtHesysWpM';
$iv2 = 'gergergertqqwerw';

$encode = base64_encode(openssl_encrypt($data,"AES-128-OFB",$key,OPENSSL_RAW_DATA,$iv));

// 解密
$decode = openssl_decrypt(base64_decode($encode),"AES-128-OFB",$key,OPENSSL_RAW_DATA,$iv2);

echo $encode.PHP_EOL;
echo $data.PHP_EOL;
echo $decode.PHP_EOL;
?>

输出内容:

shell5MuwKWvcGaXaKfenTlK9Ibkd7J6mqD8+YTkratN3B5RNyZfF
0123456789abcdefghijklmnopqrstuvwxyz
KB�����Ǻ�w	~&@b)��2A��8]�cȐQ�A

结论,OFB的初始向量影响整个数据,是因为他的加密机制,利用密钥流与明文流整体异或,哪怕初始向量只有一个字节不同,结果都会差很多。

CTR模式 (计数器:Counter)

它和OFB有些类似,但是有一个counter计数器,每次加密就+1,用这个值使用加密器加密,然后与明文分组异或

<?php
$data = '0123456789abcdefghijklmnopqrstuvwxyz';
$key = "0123456789abcdef";
$iv = '8NONwyJtHesysWpM';
$iv2 = 'gergergertqqwerw';

$encode = base64_encode(openssl_encrypt($data,"AES-128-CTR",$key,OPENSSL_RAW_DATA,$iv));

// 解密
$decode = openssl_decrypt(base64_decode($encode),"AES-128-CTR",$key,OPENSSL_RAW_DATA,$iv2);

echo $encode.PHP_EOL;
echo $data.PHP_EOL;
echo $decode.PHP_EOL;
?>

输出内容:

5MuwKWvcGaXaKfenTlK9IVbSSYBHiHol+Ye3qJBeRdPgfY8h
0123456789abcdefghijklmnopqrstuvwxyz
�Z��Iڱ9���aUX�w鳴��I�(k�iZ&[

结论,CTR的初始向量影响整个数据,也是因为他的加密机制,哪怕初始向量只有一个字节不同,结果都会差很多。

评论 11
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

没事干写博客玩

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值