SMS4分析实验报告附C++实现代码.docx
《SMS4分析实验报告附C++实现代码.docx》由会员分享,可在线阅读,更多相关《SMS4分析实验报告附C++实现代码.docx(22页珍藏版)》请在冰豆网上搜索。
SMS4分析实验报告附C++实现代码
中国商用加密标准SMS4分析实验报告
一、概况
二、SMS4与DES、AES比较
三、意义
四、实现
1.密钥扩展
2.S盒替换
3.L变换
4.轮函数F
5.加密算法
6.解密算法
五、分析
1.输入改变一位,输出改变位数
2.S变换和L变换输入改变一位,输出改变位数
3.S盒连续变换使输入等于输出的轮数
附1:
实现代码
附2:
运行截图
一、概况
商用密码是指对不涉及国家秘密内容的信息进行加密保护或者安全认证所使用的密码技术和密码产品。
商用密码的应用领域十分广泛,主要用于对不涉及国家秘密内容但又具有敏感性的内部信息、行政事务信息、经济信息等进行加密保护。
1972年美国公布了第一个商用密码DES。
而2006年2月公布的用于无线局域网加密的SMS4是我国公布的第一个商用密码。
SMS4是一个分组对称密码算法。
分组长度与密钥长度均为128位。
数据处理单位主要为字节(8位)和字(32位)。
包括非线性变换S和线性变换L,经过32轮迭代结果为128位密文。
其中S盒可替换,是一种灵活的、相对稳定的密码算法。
二、SMS4与DES、AES比较
SMS4、DES与AES均为已公开的分组对称商用密码,均使用异或,置换,代换,移位操作四种基本运算。
均包括线性和非线性变换。
DES:
分组长度为64位,密钥长度为64位(放弃其中八位用作奇偶校验),16轮变换,输出64位密文。
有8个4x16位S盒。
从实际出发仍认为其安全性足够,但现在一般更多的使用AES。
AES:
分组长度为128~256位,密钥长度为128、192或256位,10~14轮变换,输出与明文对应长度的密文。
有16x16位的S盒和基于16x16位的E、F表的混合列操作。
SMS4:
分组长度为128位,密钥长度为128位,32轮变换,输出128位密文。
有16x16位S盒。
三、意义
随着信息时代的到来,信息显得越来越重要,甚至成为一种战略物资。
所以信息的安全也越来越重要。
而密码算法则是信息安全的核心。
SMS4的公布改变了长期以来不公布密码算法只提供密码芯片的局面。
打破了外国对商业密码的垄断,使得用户不再需要面对要达到加密要求就必须向外国管理者缴纳使用费的情况。
也在最大程度上避免了因使用外国密码算法而被掌握陷门的风险。
同时,SMS4也标志着我国密码体制与国际接轨,有利于我国密码管理的科学化,促进我国商用密码算法的发展。
四、实现
1.密钥扩展
使用到4个常数FK0~3和32个固定参数CK0~31,定义K0~3为FK与密钥的异或值。
子密钥IKi等于Ki+4等于Ki+1~3与CKi的T'变换与Ki的异或值。
2.S盒替换
使用16x16位的S盒,以输入高位为行号、低位为列号取对应表中数值作为输出。
3.L变换
以输入与其循环左移2,10,18,24次的值的异或值作为输出。
(密钥扩展里用到的L'变换的左移次数为13,23次)
4.轮函数F
四个S盒并行替换后做L变换称作T变换。
F函数的输出为输入数据X1~3与子密钥IK的异或值的T变换得到的值再与输入数据X0的异或值。
5.加密算法
明文作为第一轮F的输入,之后的输入为前一轮输入的后三项与前一轮F变换的结果,子密钥为IK0~31。
32轮变换后,最后四轮的输出分别作为密文的第4到第1项。
6.解密算法
解密算法与加密相同,但子密钥的使用顺序为IK31~0。
五、分析
1.输入改变一位,输出改变位数
每次测试先随机产生原始输入,之后每次随机改变一位,与前一次输出比较改变位数。
每次测试做1000次改变,取平均数。
见图(四)。
多次统计取平均结果为:
63.63位
2.S变换和L变换输入改变一位,输出改变位数
每次测试先随机产生原始输入,之后每次随机改变一位,与前一次输出比较改变位数。
每次测试做1000次改变,取平均数。
见图(三)。
多次统计取平均结果为:
S:
3.98位
L:
5位
3.S盒连续变换使输入等于输出的轮数
S盒公有256种输入,对每个输入做连续S变换,直到输出与输入相同。
对于每个S盒结果为定值。
部分见图(四)。
对于附1中的代码实现时所用S盒的计算结果为:
(XX:
YXX=输入Y=S盒替换次数)
00:
12001:
2402:
12003:
2404:
5605:
12006:
12007:
56
08:
5609:
1200A:
560B:
560C:
1200D:
350E:
560F:
120
10:
2411:
12012:
12013:
12014:
5615:
12016:
5617:
56
18:
12019:
1201A:
1201B:
351C:
1201D:
1201E:
1201F:
56
20:
2421:
12022:
12023:
12024:
925:
12026:
3527:
120
28:
12029:
1202A:
562B:
242C:
562D:
32E:
352F:
56
30:
12031:
12032:
12033:
12034:
3535:
5636:
637:
35
38:
12039:
243A:
1203B:
563C:
353D:
1203E:
353F:
35
40:
12041:
5642:
12043:
2444:
12045:
12046:
5647:
120
48:
12049:
1204A:
354B:
1204C:
564D:
1204E:
94F:
9
50:
12051:
5652:
5653:
3554:
12055:
12056:
5657:
120
58:
659:
1205A:
1205B:
1205C:
355D:
565E:
1205F:
56
60:
12061:
962:
5663:
12064:
12065:
666:
3567:
120
68:
12069:
1206A:
1206B:
566C:
246D:
1206E:
566F:
56
70:
3571:
12072:
5673:
12074:
3575:
3576:
12077:
56
78:
5679:
67A:
1207B:
1207C:
1207D:
567E:
1207F:
120
80:
12081:
5682:
5683:
12084:
12085:
12086:
12087:
56
88:
3589:
248A:
568B:
1208C:
1208D:
98E:
1208F:
120
90:
2491:
992:
5693:
5694:
12095:
3596:
12097:
120
98:
3599:
569A:
1209B:
1209C:
249D:
1209E:
1209F:
35
A0:
120A1:
120A2:
120A3:
35A4:
56A5:
35A6:
35A7:
120
A8:
9A9:
120AA:
120AB:
1AC:
35AD:
35AE:
9AF:
56
B0:
24B1:
120B2:
35B3:
120B4:
2B5:
56B6:
120B7:
56
B8:
24B9:
120BA:
120BB:
56BC:
120BD:
24BE:
120BF:
56
C0:
9C1:
35C2:
56C3:
56C4:
56C5:
120C6:
120C7:
120
C8:
120C9:
35CA:
35CB:
56CC:
56CD:
24CE:
120CF:
3
D0:
56D1:
35D2:
120D3:
35D4:
35D5:
24D6:
120D7:
24
D8:
3D9:
35DA:
56DB:
120DC:
24DD:
120DE:
2DF:
24
E0:
24E1:
120E2:
120E3:
35E4:
120E5:
120E6:
56E7:
120
E8:
6E9:
120EA:
120EB:
120EC:
120ED:
56EE:
120EF:
120
F0:
120F1:
120F2:
56F3:
120F4:
120F5:
24F6:
120F7:
24
F8:
6F9:
120FA:
56FB:
35FC:
24FD:
56FE:
24FF:
120
表
(一)S变换循环测试
附1:
//10385001丁雅博SMS4密码算法VC++6.0编译
#include
#include
#include
#include
#include
#include
usingnamespacestd;
intS_box[16][16]={{0xd6,0x90,0xe9,0xfe,0xcc,0xe1,0x3d,0xb7,0x16,0xb6,0x14,0xc2,0x28,0xfb,0x2c,0x05},
{0x2b,0x67,0x9a,0x76,0x2a,0xbe,0x04,0xc3,0xaa,0x44,0x13,0x26,0x49,0x86,0x06,0x99},
{0x9c,0x42,0x50,0xf4,0x91,0xef,0x98,0x7a,0x33,0x54,0x0b,0x43,0xed,0xcf,0xac,0x62},
{0xe4,0xb3,0x1c,0xa9,0xc9,0x08,0xe8,0x95,0x80,0xdf,0x94,0xfa,0x75,0x8f,0x3f,0xa6},
{0x47,0x07,0xa7,0xfc,0xf3,0x73,0x17,0xba,0x83,0x59,0x3c,0x19,0xe6,0x85,0x4f,0xa8},
{0x68,0x6b,0x81,0xb2,0x71,0x64,0xda,0x8b,0xf8,0xeb,0x0f,0x4b,0x70,0x56,0x9d,0x35},
{0x1e,0x24,0x0e,0x5e,0x63,0x58,0xd1,0xa2,0x25,0x22,0x7c,0x3b,0x01,0x21,0x78,0x87},
{0xd4,0x00,0x46,0x57,0x9f,0xd3,0x27,0x52,0x4c,0x36,0x02,0xe7,0xa0,0xc4,0xc8,0x9e},
{0xea,0xbf,0x8a,0xd2,0x40,0xc7,0x38,0xb5,0xa3,0xf7,0xf2,0xce,0xf9,0x61,0x15,0xa1},
{0xe0,0xae,0x5d,0xa4,0x9b,0x34,0x1a,0x55,0xad,0x93,0x32,0x30,0xf5,0x8c,0xb1,0xe3},
{0x1d,0xf6,0xe2,0x2e,0x82,0x66,0xca,0x60,0xc0,0x29,0x23,0xab,0x0d,0x53,0x4e,0x6f},
{0xd5,0xdb,0x37,0x45,0xde,0xfd,0x8e,0x2f,0x03,0xff,0x6a,0x72,0x6d,0x6c,0x5b,0x51},
{0x8d,0x1b,0xaf,0x92,0xbb,0xdd,0xbc,0x7f,0x11,0xd9,0x5c,0x41,0x1f,0x10,0x5a,0xd8},
{0x0a,0xc1,0x31,0x88,0xa5,0xcd,0x7b,0xbd,0x2d,0x74,0xd0,0x12,0xb8,0xe5,0xb4,0xb0},
{0x89,0x69,0x97,0x4a,0x0c,0x96,0x77,0x7e,0x65,0xb9,0xf1,0x09,0xc5,0x6e,0xc6,0x84},
{0x18,0xf0,0x7d,0xec,0x3a,0xdc,0x4d,0x20,0x79,0xee,0x5f,0x3e,0xd7,0xcb,0x39,0x48}};
unsignedintck[32]={0x00070e15,0x1c232a31,0x383f464d,0x545b6269,0x70777e85,0x8c939aa1,0xa8afb6bd,0xc4cbd2d9,0xe0e7eef5,0xfc030a11,0x181f262d,0x343b4249,0x50575e65,0x6c737a81,0x888f969d,0xa4abb2b9,0xc0c7ced5,0xdce3eaf1,0xf8ff060d,0x141b2229,0x30373e45,0x4c535a61,0x686f767d,0x848b9299,0xa0a7aeb5,0xbcc3cad1,0xd8dfe6ed,0xf4fb0209,0x10171e25,0x2c333a41,0x484f565d,0x646b7279};
unsignedintfk[4]={0xa3b1bac6,0x56aa335,0x677d9197,0xb27022dc};
voidpri(chara[],intn)//数组输出
{
for(inti=0;i{
cout<}
cout<}
voidpri_(chara[],intn)//16进制输出
{
intm=n/4;
for(inti=0;i{
intk=i*4;
inttemp=(a[k]-'0')*8+(a[k+1]-'0')*4+(a[k+2]-'0')*2+(a[k+3]-'0');
if(temp<10)
{
cout<}
else
{
chartemp_=temp-10+'A';
cout<}
}
cout<}
voidpri__(chara[],intn)//二进制转字符输出
{
intm=n/8;
for(inti=0;i{
inttemp=0,k=i*8;
for(intj=0;j<8;j++)
{
temp=temp*2;
temp=temp+a[k+j]-'0';
}
cout<}
cout<}
voidgetbi(chara[],charre[],intn)//获得二进制码
{
for(inti=0;i{
intsb=a[i];
for(intj=0;j<8;j++)
{
re[i*8+7-j]=sb%2+'0';
sb=sb/2;
}
}
}
voidgiv(chara[32],charre[32])//赋值
{
for(inti=0;i<32;i++)
re[i]=a[i];
}
voidxor(chara[32],charb[32],charre[32])//异或
{
for(inti=0;i<32;i++)
{
if(a[i]==b[i])
re[i]='0';
else
re[i]='1';
}
}
voidzy(chara[32],intn)//循环左移
{
while(n--)
{
chartemp=a[0];
for(inti=0;i<31;i++)
a[i]=a[i+1];
a[31]=temp;
}
}
voidd_to_b(unsignedinta,charre[32])//十进制转二进制
{
for(inti=1;i<=32;i++)
{
re[32-i]=a%2+'0';
a=a/2;
}
}
voidh_to_b(chara[32],charre[4][32])//十六进制转二进制
{
inti,j;
charb[128];
for(i=0;i<32;i++)
{
intd;
if(a[i]>='A')
d=a[i]-'A'+10;
else
d=a[i]-'0';
for(j=0;j<4;j++)
{
b[i*4+3-j]=d%2+'0';
d=d/2;
}
}
for(i=0;i<4;i++)
{
for(j=0;j<32;j++)
re[i][j]=b[i*32+j];
}
}
voidS_change(chara[32],charre[32])//4个S盒并行置换
{
for(inti=0;i<4;i++)
{
intxtemp=0;
intytemp=0;
for(intj=0;j<4;j++)
{
xtemp=xtemp*2+a[8*i+j]-'0';
ytemp=ytemp*2+a[8*i+j+4]-'0';
}
inttemp=S_box[xtemp][ytemp];
for(intk=0;k<8;k++)
{
re[i*8+7-k]=temp%2+'0';
temp=temp/2;
}
}
}
voidL_change(chara[32],charre[32])//L置换
{
chartemp[32];
giv(a,temp);
zy(temp,2);
xor(a,temp,re);
zy(temp,8);
xor(re,temp,re);
zy(temp,8);
xor(re,temp,re);
zy(temp,6);
xor(re,temp,re);
}
voidkey_LC(chara[32],charre[32])//L*置换
{
chartemp[32];
giv(a,temp);
zy(temp,13);
xor(a,temp,re);
zy(temp,10);
xor(re,temp,re);
}
voidF_change(chara[32],charb[32],charc[32],chard[32],charrk[32],charre[32])//F变换
{
xor(b,c,re);
xor(re,d,re);
xor(re,rk,re);
S_change(re,re);
L_change(re,re);
xor(a,re,re);
}
voidkey_ex(chara[4][32],charre[32][32])//密钥扩展
{
inti;
charK[36][32];
charFK[4][32];
for(i=0;i<4;i++)
{
d_to_b(fk[i],FK[i]);
xor(a[i],FK[i],K[i]);
}
charCK[32][32];
for(i=0;i<32;i++)
d_to_b(ck[i],CK[i]);
for(i=0;i<32;i++)
{
chartemp[32];
xor(K[i+1],K[i+2],temp);
xor(temp,K[i+3],temp);
xor(temp,CK[i],temp);
S_change(temp,temp);
key_LC(temp,temp);
xor(K[i],temp,re[i]);
giv(re[i],K[i+4]);
}
}
voidpu_to_pr(chara[4][32],charb[32][32],charre[4][32])//加密
{
inti=0;
charX[36][32];
for(i=0;i<4;i++)
giv(a[i],X[i]);
for(i=0;i<32;i++)
F_change(X[i],X[i+1],X[i+2],X[i+3],b[i],X[i+4]);
for(i=0;i<4;i++)
giv(X[35-i],re[i]);
}
voidpr_to_pu(chara[4][32],charb[32][32],charre[4][32])//解密
{
inti=0;
charX[36][32];
for(i=0;i<4;i++)
giv(a[i],X[i]);
for(i=0;i<32;i++)
F_change(X[i],X[i+1],X[i+2],X[i+3],b[31-i],X[i+4]);
for(i=0;i<4;i++)
giv(X[35-i],re[i]);
}
doublecomp(chara[],charb[],intn)//比较俩数组不同的位数
{
doublere=0;
for(inti=0;i{
if(a[i]!
=b[i])
re++;
}
returnre;
}
doublecomp_Z(chara[4][32],charb[32][32])//输入改变一位,输出平均改变位数
{
doublere=0;
charpr[4][32],pr_[4][32];
pu_to_pr(a,b,pr);
srand(time(0));
for(inti=0;i<1000;i++)
{
intp=rand()%128;
if(a[p/32][128%32]=='0')
a[p/32][128%32]='1';
else
a[p/32]