分组密码的工作模式
Posted 陈如初
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了分组密码的工作模式相关的知识,希望对你有一定的参考价值。
分组密码的工作模式简介
- 在实际应用中,需要加密的消息的数据量是不定的,数据格式可能是多种多样的,因此需要做一些变通,灵活的使用这些基本密码。
- 需要采用适当的块处理方式来隐藏明文的统计特性、数据格式等,以提高整体的安全性,降低删除、重放、插入和伪造成功的机会。
这种针对基本密码算法采用不同的块处理方式,就是密码模式,也成为分组密码的工作模式。
密码模式通常是基本密码、一些反馈和一些简单运算的组合。
分组密码的工作模式
1、电子密码本模式(ECB)
- 流程图
- 电子密码本模式(EBC)特点:
(1)如果明文大于64比特,首先将其分为长为64比特的分组; 若最后一个分组如果不够64比特,则需要填充;
(2)明文加密过程和解密过程分别调用加密算法和解密算法。
(3) 不需要额外的初始向量。
(4)密文块可以分别独立解密,无顺序要求。
(5) 模式操作简单,主要用于数据随机且较少的报文的加密传递(比如加密密钥);
(6) 相同明文(在相同密钥下)得出相同的密文,即明文中的重复内容将在密文中表现出来,容易受统计分析攻击、分组重放攻击和代换攻击;
(7) 链接依赖性:各组的加密都独立于其他分组,可实现并行处理;
(8) 良好的差错控制:单个密文分组中有一个或多个比特错误只会影响该分组的解密结果
2、密码分组链接模式(CBC)
-
流程图
-
密码分组链接模式(CBC)模式特点:
(1) 反馈机制在分组密码中的应用,每个密文分组不仅依赖于产生它的明文分组,还依赖于它前面的所有分组;(雪崩效应)
(2) 相同的明文,即使用相同的密钥下也会得到不同的密文分组,隐藏了明文的统计特性;
(3) 链接依赖性:对于一个正确密文分组的正确解密要求它之前的那个密文分组也正确,不能实现并行处理;
(4) 错误传播:密文分组中的一个单比特错误会影响到本组和其后分组的解密,错误传播为两组;
(5) 初始化向量IV不需要保密,它可以明文形式与密文一起传送。密文块需按顺序逐一解密
3、密码反馈模式(CFB)
-
流程图
-
密码反馈模式(CFB)特点:
(1)消息被看做bit流,不需要整个数据分组在接收完成后才能进行加解密。
(2) 将分组密码转换成了序列密码,可用于同步序列密码。具有CBC模式的优点。
(3) 对信道错误较敏感且会造成错误传播。
(4) 数据加解密的速率较低,其数据率不会太高。
4、输出反馈模式(OFB)
- 流程图
- 输出反馈模式(OFB)
(1)OFB模式是CFB模式的一种改进,克服由错误传播带来的问题,但对密文被篡改难于进行检测;
(2) OFB模式不具有自动同步能力,要求系统保持严格的同步,否则难于解密;
(3)初始向量IV无需保密,但各条消息必须选用不同的IV;
5、计数器模式(CTR)
-
流程图
-
计数器模式(CTR)特点:
(1) 效率
(2) 可并行加密
(3) 预处理
(4) 吞吐量仅受可使用并行数量的限制
(5) 加密数据块的随机访问
(6)可证明安全
(7)简单性(只要求实现加密算法)
几种工作模式的对比
(1) ECB是最快、最简单的分组密码模式,但它的安全性最弱,一般不推荐使用ECB加密,但如
果加密随机数据,如密钥,ECB是最好的选择。
(2) CBC适合文件加密,而且有少量错误时不会造成同步失败,是软件加密的最好选择。
(3) CFB通常是加密字符序列所选择的模式,它也能容忍少量错误扩展,而且具有同步恢复能力。
(4) OFB是在极易出错的环境中选用的模式,但需有高速同步机制。CFB和OFB适合流模式加解密。
分组密码模式: CBC模式(密码分组链接模式)
CBC模式是将前一个密文分组与当前明文分组的内容混合起来进行加密的,这样就可以避免ECB模式的弱点。
在CBC模式中,首先将明文分组与前一个密文分组进行XOR运算,然后再进行加密,如下图所示:
如果将一个分组的加密过程分离出来,我们就可以很容易地比较出ECB模式和CBC模式的区别,ECB模式只进行了加密,而CBC模式则在加密之前进行了一次XOR,如下图所示:
当加密第一个明文分组时,由于不存在“前一个密文分组”,因此需要事先准备一个长度为一个分组的比特序列来代替“前一个密文分组”,这个比特序列称为初始化向量,通常缩写为IV。
CBC模式优点:
1. 不容易主动攻击, 安全性好于ECB, 适合传输长度长的报文, 是SSL、IPSec的标准
CBC模式缺点:
1. 不利于并行计算
2. 误差传递
3. 需要初始化向量IV
对CBC模式的攻击,截图来源自图解密码技术一书:
CBC模式的加密:
#include <STRING.H> #define IN #define OUT //假设加密分组为4字节一组 void Encrypt(IN char *lpszData, IN char *lpszKey, OUT char *lpszEnData) { int i = 0; for (i = 0; i < 4; i++) { lpszEnData[i] = lpszData[i] ^ lpszKey[i]; } } void Decrypt(IN char *lpszData, IN char *lpszKey, OUT char *lpszDeData) { int i = 0; for (i = 0; i < 4; i++) { lpszDeData[i] = lpszData[i] ^ lpszKey[i]; } } int main(int argc, char* argv[]) { char szData[] = "Hello World!"; char szEnData[16] = {0}; char szDeData[16] = {0}; char *lpszKey = "1234"; int i = 0; char szIV[] = "9999"; printf("原始数据: %s\\r\\n", szData); while (true) { if (strlen(szData + i) == 0) { break; } //首先需要与前一个密文分组进行xor //由于自己的加密也是异或, 所以就不单独写与密文分组的xor函数了 Encrypt(szData + i, szIV, szData + i); //更新密文分组 Encrypt(szData + i, lpszKey, szIV); memcpy(szEnData + i, szIV, 4); i += 4; } printf("加密后数据: %s\\r\\n", szEnData); memcpy(szIV, "9999", 4); i = 0; char szPreEnData[8] = {0}; while (true) { if (strlen(szEnData + i) == 0) { break; } memcpy(szPreEnData, szEnData + i, 4); //先解密 Decrypt(szEnData + i, lpszKey, szEnData + i); //再与前一个密文分组进行xor //由于自己的加密也是异或, 所以就不单独写与密文分组的xor函数了 Decrypt(szEnData + i, szIV, szIV); memcpy(szDeData + i, szIV, 4); memcpy(szIV, szPreEnData, 4); i += 4; } printf("解密后数据: %s\\r\\n", szDeData); return 0; }
原始数据: Hello World!
加密后数据: @nfa|:]"U/
解密后数据: Hello World!
以上是关于分组密码的工作模式的主要内容,如果未能解决你的问题,请参考以下文章