简介
一般的加密通常都是块加密,如果要加密超过块大小的数据,就需要涉及填充和链加密模式,本文对对称加密和分组加密中的几种种模式进行一一分析(ECB、CBC、CFB、OFB,CTR)
电码本模式 Electronic Codebook Book (ECB)
概述
这种模式是将整个明文分成若干段相同的小段,然后对每一小段进行加密。
特点分析
优点:
- 简单;
- 有利于并行计算;
- 误差不会被传送;
缺点: - 不能隐藏明文的模式;
- 可能对明文进行主动攻击;
代码演示
/**
*@autho stardust
*@time 2013-10-10
*@param 实现AES五种加密模式的测试
*/
#include <iostream>
using namespace std;
//加密编码过程函数,16位1和0
int dataLen = 16; //需要加密数据的长度
int encLen = 4; //加密分段的长度
int encTable[4] = {1,0,1,0}; //置换表
int data[16] = {1,0,0,1,0,0,0,1,1,1,1,1,0,0,0,0}; //明文
int ciphertext[16]; //密文
//切片加密函数
void encode(int arr[])
{
for(int i=0;i<encLen;i++)
{
arr[i] = arr[i] ^ encTable[i];
}
}
//电码本模式加密,4位分段
void ECB(int arr[])
{
//数据明文切片
int a[4][4];
int dataCount = 0; //位置变量
for(int k=0;k<4;k++)
{
for(int t=0;t<4;t++)
{
a[k][t] = data[dataCount];
dataCount++;
}
}
dataCount = 0;//重置位置变量
for(int i=0;i<dataLen;i=i+encLen)
{
int r = i/encLen;//行
int l = 0;//列
int encQue[4]; //编码片段
for(int j=0;j<encLen;j++)
{
encQue[j] = a[r][l];
l++;
}
encode(encQue); //切片加密
//添加到密文表中
for(int p=0;p<encLen;p++)
{
ciphertext[dataCount] = encQue[p];
dataCount++;
}
}
cout<<"ECB加密的密文为:"<<endl;
for(int t1=0;t1<dataLen;t1++) //输出密文
{
if(t1!=0 && t1%4==0)
cout<<endl;
cout<<ciphertext[t1]<<" ";
}
cout<<endl;
cout<<"---------------------------------------------"<<endl;
}
密码分组链接模式 Cipher Block Chaining (CBC)
概述
这种模式是先将明文切分成若干小段,然后每一小段与初始块或者上一段的密文段进行异或运算后,再与密钥进行加密。
特点分析
优点:
- 不容易主动攻击,安全性好于ECB,适合传输长度长的报文,是SSL、IPSec的标准。
缺点: - 不利于并行计算;
- 误差传递;
- 需要初始化向量IV
代码演示
#include <iostream>
using namespace std;
//加密编码过程函数,16位1和0
int dataLen = 16; //需要加密数据的长度
int encLen = 4; //加密分段的长度
int encTable[4] = {1,0,1,0}; //置换表
int data[16] = {1,0,0,1,0,0,0,1,1,1,1,1,0,0,0,0}; //明文
int ciphertext[16]; //密文
//切片加密函数
void encode(int arr[])
{
for(int i=0;i<encLen;i++)
{
arr[i] = arr[i] ^ encTable[i];
}
}
//CBC
//密码分组链接模式,4位分段
void CBC(int arr[])
{
//数据明文切片
int a[4][4];
int dataCount = 0; //位置变量
for(int k=0;k<4;k++)
{
for(int t=0;t<4;t++)
{
a[k][t] = data[dataCount];
dataCount++;
}
}
dataCount = 0;//重置位置变量
int init[4] = {1,1,0,0}; //初始异或运算输入
//初始异或运算
for(int i=0;i<dataLen;i=i+encLen)
{
int r = i/encLen;//行
int l = 0;//列
int encQue[4]; //编码片段
//初始化异或运算
for(int k=0;k<encLen;k++)
{
a[r][k] = a[r][k] ^ init[k];
}
//与Key加密的单切片
for(int j=0;j<encLen;j++)
{
encQue[j] = a[r][j];
}
encode(encQue); //切片加密
//添加到密文表中
for(int p=0;p<encLen;p++)
{
ciphertext[dataCount] = encQue[p];
dataCount++;
}
//变换初始输入
for(int t=0;t<encLen;t++)
{
init[t] = encQue[t];
}
}
cout<<"CBC加密的密文为:"<<endl;
for(int t1=0;t1<dataLen;t1++) //输出密文
{
if(t1!=0 && t1%4==0)
cout<<endl;
cout<<ciphertext[t1]<<" ";
}
cout<<endl;
cout<<"---------------------------------------------"<<endl;
}
//CBC
//密码分组链接模式,4位分段
void CBC(int arr[])
{
//数据明文切片
int a[4][4];
int dataCount = 0; //位置变量
for(int k=0;k<4;k++)
{
for(int t=0;t<4;t++)
{
a[k][t] = data[dataCount];
dataCount++;
}
}
dataCount = 0;//重置位置变量
int init[4] = {1,1,0,0}; //初始异或运算输入
//初始异或运算
for(int i=0;i<dataLen;i=i+encLen)
{
int r = i/encLen;//行
int l = 0;//列
int encQue[4]; //编码片段
//初始化异或运算
for(int k=0;k<encLen;k++)
{
a[r][k] = a[r][k] ^ init[k];
}
//与Key加密的单切片
for(int j=0;j<encLen;j++)
{
encQue[j] = a[r][j];
}
encode(encQue); //切片加密
//添加到密文表中
for(int p=0;p<encLen;p++)
{
ciphertext[dataCount] = encQue[p];
dataCount++;
}
//变换初始输入
for(int t=0;t<encLen;t++)
{
init[t] = encQue[t];
}
}
cout<<"CBC加密的密文为:"<<endl;
for(int t1=0;t1<dataLen;t1++) //输出密文
{
if(t1!=0 && t1%4==0)
cout<<endl;
cout<<ciphertext[t1]<<" ";
}
cout<<endl;
cout<<"---------------------------------------------"<<endl;
}
计算器模式Counter (CTR)
概述
计算器模式不常见,在CTR模式中, 有一个自增的算子,这个算子用密钥加密之后的输出和明文异或的结果得到密文,相当于一次一密。这种加密方式简单快速,安全可靠,而且可以并行加密,但是 在计算器不能维持很长的情况下,密钥只能使用一次 。CTR的示意图如下所示:
特点分析
优点:
- 无填
- 同明文不同密
- 每个块单独运算,适合并行运算。
缺点: - 可能导致明文攻击。
代码演示
#include <iostream>
using namespace std;
//加密编码过程函数,16位1和0
int dataLen = 16; //需要加密数据的长度
int encLen = 4; //加密分段的长度
int encTable[4] = {1,0,1,0}; //置换表
int data[16] = {1,0,0,1,0,0,0,1,1,1,1,1,0,0,0,0}; //明文
int ciphertext[16]; //密文
//切片加密函数
void encode(int arr[])
{
for(int i=0;i<encLen;i++)
{
arr[i] = arr[i] ^ encTable[i];
}
}
//CTR
//计算器模式,4位分段
void CTR(int arr[])
{
//数据明文切片
int a[4][4];
int dataCount = 0; //位置变量
for(int k=0;k<4;k++)
{
for(int t=0;t<4;t++)
{
a[k][t] = data[dataCount];
dataCount++;
}
}
dataCount = 0;//重置位置变量
int init[4][4] = {{1,0,0,0},{0,0,0,1},{0,0,1,0},{0,1,0,0}}; //算子表
int l = 0; //明文切片表列
//初始异或运算
for(int i=0;i<dataLen;i=i+encLen)
{
int r = i/encLen;//行
int encQue[4]; //编码片段
//将算子切片
for(int t=0;t<encLen;t++)
{
encQue[t] = init[r][t];
}
encode(encQue); //算子与key加密
//最后的异或运算
for(int k=0;k<encLen;k++)
{
encQue[k] = encQue[k] ^ a[l][k];
}
l++;
//添加到密文表中
for(int p=0;p<encLen;p++)
{
ciphertext[dataCount] = encQue[p];
dataCount++;
}
}
cout<<"CTR加密的密文为:"<<endl;
for(int t1=0;t1<dataLen;t1++) //输出密文
{
if(t1!=0 && t1%4==0)
cout<<endl;
cout<<ciphertext[t1]<<" ";
}
cout<<endl;
cout<<"---------------------------------------------"<<endl;
}
密码反馈模式(Cipher FeedBack (CFB)
概述
特点分析
优点:
- 隐藏了明文模式;
- 分组密码转化为流模式;
- 可以及时加密传送小于分组的数据;
缺点: - 不利于并行计算;
- 误差传送:一个明文单元损坏影响多个单元;
- 唯一的IV;。
代码演示
/**
*@autho stardust
*@time 2013-10-10
*@param 实现AES五种加密模式的测试
*/
#include <iostream>
using namespace std;
//加密编码过程函数,16位1和0
int dataLen = 16; //需要加密数据的长度
int encLen = 4; //加密分段的长度
int encTable[4] = {1,0,1,0}; //置换表
int data[16] = {1,0,0,1,0,0,0,1,1,1,1,1,0,0,0,0}; //明文
int ciphertext[16]; //密文
//切片加密函数
void encode(int arr[])
{
for(int i=0;i<encLen;i++)
{
arr[i] = arr[i] ^ encTable[i];
}
}
//CFB
//密码反馈模式,4位分段
void CFB(int arr[])
{
//数据明文切片,切成2 * 8 片
int a[8][2];
int dataCount = 0; //位置变量
for(int k=0;k<8;k++)
{
for(int t=0;t<2;t++)
{
a[k][t] = data[dataCount];
dataCount++;
}
}
dataCount = 0; //恢复初始化设置
int lv[4] = {1,0,1,1}; //初始设置的位移变量
int encQue[2]; //K的高两位
int k[4]; //K
for(int i=0;i<2 * encLen;i++) //外层加密循环
{
//产生K
for(int vk=0;vk<encLen;vk++)
{
k[vk] = lv[vk];
}
encode(k);
for(int k2=0;k2<2;k2++)
{
encQue[k2] = k[k2];
}
//K与数据明文异或产生密文
for(int j=0;j<2;j++)
{
ciphertext[dataCount] = a[dataCount/2][j] ^ encQue[j];
dataCount++;
}
//lv左移变换
lv[0] = lv[2];
lv[1] = lv[3];
lv[2] = ciphertext[dataCount-2];
lv[3] = ciphertext[dataCount-1];
}
cout<<"CFB加密的密文为:"<<endl;
for(int t1=0;t1<dataLen;t1++) //输出密文
{
if(t1!=0 && t1%4==0)
cout<<endl;
cout<<ciphertext[t1]<<" ";
}
cout<<endl;
cout<<"---------------------------------------------"<<endl;
}
输出反馈模式Output FeedBack (OFB)
概述
特点分析
优点:
- 同明文不同密文,分组密钥转换为流密码。
缺点: - 串行运算不利并行
- 传输错误可能导致后续传输块错误。
代码演示
/**
*@autho stardust
*@time 2013-10-10
*@param 实现AES五种加密模式的测试
*/
#include <iostream>
using namespace std;
//加密编码过程函数,16位1和0
int dataLen = 16; //需要加密数据的长度
int encLen = 4; //加密分段的长度
int encTable[4] = {1,0,1,0}; //置换表
int data[16] = {1,0,0,1,0,0,0,1,1,1,1,1,0,0,0,0}; //明文
int ciphertext[16]; //密文
//切片加密函数
void encode(int arr[])
{
for(int i=0;i<encLen;i++)
{
arr[i] = arr[i] ^ encTable[i];
}
}
//OFB
//输出反馈模式,4位分段
void OFB(int arr[])
{
//数据明文切片,切成2 * 8 片
int a[8][2];
int dataCount = 0; //位置变量
for(int k=0;k<8;k++)
{
for(int t=0;t<2;t++)
{
a[k][t] = data[dataCount];
dataCount++;
}
}
dataCount = 0; //恢复初始化设置
int lv[4] = {1,0,1,1}; //初始设置的位移变量
int encQue[2]; //K的高两位
int k[4]; //K
for(int i=0;i<2 * encLen;i++) //外层加密循环
{
//产生K
for(int vk=0;vk<encLen;vk++)
{
k[vk] = lv[vk];
}
encode(k);
for(int k2=0;k2<2;k2++)
{
encQue[k2] = k[k2];
}
//K与数据明文异或产生密文
for(int j=0;j<2;j++)
{
ciphertext[dataCount] = a[dataCount/2][j] ^ encQue[j];
dataCount++;
}
//lv左移变换
lv[0] = lv[2];
lv[1] = lv[3];
lv[2] = encQue[0];
lv[3] = encQue[1];
}
cout<<"CFB加密的密文为:"<<endl;
for(int t1=0;t1<dataLen;t1++) //输出密文
{
if(t1!=0 && t1%4==0)
cout<<endl;
cout<<ciphertext[t1]<<" ";
}
cout<<endl;
cout<<"---------------------------------------------"<<endl;
}