用c++实现AES基本算法
#include<string>
#include<iostream>
#include<bitset>
using namespace std;
typedef bitset<8> byte;
typedef bitset<32> word;
typedef bitset<128> fword;
//测试密钥:00012001710198aeda79171460153594
//测试明文:0001000101a198afda78173486153566
//结果密文:6cdd596b8f5642cbd23b47981a65422a
byte S_Box[16][16] = {
{0x63, 0x7C, 0x77, 0x7B, 0xF2, 0x6B, 0x6F, 0xC5, 0x30, 0x01, 0x67, 0x2B, 0xFE, 0xD7, 0xAB, 0x76},
{0xCA, 0x82, 0xC9, 0x7D, 0xFA, 0x59, 0x47, 0xF0, 0xAD, 0xD4, 0xA2, 0xAF, 0x9C, 0xA4, 0x72, 0xC0},
{0xB7, 0xFD, 0x93, 0x26, 0x36, 0x3F, 0xF7, 0xCC, 0x34, 0xA5, 0xE5, 0xF1, 0x71, 0xD8, 0x31, 0x15},
{0x04, 0xC7, 0x23, 0xC3, 0x18, 0x96, 0x05, 0x9A, 0x07, 0x12, 0x80, 0xE2, 0xEB, 0x27, 0xB2, 0x75},
{0x09, 0x83, 0x2C, 0x1A, 0x1B, 0x6E, 0x5A, 0xA0, 0x52, 0x3B, 0xD6, 0xB3, 0x29, 0xE3, 0x2F, 0x84},
{0x53, 0xD1, 0x00, 0xED, 0x20, 0xFC, 0xB1, 0x5B, 0x6A, 0xCB, 0xBE, 0x39, 0x4A, 0x4C, 0x58, 0xCF},
{0xD0, 0xEF, 0xAA, 0xFB, 0x43, 0x4D, 0x33, 0x85, 0x45, 0xF9, 0x02, 0x7F, 0x50, 0x3C, 0x9F, 0xA8},
{0x51, 0xA3, 0x40, 0x8F, 0x92, 0x9D, 0x38, 0xF5, 0xBC, 0xB6, 0xDA, 0x21, 0x10, 0xFF, 0xF3, 0xD2},
{0xCD, 0x0C, 0x13, 0xEC, 0x5F, 0x97, 0x44, 0x17, 0xC4, 0xA7, 0x7E, 0x3D, 0x64, 0x5D, 0x19, 0x73},
{0x60, 0x81, 0x4F, 0xDC, 0x22, 0x2A, 0x90, 0x88, 0x46, 0xEE, 0xB8, 0x14, 0xDE, 0x5E, 0x0B, 0xDB},
{0xE0, 0x32, 0x3A, 0x0A, 0x49, 0x06, 0x24, 0x5C, 0xC2, 0xD3, 0xAC, 0x62, 0x91, 0x95, 0xE4, 0x79},
{0xE7, 0xC8, 0x37, 0x6D, 0x8D, 0xD5, 0x4E, 0xA9, 0x6C, 0x56, 0xF4, 0xEA, 0x65, 0x7A, 0xAE, 0x08},
{0xBA, 0x78, 0x25, 0x2E, 0x1C, 0xA6, 0xB4, 0xC6, 0xE8, 0xDD, 0x74, 0x1F, 0x4B, 0xBD, 0x8B, 0x8A},
{0x70, 0x3E, 0xB5, 0x66, 0x48, 0x03, 0xF6, 0x0E, 0x61, 0x35, 0x57, 0xB9, 0x86, 0xC1, 0x1D, 0x9E},
{0xE1, 0xF8, 0x98, 0x11, 0x69, 0xD9, 0x8E, 0x94, 0x9B, 0x1E, 0x87, 0xE9, 0xCE, 0x55, 0x28, 0xDF},
{0x8C, 0xA1, 0x89, 0x0D, 0xBF, 0xE6, 0x42, 0x68, 0x41, 0x99, 0x2D, 0x0F, 0xB0, 0x54, 0xBB, 0x16}
};
void ox_to_b(string &ppx,string &ppz) //16进制字符串转换2进制函数
{
string ppl[32];
for(int cv = 0;cv<32;cv++)
{
switch(ppx[cv]){
case '0': ppl[cv] = "0000";break;
case '1': ppl[cv] = "0001";break;
case '2': ppl[cv] = "0010";break;
case '3': ppl[cv] = "0011";break;
case '4': ppl[cv] = "0100";break;
case '5': ppl[cv] = "0101";break;
case '6': ppl[cv] = "0110";break;
case '7': ppl[cv] = "0111";break;
case '8': ppl[cv] = "1000";break;
case '9': ppl[cv] = "1001";break;
case 'A': ppl[cv] = "1010";break;
case 'a': ppl[cv] = "1010";break;
case 'B': ppl[cv] = "1011";break;
case 'b': ppl[cv] = "1011";break;
case 'C': ppl[cv] = "1100";break;
case 'c': ppl[cv] = "1100";break;
case 'D': ppl[cv] = "1101";break;
case 'd': ppl[cv] = "1101";break;
case 'E': ppl[cv] = "1110";break;
case 'e': ppl[cv] = "1110";break;
case 'F': ppl[cv] = "1111";break;
default: ppl[cv] = "1111";break;//待解决:ppz+-ppl[cv]不行,或许可以调用某个string函数
}
}
ppz = ppl[0] +ppl[1]+ppl[2]+ppl[3]+ppl[4]+ppl[5]+ppl[6]+ppl[7]+ppl[8]+ppl[9]+ppl[10]+ppl[11]+ppl[12]+ppl[13]+ppl[14]+ppl[15]+ppl[16]+ppl[17]+ppl[18]+ppl[19]+ppl[20]+ppl[21]+ppl[22]+ppl[23]+ppl[24]+ppl[25]+ppl[26]+ppl[27]+ppl[28]+ppl[29]+ppl[30]+ppl[31];
}
void PutOutState(word so[4])//输出状态
{
for(int jl = 0;jl<4;jl++)
cout<<so[jl].to_ulong();
cout<<endl;
}
void circle(fword &s,word &v)
{
for(int t = 0;t<32;t++)
v[t] = s[t];
}
void fword_to_word(fword &x,word y[4])//四字转化为单字
{
fword temp;
for(int o = 0;o<4;o++)
{
temp=x>>o*32;
circle(temp,y[3-o]); //注意是反着放的
}
}
word Rotl(word &v,int gh)//左移函数
{
word stemp;
word ktemp;
stemp = v>>24-gh*8;
ktemp = v<<8+gh*8;
return stemp|ktemp;
}
word Rcon[10] = {0x01000000, 0x02000000, 0x04000000, 0x08000000, 0x10000000,
0x20000000, 0x40000000, 0x80000000, 0x1b000000, 0x36000000}; //轮常数
word byte_to_word(byte r[],int j)//状态列字节转换为字的函数
{
word n(r[0+4*j].to_string()+r[1+4*j].to_string()+r[2+4*j].to_string()+r[3+4*j].to_string());
//cout<<hex<<n.to_ulong()<<endl;
return n;
}
word Byte_to_word(byte r[],int gg)//状态行字节转化为字的函数
{
word n(r[0+gg].to_string()+r[4+gg].to_string()+r[8+gg].to_string()+r[12+gg].to_string());
//cout<<hex<<n.to_ulong()<<endl;
return n;
}
word SubByte(word &vv)//S盒变换
{
byte p[4];
// cout<<hex<<vv.to_ulong()<<endl;
// cout<<vv<<endl;
for(int u = 0;u<4;u++)
{
int col = vv[u*8]+vv[u*8+1]*2+vv[u*8+2]*4+vv[u*8+3]*8; //注意二进制站位和string不同
int row = vv[u*8+4]+vv[u*8+5]*2+vv[u*8+6]*4+vv[u*8+7]*8;
// cout<<row<<" "<<col<<endl;
p[3-u] = S_Box[row][col];
//cout<<hex<<p[u].to_ulong()<<endl;
}
return byte_to_word(p,0);
}
void ByteSub(word State[4]) //状态S盒变换
{
for(int g = 0;g<4;g++)
State[g] = SubByte(State[g]);
}
void KeyExpansion(word q[] ,word e[]) //密钥扩展函数
{
word Temp;
for(int i=0;i<4;i++)
e[i] = q[i];
for(int d = 4;d<4*(1+10);d++)
{
Temp = e[d-1];
if(d%4==0)
Temp=SubByte(Rotl(Temp,0))^Rcon[(d/4)-1];
e[d] = e[d-4]^Temp;
//cout<<hex<<e[d].to_ulong()<<endl;
}
}
fword Word_to_Fword(word g[],int yy)//单字转化为四字函数
{
fword jj(g[yy*4].to_string()+g[yy*4+1].to_string()+g[yy*4+2].to_string()+g[yy*4+3].to_string());
return jj;
}
void Word_to_Byte(word &dc,byte nc[],int sl) //列移位字转字节
{
word dtemp;
for(int nv = 0;nv<4;nv++)
{
dtemp = dc>>nv*8;
for(int lk = 0;lk<8;lk++)
nc[3-nv+4*sl][lk] = dtemp[lk];
}
}
void word_to_Byte(word &dc,byte nc[],int sl) //行移位字转字节
{
word dtemp;
for(int nv = 0;nv<4;nv++)
{
dtemp = dc>>nv*8;
for(int lk = 0;lk<8;lk++)
nc[12-nv*4+sl][lk] = dtemp[lk]; //重点笔记:考虑到用string初始化的bitset对象中的二进制位和原string中的下标相反,即反序,故对下标操作需要反存放。
}
}
void ShiftRows(byte sr[16])
{
for(int sk = 0;sk<4;sk++)
word_to_Byte(Rotl(Byte_to_word(sr,sk),sk-1),sr,sk); //重点笔记:先转化为字,再左移,在返回字节
}
void AddRoundKey(word roundkey[],word roundstate[],int jk) //轮密钥异或函数
{
for(int ee = 0;ee<4;ee++)
roundstate[ee]^=roundkey[jk*4+ee];
}
byte qtime(byte& x) { //乘2,字节解析,类似于乘法分配律,另外根据GF(2^8)规则,若超过2^8,需要异或0x1b.
byte answer = x&0x80;
//cout<<hex<<answer.to_ulong()<<endl;
if(answer==0x80)
answer = (x<<1)^0x1b; //经验:不要把二进制倒过来看,除非对下标进行访问
else
answer = x<<1;
//cout<<hex<<answer.to_ulong()<<endl;
return answer; //不能直接返回数值
}
byte GF(byte& a, byte& b) //GF(2^8)中的乘法函数
{
byte vtemp[8];
vtemp[0] = a;
for (int j = 1; j < 8; j++) {
vtemp[j] = qtime(vtemp[j - 1]); //这个数组里存放着所有a的移位值
}
//for(int i = 0;i<8;i++)
//cout<<vtemp[i]<<endl;
//cout<<endl;
byte mtemp(0x00);
for (int i = 0; i < 8; i++)
{
if(((b>>i)&0x01)==1) //b的最后一位决定数组中的元素是否参与最后的异或
mtemp ^= vtemp[i];
}
return mtemp;
}
void MixColumn(byte ko[16]) //列混合变换
{
byte temp[16];
for(int i = 0;i<16;i++)
temp[i] = ko[i];
// for(int j = 0;j<16;j++)
// cout<<hex<<temp[j].to_ulong();
// cout<<endl;
byte jz2(0x02);
byte jz3(0x03);
for(int re = 0;re<4;re++) //矩阵乘法,参见密码学引论第93面
{
ko[re*4+0] = GF(jz2,temp[re*4+0])^GF(jz3,temp[re*4+1])^temp[re*4+2]^temp[re*4+3];
ko[re*4+1] = temp[re*4+0]^GF(jz2,temp[re*4+1])^GF(jz3,temp[re*4+2])^temp[re*4+3];
ko[re*4+2] = temp[re*4+0]^temp[re*4+1]^GF(jz2,temp[re*4+2])^GF(jz3,temp[re*4+3]);
ko[re*4+3] = GF(jz3,temp[re*4+0])^temp[re*4+1]^temp[re*4+2]^GF(jz2,temp[re*4+3]);
}
}
void StateTransform(word state[4],byte bstate[16]) //状态字节转化为字
{
for(int i = 0;i<4;i++)
state[i] = byte_to_word(bstate,i);
}
void ByteTransform(word state[4],byte bstate[16]) //状态字转化为字节
{
for(int ip = 0;ip<4;ip++)
Word_to_Byte(state[ip],bstate,ip);
}
void main()
{
cout<<"---------------------------------AES-128-----------------------------------"<<endl;
string ikey(32,'1'); //加密密钥扩展
string kkey(128,'1');
cout<<"请输入16进制密钥:"<<endl;
cin>>ikey; //输入密钥
ox_to_b(ikey,kkey);
fword skey(kkey); //初始化密钥
word ss[4];
fword_to_word(skey,ss); //四字密钥转化为字密钥
word gkey[4*11];
KeyExpansion(ss,gkey); //密钥拓展
for(int f = 0;f<4*11;f++) //输出全部密钥
{
if(f%4==0)
{
cout<<endl;
cout<<"key["<<dec<<f/4<<"] = ";
}
cout<<hex<<gkey[f].to_ulong();
}
cout<<endl; //2017-5-9 23:08
//cout<<"w["<<f<<"] = "<<gkey[f].to_ulong()<<endl;
//cout<<Word_to_Fword(gkey,f)<<endl;
string ming(32,'1');
string mingg(128,'1');
cout<<"请输入16进制明文:"<<endl;
cin>>ming; //输入明文
ox_to_b(ming,mingg);
fword sming(mingg); //初始化明文四字
word state[4];
fword_to_word(sming,state); //明文四字转化为字,缺个2进制转16进制string函数
AddRoundKey(gkey,state,0); //轮密钥加
cout<<"AddRoundKey: ";
PutOutState(state);
/*for(int io = 0;io<4;io++)
cout<<hex<<state[io].to_ulong();
cout<<endl;*/
/*for(int ui = 0;ui<32;ui++)
cout<<state[0][ui];
cout<<endl;*/
byte bstate[4*4];
for(int t = 1;t<10;t++) //第一轮到第九轮变换
{
ByteSub(state); //S盒变换
cout<<"SubByte: ";
PutOutState(state);
ByteTransform(state,bstate);
ShiftRows(bstate); //行移位变换
StateTransform(state,bstate);
cout<<"ShiftRows: ";
PutOutState(state);
MixColumn(bstate); //列混合变变换
StateTransform(state,bstate);
cout<<"MixColumns:";
PutOutState(state);
AddRoundKey(gkey,state,t); //轮密钥加
cout<<"AddRoundKey: ";
PutOutState(state);
ByteTransform(state,bstate);
cout<<endl;
cout<<endl;
/*for(int kl =0;kl<16;kl++)
cout<<hex<<bstate[kl].to_ulong();
cout<<endl;*/
}
ByteSub(state); //最后一轮变换,相比第九轮少一个列混合变换
cout<<"SubByte: ";
PutOutState(state);
ByteTransform(state,bstate);
ShiftRows(bstate);
StateTransform(state,bstate);
cout<<"ShiftRows: ";
PutOutState(state);
AddRoundKey(gkey,state,t);
cout<<"AddRoundKey:";
PutOutState(state);
ByteTransform(state,bstate);
}
程序截图
//2017-5-12 0:14 终于差不多把AES加密搞完了,缺点还有16进制显示有时会省略0(或许用字符串输出会更好),明天加笔记。。。。。
//2017-5-12 8:30 笔记差不多完成了,总结一下,AES比DES复杂,对数学要求更高,并且这次采用的方法和之前DES的不同,之前的是大部分调用bitset类的to_string()方法,并在字符串上进行操作的
//这次AES大部分操作是直接在bitset对象上操作的,通过反复实验,发现用string初始化的bitset对象是反序存放,而对cout,to_ulong,to_string,<<,>>,&,^等操作符不受反序影响,推测应该是重载函数内部已经处理了。
//解密的等写完RSA再来写(累~~~)
//最后推荐两篇博文写的很好,收益颇多
//AES算法及实现:http://blog.csdn.net/lisonglisonglisong/article/details/41909813
//GF(2^8)乘法及实现:http://blog.csdn.net/bupt073114/article/details/27382533
//参考资料:密码学引论(张焕国 唐明编著,第三版,武汉大学出版社)
用c++实现AES基本算法相关推荐
- RC4算法原理、Java实现RC4加密算法、DES AES RC4算法比较
DES AES RC4算法比较 根据密钥类型的不同,加密算法分为对称和非对称两种.对称加密系统是指加密和解密均采用同一把密钥. 对称加密算法是最常用的加密算法,优势在于算法公开,计算量小,加密效率高. ...
- aes解密算法 java_AES算法实现Java和JS互通加解密
实际开发中客户端与服务端的通信内容往往需要通过密文传输,本文将介绍可以实现Java与js的互相加解密的AES加密方式 Java语言实现 public class AESTest { //static ...
- C++使用AES+Base64算法对文本进行加密
使用AES算法和Base64实现具体的文本加密. 采用AES算法的CBC模式,16位秘钥,PKCS7Padding填充方案对文本进行加解密.此方案可防止一些比较关键的文本暴露,也可以用于服务器通信间的 ...
- java aes解密算法_使用java实现AES算法的加解密(亲测可用)
话不多说,直接上代码 import javax.crypto.Cipher; import javax.crypto.spec.IvParameterSpec; import javax.crypto ...
- AES GCM算法实现
当前业界敏感信息加密使用AES较多,GCM模式兼具效率和安全性,故选择使用该模式. 注意 我们经常使用256位秘钥,因为美国的安全管控,jdk8的较老版本安全策略不支持256位秘钥,需替换jdk\jr ...
- AES GCM 算法
AES-GCM算法是带认证和加密的算法,也即同时可以对给定的原文,生成加密数据和认证码. 加密方: plain_test key_128/key_256 iv/salt aad, 生成校验码的盐值 密 ...
- Delphi与JAVA互加解密AES算法
搞了半天终于把这个对应的参数搞上了,话不多说,先干上代码: package com.bss.util;import java.io.UnsupportedEncodingException; impo ...
- 对于AES和RSA算法的结合使用以及MD5加盐注册登录时的密码加密
RSA和AES结合使用 接上篇的RSA和AES算法加密之后,AES对称算法对数据量大的加密比较快,而RSA公私钥加密的话会影响加密效率,但是AES的加密与解密的密钥是一致的,导致密钥不能外泄,密钥在网 ...
- 加密芯片——AES算法特点与应用注意事项
AES是一种区块加密标准算法,它的提出是为了升级替换原有的DES加密算法.因此它的安全强度高于DES算法.但不应片面理解,系统和数据的安全不仅与应用的加密算法有关,更与加密应用方案有关.和DES算法一 ...
最新文章
- 解决 wcf HTTP 无法注册 另一应用程序正在使用 TCP 端口 80
- web前端数组处理之扁平化数组
- 顶层 pom 中的 dependencies 与 dependencyManagement 区别
- python 抠图 锯齿_Python | 绘图中的抗锯齿
- java 解析http返回的xml_Java解析调用webservice服务的返回XML串详解
- 编译安装 zbar 时两次 make 带来的惊喜
- HDU3930(离散对数与原根)
- java中sql语句怎么把开始和结束时间作为参数写sql查询_聊一聊MyBatis 和 SQL 注入间的恩恩怨怨
- 长短期记忆网络_思维导图:长短期记忆模型
- 机房服务器维护管理规范,机房维护管理规范.pdf
- 高中计算机课程网页修改,高中信息技术教学贯彻新课改理念
- 微信小程序实现组件之间的传值
- 何恺明的ResNet引用量突破10万!
- 前端js实现从视频中提取图片帧
- 关于Python虚拟环境与包管理你应该知道的事
- Linux下基于GTK人脸识别界面设计
- 《华仪酒店管理系统》项目研发性总结
- 可以听歌玩游戏看股票背单词的ROS开发工具?小鱼:就差能点外卖了~
- 六大维度让你彻底明白机器视觉与计算机视觉的区别!
- “云+AI”沉锚,百度智能云锁定百度AI产业智能化航道
热门文章
- 远景在线(www.pcbeta.com):使用IE10登陆中国银行网银蓝屏或者死机的解决方案
- jenkins构建项目报错:java:[17,37] package xx.xx.xxx does not exist
- 官宣!1024 程序员节日程发布,第一代程序员求伯君将出席大会
- 微信小程序--在app.js 和其他页面中更改globalData的值
- 现代信息技术(IT)对会计模式的影响(by 杨烈飙)
- HTML+CSS大作业: 抗击疫情网页制作作业_疫情防控网页设计模板HTML_ 简单学生网页设_静态HTML+CSS网站制作成品...
- python 调用函数实现——斐波纳契数列
- 互联网+时代的企业应用集成平台
- Bad owner or permissions on C:\\Users\\XX/.ssh/config
- Windows Oracle ODBC驱动数据源安装配置