第一篇:通信网络与信息安全论坛邀请函
第五届通信网络和信息安全高层论坛
参会邀请函
尊敬的女士/先生:
在工业和信息化部通信保障局的指导下,由中国通信学会普及与教育工作委员会、人民邮电出版社主办,北京信通传媒有限责任公司承办的“2013通信网络和信息安全高层论坛”将于2013年4月11日在北京鸿翔大厦举办。
论坛将以“协作创新应对安全变革新时代”为主题,针对实名制下的网络安全、云计算公共服务网络安全、基于云的第三方灾难备份、IDC类应用系统安全防护、电信网络的安全防护评测和管理、IPv6网络安全保障体系研究、Web应用安全、移动互联网的安全和挑战等议题展开深入研讨和交流。
联系人:
电话:
邮件:
北京信通传媒有限责任公司
2013年4月6日
第二篇:网络与信息安全
《网络与信息安全》复习资料
信息安全特征:完整性、保密性、可用性、不可否认性、可控性。保密学是研究信息系统安全保密的科学。
网络信息安全体系结构框架:安全控制单元、安全服务层面、协议层次。公钥密码:由两个密码组成,每个用户拥有一对选择密钥:加密密钥与解密密钥。公钥密码特点:(1)加密密钥和解密密钥在本质上是不同的,即使知道一个密钥,也不存在可以轻易地推导出另一个密钥的有效算法。(2)不需要增加分发密钥的额外信道。公布公钥空间,不影响公钥系统的保密性,因为保密的仅是解密密钥。公钥密码系统应具备两个条件:(1)加密和解密交换必须满足在计算上是容易的。(2)密码分析必须满足在计算机上是困难的。协议:两个或两个以上的主体为完成某一特定任务共同发起的某种协约或采取的一系列步骤。协议的特征:(1)至始至终有序进行。(2)协议成立至少要有两个主体。(3)协议执行要通过实体操作来实现。数字签名与手写签名的区别:(1)签名实体对象不同。(2)认证方式不同。(3)拷贝形式不同。
签名算法的三个条件:(1)签名者事后不能否认自己的签名。(2)任何其他人都不能伪造签名,接收者能验证签名。(3)当签名双方发生争执时,可由公正的第三方通过验证辨别真伪。
不可否认数字签名:没有签名者的合作,接收者就无法验证签名,某种程度上保护了签名者的利益,从而可防止复制或散布签名文件的滥用。
不可否认数字签名方案由三部分组成:数字签名算法、验证协议、否认协议。
散列函数:一种将任意长度的消息压缩为某一固定长度的消息摘要的函数。消息认证码:满足某种安全性质带有密钥功能的单向散列函数。身份证明分两大娄:身份证实、身份识别。信息隐藏:把一个有含义的信息隐藏在另一个载体信息中得到隐密载体的一种新型加密方式。
信息隐藏的两种主要技术:信息隐秘术、数字水印术。数字水印技术:指用信号处理的方法在数字化的多媒体数据中嵌入隐藏标识的技术。
三种数字水印:(1)稳健的不可见的水印。(2)不稳健的不可见的水印。(3)可见的水印。
数字水印三个特征:(1)稳健性。(2)不可感知性。(3)安全可靠性。
数字水印三个部分:(1)水印生成。(2)水印嵌入。(3)水印提取(检测)。
密钥管理的基本原则:(1)脱离密码设备的密钥数据应绝对保密。(2)密码设备内部的密钥数据绝对不外泄。(3)密钥使命完成,应彻底销毁、更换。常用密钥种类:(1)工作密钥。(2)会话密钥。(3)密钥加密密钥。(4)主机主密钥。
公开密钥分发:(1)广播式密钥分发。(2)目录式密钥分发。(3)公开密钥机构分发。(4)公开密钥证书分发。密钥保护方法:(1)终端密钥保护。(2)主机密钥保护。(3)密钥分级保护管理。
秘密共享方案:将一个密钥K分成n个共享密钥K1、K2……Kn,并秘密分配给n个对象保管。密钥托管技术:为用户提供更好的安全通信方式,同时允许授权者为了国家等安全利益,监听某些通信和解密有关密文。密钥托管加密体制由三部分组成:用户安全分量、密钥托管分量、数据恢复分量。密钥管理:指对于网络中信息加密所需要的各种密钥在产生、分配、注入、存储、传送及使用过程中的技术和管理体制。
保密通信的基本要求:保密性、实时性、可用性、可控性。密码保护技术:密码校验、数字签名、公证消息。通信保密技术:(1)语音保密通信(模拟置乱技术、数字加密技术)。(2)数据保密通信。(3)图像保密通信(模拟置乱、数字化图象信号加密)。网络通信加密的形式:(1)链路加密。(2)端-端加密。(3)混合加密。网络通信访问基本控制方式:(1)连接访问控制。(2)网络数据访问控制。(3)访问控制转发。(4)自主访问控制与强制访问控制。接入控制功能:(1)阻止非法用户进入系统。(2)允许合法用户进入系统。(3)使合法用户按其权限进行活动。接入控制策略:(1)最小权限策略。(2)最小泄漏策略。(3)多级安全策略。接入控制技术方法:(1)用户标识与认证。(2)身份认证特征(口令认证方式、协议验证身份)。
PGP的五种功能:认证性、机密性、压缩、Email兼容性、分段与重组。IP层安全功能:鉴别服务、机密性、密钥管理。
安全套接层SSL提供的安全服务:信息保密、信息完整性、相互认证。
PPDR-A模型五要素:安全策略、安全监测、安全反应、安全防御、安全对抗。操作系统安全访问控制:测试程序访问控制、操作系统的访问权限控制、保护机制的访问控制、用户认证访问控制。
安全操作系统设计四环节:安全模型、安全设计、安全确认、正确实施。安全网络平台种类:Windows NT、UNIX、Linux。(Linux兼容性好、源代码开放、安全透明)。
数据库安全条件:数据独立性、数据安全性、数据完整性、数据使用性、备份与恢复。
VPN(虚拟专用网)核心技术:隧道技术、密码技术、管理技术。
政务网的特点:信息公众化、信息机关化、信息存储量大、保密程度高、访问密级多样化。
政务网建设的三个安全域:(1)涉密域。(2)非涉密域。(3)公共服务域。
黑客攻击:指黑客利用系统漏洞和非常规手段,进行非授权的访问行为和非法运行系统或非法操作数据。
防黑客攻击几种防范技术:安全性设计保护、先进的认证技术、扫描检测审计技术。
常规网络扫描工具:SATAN扫描工具、Nessus安全扫描器、nmap扫描器、strobe扫描器。网络监听工具:NetXRay、Sniffit。防火墙:在网络安全边界控制中,用来阻止从外网想进入给定网络的非法访问对象的安全设备。包括网络级包过滤防火墙和应用级代理防火墙。
密罐:用来观察黑客如何入侵计算机网络系统的一个软件“陷阱”,通常称为诱骗系统。
计算机病毒:指编制或者在计算机程序中插入的破坏计算机功能或者数据,影响计算机使用并且能够自我复制的一组计算机指令或者程序代码。病毒检测方法:比较法、搜索法、辨别法、分析法。
电子商务安全要求:可靠性、真实性、机密性、完整性、有效性、不可抵赖性、可控性。
电子商务安全服务:鉴别服务、访问控制服务、机密性服务、不可否认服务。电子商务基本密码协议:密钥安全协议、认证安全协议、认证的密钥安全协议。国际通用电子商务安全协议:SSL安全协议、SET安全协议、S-HTTP安全协议、STT安全协议。
电子商务实体要素:持卡人、发卡机构、商家、银行、支付网关、认证机构。
第三篇:信息安全论坛
2011中国信息安全高峰论坛
举办地点:上海华夏宾馆
会议报到:2011年10月15日
会议时间:2011年10月15-16日
2011年10月15日13:00-17:00高峰论坛
2011年10月16日9:00-12:00 14:00-17:00高峰论坛
具体演讲嘉宾和演讲题目于2011年9月20日前公布在展会网站上。
优惠方案
1、非参展企业8000元/场
2、参展企业6000元/场 参会对象:
大型企业中小型企业以及行业的IT及业务决策者
海关税务系统科教与科研
国内外银行金融证券部门
公安部门国防部门邮政电信部门
铁路航空物流
政府部门政企商业网络系统集成公司
互联网服务应用软件服务商网络服务提供商
软件设计人员网络专家技术维护人员
软件经销商代理商政府网管人员政府IT信息管理人员等
石油石化电力能源化工
各省市密码管理办公室机要保密局档案管理等部门
第四篇:《信息安全与系统管理》邀请函
《信息安全与系统管理》邀请函
今天信息安全问题正在与各种方式广泛深刻应影响着我们的商务工作和生活。对信息安全问题关注以成为国际潮流。中国的政府企业正在着手建立起积极防御的信息安全要求的,首先就是技术与人才并重。现在微软公司正在以前所未有的关度与深度,集结公司范围内个部门的力量,通力配合,制定有效的安全措施,帮助 广大用户战胜信息安全威胁,提高商务工作环境性,为大众获得最为快捷和优质的信息作出我们的努力,并为您了解微软最新的信息安全管理念,成为中国信息安全管理的翘楚。
这正是我们向您提供一系列信息安全培训目的。
在信息安全培训中,我们将把微软自身用于解决信息安全问题的有效管理方法和崭新理念 以形象生动、深入浅出的形式展示给广大听众。
在2010年2月到6月间,微软安排了全国各地举办一系列以 信息安全为主题的培训。培训将涵盖构建信息安全的3工人阶段:
第一阶段:桌面安全—补丁分发管理解决方案。
第二阶段:信息系统架构 安全。
第三阶段:信息安全与管理
现在你就可以在合同谈判//www.shdnhhhgfrGGF/获取想关资源信息,作好准备迎接更为安全的网络工作和安全管理理念。在此,我们诚挚邀请 来参加本次活动,与我们一起分享成功经验
第五篇:AES-CMAC实验报告 -信息与通信安全
课程名称:姓
名:选择课题:系:专
业:学
号:指导教师:
本科实验报告
信息与通信安全
C/C++实现加解密算法及其应用(实验一)
信电系 信息与通信工程
****年**月**日
目录
1.实验内容与要求.......................................................................................................................3 2.实验原理....................................................................................................................................3
2.1 AES原理..........................................................................................................................3
2.1.1 AES总体结构.......................................................................................................3 2.1.2 AES详细结构.......................................................................................................4 1.1 2.CMAC原理................................................................................................................7
实验环境...........................................................................................................................9
4. 代码实现...............................................................................................................................9
4.1字节代替变换.................................................................................................................9 4.2 行移位变换..................................................................................................................11 4.3列混淆变换...................................................................................................................14 4.4 轮密钥加......................................................................................................................17 4.5 AES的加密与解密的实现............................................................................................22 4.6 CMAC代码实现............................................................................................................23 5.思考题...................................................................................................................................27 6.心得体会...............................................................................................................................27 附录(完整程序).....................................................................................................................28
1.实验内容与要求
(1).复习AES原理。
(2).用C/C++编写AES算法并调试通过。(3).复习CMAC原理。
(4).在实现AES基础上,用C/C++编写CMAC算法并调试通过。(5).回答下列思考题。
AES解密算法和AES的逆算法之间有什么不同? CMAC与HMAC相比,有什么优点?
2.实验原理
2.1 AES原理 2.1.1 AES总体结构
下图展示了AES加密过程的总体结构。明文分组长度为128位即16字节密钥长度可以为16,24或32字节(在本次设计中选择16字节)。
加密和解密算法是输入是一个128位的分组。在FIPS PUB 197中,这个分组被描述为4*4的字节方阵。这个分组被复制到state数组,饼子啊加密或解密的各个阶段被修改。同样,密钥也被描述为字节的方阵,并被扩展为44字的密钥字序列。
密码由N轮组成,其中轮数依赖于密钥长度,16字节密钥是10轮,前N-1轮由4个不同的变换组成:字节代替,行位移,列混淆,轮密钥加。最后一轮包含三个变换,而在第一轮的前面有一个起始的单变换(轮密钥加),可视为第0轮。每一个变换输入一个活多个4*4的矩阵,并输出一个4*4的矩阵,最后一轮输出为密文。同样,密钥扩展函数为N+1轮密钥,它们是互不相同的4*4矩阵。每一个轮密钥作为每轮的轮密钥加变换的一种输入。
2.1.2 AES详细结构
1)
AES算法未使用Feisel结构,而是在每一轮都使用代替和混淆将整个数据分组作为一个单一的矩阵处理。
2)输入的密钥被扩展为44个32位字所组成的数组w[i],每轮由四个不同的字作为该轮的轮密钥。3)由四个不同的阶段组成,包括一个置换和三个代替。字节代替:
用一个S盒完成分组的字节到字节的代替。行位移:
一个简单的置换。列混淆:
利用GF(2^8)上的算术特性的一个代替。轮密钥加:
当前分组和扩展秘钥的一部分进行按位异或。
(一)字节代替变换
如上图,字节代替变换是一个简单的查表操作。AES定义了一个S盒,它由16*16个字节组成的矩阵,包含了8位所能表示的256个数的一个置换。State中 的每个字节按照如下的方式映射为一个新的字节,把改字节的搞4位作为行值,低四位作为列值,以这些行列值作为索引从S盒的对应位置取出元素作为输出。而其逆向操作则是有对应的逆S盒可进行查表。
(二)行移位变换
如上图,其正向行移位变换中,state的第一行保持不变,把state的第二行循环左移一个字节,state的第三行循环左移两个字节,state的第四行循环左移四个字节。例如:
逆向行移位变换将state中的后三行执行相反方向的一位操作即可。
(三)列混淆变换
如上图,列混淆的正向变换是对每列单独进行操作。每列中的每个字节被映射为一个新值,此值由该列中的4个字通过函数变换得到。这个变换可有下面基于state的矩阵乘法表示:
乘积矩阵中的每个元素军事一行和一列中对应元素的乘积之和。这里的乘法和假发都是定义在GF(2^n)上的。状态中单列的列混淆变换可表示为:
其中一个例子如下:
(四)轮密钥加变换
如上图,在轮密钥加变换中,128位的state按位与128位的轮秘钥XOR。该操作可以视为state的一列中的四个字节与轮秘钥的一个字进行列间的操作,例如:
(五)AES密钥扩展
AES密钥扩展算法的输入值是一个4个字,输出值是一个由44个字组成的移位线性数组。
输入密钥字节被复制到扩展密钥数组的前4个字。然后每次用四个字填充扩展密钥数组余下的部分。在扩展数组中,每一个新增的字w[i]的值依赖于w[i-1]和w[i-4]。在4
个情形中,三个使用了异或。对w数组中下标为4的倍数的的元素采用了更复杂的函数来计算:
(1)字循环的功能时使一个字中的四个字节的循环左移一个字节,即将输入字[B0,B1,B2,B3]变成为[B1,B2,B3,B0].(2)字代替利用S盒对输入字中的每个字节进行字节代替。(3)步骤1和步骤2的结果再与轮常量Rcon[j]相异或。
1.1 CMAC原理
基于密码的消息认证码(CMAC)对于AES,3DES适用,它使用三个密钥:一个密钥长为K,用在密文分组链接的每一步,两个长度为n的密钥,其中k是密钥长度,n为密文分组长度。并且两个n位的密钥可以从加密密钥导出,而不是单独提供。首先,当消息长度是分组长度b的n倍时,我们考虑CMAC的运算情况。对AES,b=128,对于3DES,b=64.这个消息被划分为n组,(M1,M2…,Mn)。算法使用了k比特的加密密钥K和n比特的常数K1。对于AES,密钥长度k为128,192和256比特,对于3DES,密钥长度为112或168比特。CMAC按如下方式计算:
C1E(K,M1)C2E(K,[M2C1])C3E(K,[M3C2])...CnE(K,[MNCn1K1])TMSBTlen(Cn)其中:
T——消息认证码,也称为tag Tlen——T的比特长度
MSBs(X)——比特串X最左边的s位
如果消息不是密文分组长度的整数倍,则最后分组的右边(低有效位)填充一个1和若干个0,使得最后的分组长度为b。除了使用一个不同的n比特密钥K2代替K1外,与前面所述一样进行CMAC运算。
两个n比特的密钥由k比特的加密密钥按如下方式导出:
LE(K,0n)K1LxK2LX2(Lx)x其中乘法(·)是在域GF(2^n)内进行,X和X^2是该域的一次和二次多项式。因此X的二元表示为n-2个0,后跟10,X^2的二元表示为n-3个0,后跟100。对于AES,已获批准的分组长度为X^128 +X^7 +X^2 +X+2.。
当消息长度是分组长度的整数倍:
当消息长度不是分组长度的整数倍:
2.实验环境
装有C_Free 的笔记本
4. 代码实现
首先是实现AES的各个子模块,在验证其正确以后,再进行CMAC的认证算法的实现。
4.1字节代替变换
#include
static unsigned char Sbox[256] =
{ //AES的S盒
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 };
static unsigned char InvSbox[256] = { // AES的逆S盒
0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb, 0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87, 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb, 0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d, 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e, 0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2, 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25, 0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92, 0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda, 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84,0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a, 0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06, 0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02, 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b, 0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea, 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73, 0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, 0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e, 0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89, 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b, 0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20, 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4, 0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f, 0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d, 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef, 0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0, 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61, 0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d };
//字节代替变换
void Sub_Byte(unsigned char state[4][4]){ int i,j;
for(i=0;i<4;i++)
for(j=0;j<4;j++)
state[i][j]=Sbox[state[i][j]];
} //逆向字节代替
void Inv_Sub_Byte(unsigned char state[4][4]){ int i,j;
for(i=0;i<4;i++)
for(j=0;j<4;j++)
state[i][j]=InvSbox[state[i][j]];
}
int main(){ unsigned char state[4][4]={
{0xea,0x04,0x65,0x85},{0x83,0x45,0x5d,0x96},{0x5c,0x33,0x98,0xb0},{0xf0,0x2d,0xad,0xc5}
};int i,j;//正向替换 Sub_Byte(state);
printf(“正向代替结果:n”);for(i=0;i<4;i++)
{
for(j=0;j<4;j++)
printf(“%x ”,state[i][j]);
printf(“n”);
}
printf(“n”);//反向替换
Inv_Sub_Byte(state);
printf(“反向代替结果:n”);
for(i=0;i<4;i++)
{
for(j=0;j<4;j++)
printf(“%x ”,state[i][j]);
printf(“n”);
}
}
其测试结果如下,可见该功能可实现是正确的。
4.2 行移位变换
#include
//行移位
void Row_Shift(unsigned char state[4][4]){ int i;unsigned char temp;
} //第一行保持不变,第二行左移一位
temp=state[1][0];for(i=0;i<3;i++)state[1][i]=state[1][i+1];state[1][3]=temp;
//第三行左移2位 temp=state[2][0];state[2][0]=state[2][2];state[2][2]=temp;
temp=state[2][1];state[2][1]=state[2][3];state[2][3]=temp;
//第四行左移3位
temp=state[3][3];for(i=3;i>0;i--)state[3][i]=state[3][i-1];state[3][0]=temp;
//逆向行移位
void Inv_Row_Shift(unsigned char state[4][4]){ int i;unsigned char temp;
//第一行保持不变,第二行右移一位
temp=state[1][3];for(i=3;i>0;i--)state[1][i]=state[1][i-1];state[1][0]=temp;
//第三行右移二位 temp=state[2][0];state[2][0]=state[2][2];state[2][2]=temp;
temp=state[2][1];state[2][1]=state[2][3];state[2][3]=temp;
//第四行右移三位 temp=state[3][0];for(i=0;i<3;i++)state[3][i]=state[3][i+1];state[3][3]=temp;}
int main(){ int i,j;unsigned char state[4][4]={
{0x87,0xf2,0x4d,0x97},{0xec,0x6e,0x4c,0x90},{0x4a,0xc3,0x46,0xe7},{0x8c,0xd8,0x95,0xa6}
};
Row_Shift(state);printf(“正向行移位变换:n”);for(i=0;i<4;i++)
{
for(j=0;j<4;j++)
printf(“%02x ”,state[i][j]);
printf(“n”);
}
printf(“n”);
Inv_Row_Shift(state);
printf(“反向向行移位变换:n”);
for(i=0;i<4;i++)
{
for(j=0;j<4;j++)
printf(“%02x ”,state[i][j]);
printf(“n”);
} } 测试结果如下
通过比较,可知结果正确,因此该子模块实现。
4.3列混淆变换
#include
unsigned char x_time2(unsigned char state)//乘2处理
{
unsigned char temp;
if(state>=0x80)
temp=(state<<1)^0x1b;//判断b7=1?
else
temp=(state<<1);
return temp;}
unsigned char x_time3(unsigned char state)//乘3处理
{
state=state^x_time2(state);
return state;}
unsigned char x_time4(unsigned char state)//乘4处理
{
state=x_time2(x_time2(state));
return state;}
unsigned char x_time8(unsigned char state)//乘8处理14
{
state=x_time2(x_time2(x_time2(state)));
return state;}
unsigned char x_time9(unsigned char state)//乘9处理
{
state=state^x_time8(state);
return state;}
unsigned char x_timeB(unsigned char state)//乘B处理
{
state=state^x_time2(state)^x_time8(state);
return state;}
unsigned char x_timeD(unsigned char state)//乘D处理
{
state=state^x_time4(state)^x_time8(state);
return state;}
unsigned char x_timeE(unsigned char state)//乘E处理
{
state=x_time2(state)^x_time4(state)^x_time8(state);
return state;}
void MixColumns(unsigned char state[4][4]){
int i,j;unsigned char state_1[4][4];
for(i=0;i<4;i++)for(j=0;j<4;j++)
state_1[i][j]=state[i][j];
for(j=0;j<4;j++)
{
state[0][j]=x_time2(state_1[0][j])^x_time3(state_1[1][j])^state_1[2][j]^state_1[3][j];
state[1][j]=state_1[0][j]^x_time2(state_1[1][j])^x_time3(state_1[2][j])^state_1[3][j];
state[2][j]=state_1[0][j]^state_1[1][j]^x_time2(state_1[2][j])^x_time3(state_1[3][j]);
state[3][j]=x_time3(state_1[0][j])^state_1[1][j]^state_1[2][j]^x_time2(state_1[3][j]);} } //逆向列混淆
void Inv_MixColumns(unsigned char state[4][4]){ int i,j;unsigned char state_1[4][4];
for(i=0;i<4;i++)for(j=0;j<4;j++)
state_1[i][j]=state[i][j];
for(j=0;j<4;j++){
state[0][j]=x_timeE(state_1[0][j])^x_timeB(state_1[1][j])^x_timeD(state_1[2][j])^x_time9(state_1[3][j]);
state[1][j]=x_time9(state_1[0][j])^x_timeE(state_1[1][j])^x_timeB(state_1[2][j])^x_timeD(state_1[3][j]);
state[2][j]=x_timeD(state_1[0][j])^x_time9(state_1[1][j])^x_timeE(state_1[2][j])^x_timeB(state_1[3][j]);
state[3][j]=x_timeB(state_1[0][j])^x_timeD(state_1[1][j])^x_time9(state_1[2][j])^x_timeE(state_1[3][j]);} } int main(){ int i,j;unsigned char state[4][4]={
{0x87,0xf2,0x4d,0x97},{0x6e,0x4c,0x90,0xec},{0x46,0xe7,0x4a,0xc3},{0xa6,0x8c,0xd8,0x95}
};
MixColumns(state);
printf(“正向列混淆结果: n”);
for(i=0;i<4;i++)
{
for(j=0;j<4;j++)
printf(“%x ”,state[i][j]);
printf(“n”);
}
printf(“n”);
Inv_MixColumns(state);
printf(“逆向列混淆结果: n”);
for(i=0;i<4;i++)
{
for(j=0;j<4;j++)
printf(“%x ”,state[i][j]);
printf(“n”);
}
} 其测试结果如下:
通过比较,可知结果正确,因此该子模块实现。
4.4 轮密钥加
#include
{ //AES的S盒
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 key_Expansion(unsigned char key[16]){ int i,j,k;
unsigned char temp[4];//用于寄存w[i-1]
unsigned char t;
unsigned char RC[10]={0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80,0x1b,0x36};
unsigned char Rcon[10][4]={{0x01,0x0,0x0,0x0},{0x02,0x0,0x0,0x0},{0x04,0x0,0x0,0x0},{0x08,0x0,0x0,0x0},{0x10,0x0,0x0,0x0},{0x20,0x0,0x0,0x0},{0x40,0x0,0x0,0x0},{0x80,0x0,0x0,0x0},{0x1b,0x0,0x0,0x0},{0x36,0x0,0x0,0x0},};
//轮常量
for(i=0;i<16;i++)//将输入秘钥复制到扩展秘钥数组的前四个字
{
ex_key[i]=key[i];
}
for(i=16;i<176;i+=4)//秘钥扩展
{
for(j=0;j<4;j++)
temp[j]=ex_key[i-4+j];//用于寄存w[i-1]
if(i%16==0)//对于w[i]中下标为的4的倍数要使用函数g来计算
{
//循环左移
t=temp[0];
for(k=0;k<3;k++)
temp[k]=temp[k+1];
temp[3]=t;
//字代替
for(k=0;k<4;k++)
temp[k]=Sbox[temp[k]];
//与轮常量相异或
for(k=0;k<4;k++)
temp[k]=temp[k]^Rcon[i/16-1][k];}
// 得到最后的w[i],w[i]=w[i-1]^w[i-4]
for(k=i;k
ex_key[k]=ex_key[k-16]^temp[k-i];
}
} //第k轮的轮密钥加
void RoundKey(unsigned char state[4][4],int k){ int i,j;
for(i=0;i<16;i++)round_key[k][i]=ex_key[16*k+i];//第k轮的轮密钥生成 for(i=0;i<4;i++)
for(j=0;j<4;j++)
state[i][j]=state[i][j]^round_key[k][4*j+i];
}
int main(){
unsigned char key[16]={0x0f,0x15,0x71,0xc9,0x47,0xd9,0xe8,0x59,0x0c,0xb7,0xad,0xd6,0xaf,0x7f,0x67,0x98};unsigned char state[4][4]={
{0xb9,0x94,0x57,0x75},{0xe4,0x8e,0x16,0x51},{0x47,0x20,0x9a,0x3f},{0xc5,0xd6,0xf5,0x3b}
};int i,j;
key_Expansion(key);
for(i=0;i<11;i++)
{
for(j=0;j<16;j++)round_key[i][j]=ex_key[16*i+j];//第k轮的轮密钥生成}
for(i=0;i<11;i++)
{
printf(“第%d轮密钥:n”,i);
for(j=0;j<16;j++)
{
printf(“%02x ”,round_key[i][j]);
if((j+1)%4==0)
printf(“n”);
}
printf(“n”);
}
RoundKey(state,1);
printf(“第一轮结束后的state输出:n”);
for(i=0;i<4;i++)
{
for(j=0;j<4;j++)
printf(“%02x ”,state[i][j]);
printf(“n”);
}
return 0;} 扩展密钥数组如下:
经过比对,可知,密钥扩展是正确的。我又选取了第一轮的轮密钥加:
测试结果如下:
经过比对,可知道轮密钥加的结果是正确的。
4.5 AES的加密与解密的实现
(程序请见附录)参照书上给的例子: Plaintext[16]={ 0x01,0x23,0x45,0x67, 0x89,0xab,0xcd,0xef, 0xfe.0xdc,0xba,0x98, 0x76,0x54,0x32,0x10 } key[16]={ 0x0f,0x15,0x71,0xc9, 0x47,0xd9,0xe8,0x59, 0x0c,0xb7,0xad,0xd6, 0xaf,0x7f,0x67,0x98 };其理论结果为:
测试结果如下,经过比对可知结果正确。
4.6 CMAC代码实现
//先用k=128的加密秘钥key产生两个n位的秘钥key_1,key_2 void k1_k2(unsigned char key[16],unsigned char key_1[16],unsigned char key_2[16]){ unsigned char L[16];unsigned char zero_n[16]={0x00};int i;Encryption(zero_n,key,L);//即L=E(K,0^n)
//计算k1=L*x,其中多项式为x^128+x^7+x^2+x+1
if(L[0]>=0x80)
//判断最高位是否是1,若是,则需要约化,即左移一位后,再异或1000 0111=0x87
{
for(i=0;i<16;i++)
key_1[i]=L[i]<<1;//左移一位
key_1[15]=key_1[15]^0x87;
} else {
for(i=0;i<16;i++)
key_1[i]=L[i]<<1;}
//产生key_2=L*x^2=key_1*x
if(key_1[0]>=0x80){
for(i=0;i<16;i++)
key_2[i]=key_1[i]<<1;//左移一位
key_2[15]=key_2[15]^0x87;
}
} else {
for(i=0;i<16;i++)
key_2[i]=key_1[i]<<1;}
//对消息不是密文分组的整数倍,要在分组最后右边填充1及若干个0 //*last_text是最后一个不完整分组,length是最后一组的长度,out_text是填充后的输出
void fill(unsigned char *last_text,int length, unsigned char out_text[16]){ int i;
for(i=0;i<16;i++){
if(i out_text[i]=last_text[i]; else if(i==length) out_text[i]=0x80; else out_text[i]=0x00; } } void AES_CMAC(unsigned char Mass[],unsigned char key[16],int length, unsigned char mac[]){ int i,j,n,last_l;int flag=0;//用于标记密文分组是否完整 unsigned char M_C1[16]={0x00},M_C2[16], M_C_K[16];//用于存放中间数据 unsigned char key_1[16],key_2[16];//分组密钥 unsigned char last[16],Cn[16]; n=(length+15)/16;//用于确定分几组 last_l=length%16; k1_k2(key,key_1,key_2); if(last_l==0) flag=1;//表明是分组长度b=128的整数倍 if(flag==0) fill(&Mass[16*(n-1)],last_l,last);//对前n-1轮 for(i=0;i for(j=0;j<16;j++) M_C2[j]=M_C1[j]^Mass[16*i+j]; Encryption(M_C2,key,M_C1); } if(flag==1) { for(i=0;i<16;i++) M_C_K[i]=Mass[16*(n-1)+i]^M_C1[i]^key_1[i]; Encryption(M_C_K,key,Cn); } else { for(i=0;i<16;i++) M_C_K[i]=last[i]^M_C1[i]^key_2[i]; Encryption(M_C_K,key,Cn); } for(i=0;i<16;i++)mac[i]=Cn[i];} int main(){ unsigned char key[16],Mass[64],T[16]; int i,j,length; printf(“请输入消息(64byte):n”);//输入消息 for(i=0;i<64;i++) scanf(“%x”,&Mass[i]); printf(“请输入密钥: n”);//输入密钥 for(i=0;i<16;i++) scanf(“%x”,&key[i]); printf(“需要使用的次数repeat=:n”); scanf(“%d”,&repeat); for(i=0;i { printf(“请输入不同的密文分组长度length:n”); scanf(“%d”,&length); printf(“AES-CMAC输出结果: n”);AES_CMAC(Mass,key,length,T);for(i=0;i<16;i++) printf(“%x ”, T[i]);printf(“n”);} } 测试结果如下: 根据查阅的资料,可知测试结果是正确的。且从上述结果可知,对于不同的分组长度,输出结果相差很大。 5.思考题 1.AES解密算法和AES的逆算法之间有什么不同? AES解密算法与其逆算法不同点在于解密算法对密文是先进行轮密钥加(对AES-128而言其扩展密钥是w[40,43])然后开始第一轮的逆向求解,而逆算法时对加密算法的求逆,即将第十轮的算法倒推回去,所以这里有区别。这是由AES特定结构所决定的。 2.CMAC与HMAC相比,有什么优点? CMAC使用分组密码算法,而HMAC使用散列函数。因为HMAC是基于其所应用的hash函数的,若hash函数的结构存在缺陷,则HMAC的安全性就会大大降低。而CMAC的安全性采用的是分组密码算法,其安全性在于密钥的长度。CMAC的长度可以通过Tlen的变化而变化,输出位数更加灵活。 6.心得体会 首先,刚开始由于这方面知识掌握不是很好,在看完书后又查阅了大量资料,包括一些程序。在这样的一个基础上,对整个编程的思路有了一些认识,按照书本上的AES加密顺序,最先做的就是密钥扩展和轮密钥加。这个部分也是难度最大的部分,主要是输入的都是字节大小的,但密钥扩展后要求是以字为单位输出的。刚开始这个方面纠结了很久,最后为了整个程序比较清晰,还是决定全都以字节为单位,经过一定转换来得到相当于字的效果。 在完成密钥扩展且测试正确后,就开始按顺序设计,字节代替,行移位,列混淆。其中3盒和逆S盒是直接从网上下载的,其他的就是按照书上给的公式和流程图来完成,还是比较顺利的。其解密算法和加密算法也是大同小异的,只是在每个函数中修改一下相应的代码即可。在加密和解密算法都写完后,就是写main函数进行测试,刚开始发现结果总是不对,经过较长时间的查错,发现还是错在轮密钥加中数组转置引起的问题。 在AES设计万仇就是设计CMAC。关于这个程序书上涉及的也较少,但算法还是比较简单的,主要涉及产生两个子密钥和对不完整的分组填充。由于书上没有现有的例子可以参考,因此,我是参照其他同学的例子,进行比较,验证结果是正确的。 附录(完整程序) #include static unsigned char key[16];//输入秘钥 static unsigned char ex_key[176];//扩展密钥,其中每四个拼成的就是一个字的秘钥数组 //即w[i]=(ex_key[4*i],ex_key[4*i+1],ex_key[4*i+2],ex_key[4*i+3])static unsigned char round_key[11][16];//轮密钥 static unsigned char Sbox[256] = { //AES的S盒 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 }; static unsigned char InvSbox[256] = { // AES的逆S盒 0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb, 0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87, 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb, 0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d, 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e, 0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2, 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25, 0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92, 0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda, 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84,0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a, 0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06, 0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02, 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b, 0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea, 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73, 0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, 0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e, 0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89, 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b, 0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20, 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4, 0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f, 0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d, 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef, 0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0, 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61, 0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d }; //乘法处理部分 unsigned char x_time2(unsigned char state)//乘2处理 { unsigned char temp; if(state>=0x80) temp=(state<<1)^0x1b;//判断b7=1? else temp=(state<<1); return temp;} unsigned char x_time3(unsigned char state)//乘3处理 { state=state^x_time2(state); return state;} unsigned char x_time4(unsigned char state)//乘4处理 { state=x_time2(x_time2(state)); return state;} unsigned char x_time8(unsigned char state)//乘8处理 { state=x_time2(x_time2(x_time2(state))); return state;} unsigned char x_time9(unsigned char state)//乘9处理 { state=state^x_time8(state); return state;} unsigned char x_timeB(unsigned char state)//乘B处理 { state=state^x_time2(state)^x_time8(state); return state;} unsigned char x_timeD(unsigned char state)//乘D处理 { state=state^x_time4(state)^x_time8(state); return state;} unsigned char x_timeE(unsigned char state)//乘E处理 { state=x_time2(state)^x_time4(state)^x_time8(state); return state;} //秘钥扩展 void key_Expansion(unsigned char key[16]){ int i,j,k; unsigned char temp[4];//用于寄存w[i-1] unsigned char t; unsigned char RC[10]={0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80,0x1b,0x36}; unsigned char Rcon[10][4]={{0x01,0x0,0x0,0x0},{0x02,0x0,0x0,0x0},{0x04,0x0,0x0,0x0},{0x08,0x0,0x0,0x0},{0x10,0x0,0x0,0x0},{0x20,0x0,0x0,0x0},{0x40,0x0,0x0,0x0},{0x80,0x0,0x0,0x0},{0x1b,0x0,0x0,0x0},{0x36,0x0,0x0,0x0}, }; //轮常量 for(i=0;i<16;i++)//将输入秘钥复制到扩展秘钥数组的前四个字 { ex_key[i]=key[i]; } for(i=16;i<176;i+=4)//秘钥扩展 { for(j=0;j<4;j++) temp[j]=ex_key[i-4+j];//用于寄存w[i-1] if(i%16==0)//对于w[i]中下标为的4的倍数要使用函数g来计算 { //循环左移 t=temp[0]; for(k=0;k<3;k++) temp[k]=temp[k+1]; temp[3]=t; //字代替 for(k=0;k<4;k++) temp[k]=Sbox[temp[k]]; //与轮常量相异或 for(k=0;k<4;k++) temp[k]=temp[k]^Rcon[i/16-1][k];} // 得到最后的w[i],w[i]=w[i-1]^w[i-4] for(k=i;k ex_key[k]=ex_key[k-16]^temp[k-i]; } } //第k轮的轮密钥加 void RoundKey(unsigned char state[4][4],int k){ int i,j; for(i=0;i<16;i++) round_key[k][i]=ex_key[16*k+i];//第k轮的轮密钥生成 for(i=0;i<4;i++) for(j=0;j<4;j++) state[i][j]=state[i][j]^round_key[k][4*j+i]; } //字节代替变换 void Sub_Byte(unsigned char state[4][4]){ int i,j; for(i=0;i<4;i++) for(j=0;j<4;j++) state[i][j]=Sbox[state[i][j]]; } //行移位 void Row_Shift(unsigned char state[4][4]){ int i;unsigned char temp; //第一行保持不变,第二行左移一位 temp=state[1][0];for(i=0;i<3;i++)state[1][i]=state[1][i+1];state[1][3]=temp; //第三行左移二位 temp=state[2][0];state[2][0]=state[2][2];state[2][2]=temp; temp=state[2][1];state[2][1]=state[2][3];state[2][3]=temp; //第四行左移三位,即右移一位 temp=state[3][3];for(i=3;i>0;i--)state[3][i]=state[3][i-1]; state[3][0]=temp;} //列混淆变换 void MixColumns(unsigned char state[4][4]){ int i,j;unsigned char state_1[4][4]; for(i=0;i<4;i++)for(j=0;j<4;j++) state_1[i][j]=state[i][j]; for(j=0;j<4;j++){ state[0][j]=x_time2(state_1[0][j])^x_time3(state_1[1][j])^state_1[2][j]^state_1[3][j]; state[1][j]=state_1[0][j]^x_time2(state_1[1][j])^x_time3(state_1[2][j])^state_1[3][j]; state[2][j]=state_1[0][j]^state_1[1][j]^x_time2(state_1[2][j])^x_time3(state_1[3][j]); state[3][j]=x_time3(state_1[0][j])^state_1[1][j]^state_1[2][j]^x_time2(state_1[3][j]);} } //前9轮每轮有4个步骤 void Round_4(unsigned char state[4][4], int k){ Sub_Byte(state);Row_Shift(state);MixColumns(state);RoundKey(state,k);} //第10轮有3个步骤 void Round_3(unsigned char state[4][4]){ Sub_Byte(state);Row_Shift(state);RoundKey(state,10);} //加密算法,明文 Plaintext,密文CipherText,密钥 key void Encryption(unsigned char Plaintext[16], unsigned char key[16], unsigned CipherText[16]) char { int i,j;unsigned char state[4][4]; for(i=0;i<4;i++) for(j=0;j<4;j++) state[j][i]=Plaintext[4*i+j]; key_Expansion(key);//密钥扩展 //初始轮秘钥加 RoundKey(state,0);//1~10轮 for(i=1;i<10;i++) Round_4(state,i); Round_3(state); //产生密文 for(i=0;i<4;i++) for(j=0;j<4;j++) CipherText[4*i+j]=state[j][i]; } /*////////////////////////////解密////////////////////////////////*/ //逆向行移位 void Inv_Row_Shift(unsigned char state[4][4]){ int i;unsigned char temp; //第一行保持不变,第二行右移一位 temp=state[1][3];for(i=3;i>0;i--)state[1][i]=state[1][i-1];state[1][0]=temp; //第三行右移2位 temp=state[2][0];state[2][0]=state[2][2];state[2][2]=temp; temp=state[2][1];state[2][1]=state[2][3]; } state[2][3]=temp; //第四行右移三位,即左移1位 temp=state[3][0];for(i=0;i<3;i++)state[3][i]=state[3][i+1];state[3][3]=temp;//逆向字节代替 void Inv_Sub_Byte(unsigned char state[4][4]){ int i,j; for(i=0;i<4;i++) for(j=0;j<4;j++) state[i][j]=InvSbox[state[i][j]]; } //逆向列混淆 void Inv_MixColumns(unsigned char state[4][4]){ int i,j;unsigned char state_1[4][4]; for(i=0;i<4;i++)for(j=0;j<4;j++) state_1[i][j]=state[i][j]; for(j=0;j<4;j++){ state[0][j]=x_timeE(state_1[0][j])^x_timeB(state_1[1][j])^x_timeD(state_1[2][j])^x_time9(state_1[3][j]); state[1][j]=x_time9(state_1[0][j])^x_timeE(state_1[1][j])^x_timeB(state_1[2][j])^x_timeD(state_1[3][j]); state[2][j]=x_timeD(state_1[0][j])^x_time9(state_1[1][j])^x_timeE(state_1[2][j])^x_timeB(state_1[3][j]); state[3][j]=x_timeB(state_1[0][j])^x_timeD(state_1[1][j])^x_time9(state_1[2][j])^x_timeE(state_1[3][j]); } } //前9轮每轮有4个步骤 void Inv_Round_4(unsigned char state[4][4], int k){ Inv_Row_Shift(state);Inv_Sub_Byte(state);RoundKey(state,k);Inv_MixColumns(state);} //第10轮有3个步骤 void Inv_Round_3(unsigned char state[4][4]){ Inv_Row_Shift(state);Inv_Sub_Byte(state);RoundKey(state,0);} //解密算法,明文 Plaintext,密文CipherText,密钥 key void Dencryption(unsigned char CipherText[16], unsigned char key[16], unsigned char Plaintext[16]){ int i,j;unsigned char state[4][4]; for(i=0;i<4;i++) for(j=0;j<4;j++) state[i][j]=CipherText[4*j+i]; key_Expansion(key);//密钥扩展 //初始轮密钥加 RoundKey(state,10); //1~10轮 for(i=9;i>0;i--) Inv_Round_4(state,i);Inv_Round_3(state); //产生明文 for(i=0;i<4;i++) for(j=0;j<4;j++) Plaintext[4*i+j]=state[j][i]; } /*/////////////////////////CMAC////////////////////////////*/ //先用k=128的加密秘钥key产生两个n位的秘钥key_1,key_2 void k1_k2(unsigned char key[16],unsigned char key_1[16],unsigned char key_2[16]){ unsigned char L[16];unsigned char zero_n[16]={0x00};int i;Encryption(zero_n,key,L);//即L=E(K,0^n) //计算k1=L*x,其中多项式为x^128+x^7+x^2+x+1 if(L[0]>=0x80) //判断最高位是否是1,若是,则需要约化,即左移一位后,再异或1000 0111=0x87 { for(i=0;i<16;i++) key_1[i]=L[i]<<1;//左移一位 key_1[15]=key_1[15]^0x87; } else { for(i=0;i<16;i++) key_1[i]=L[i]<<1;} //产生key_2=L*x^2=key_1*x if(key_1[0]>=0x80){ for(i=0;i<16;i++) key_2[i]=key_1[i]<<1;//左移一位 key_2[15]=key_2[15]^0x87; } else { for(i=0;i<16;i++) key_2[i]=key_1[i]<<1;} } //对消息不是密文分组的整数倍,要在分组最后右边填充1及若干个0 //*last_text是最后一个不完整分组,length是最后一组的长度,out_text是填充后的输出 void fill(unsigned char *last_text,int length, unsigned char out_text[16]){ int i; for(i=0;i<16;i++){ if(i out_text[i]=last_text[i]; else if(i==length) out_text[i]=0x80; else out_text[i]=0x00; } } void AES_CMAC(unsigned char Mass[],unsigned char key[16],int length, unsigned char mac[]){ int i,j,n,last_l; int flag=0;//用于标记密文分组是否完整 unsigned char M_C1[16]={0x00},M_C2[16], M_C_K[16];//用于存放中间数据 unsigned char key_1[16],key_2[16];//分组密钥 unsigned char last[16],Cn[16]; n=(length+15)/16;//用于确定分几组 last_l=length%16; k1_k2(key,key_1,key_2); if(last_l==0) flag=1;//表明是分组长度b=128的整数倍 if(flag==0) fill(&Mass[16*(n-1)],last_l,last);//对前n-1轮 for(i=0;i for(j=0;j<16;j++) M_C2[j]=M_C1[j]^Mass[16*i+j]; Encryption(M_C2,key,M_C1); } if(flag==1) { for(i=0;i<16;i++) M_C_K[i]=Mass[16*(n-1)+i]^M_C1[i]^key_1[i]; Encryption(M_C_K,key,Cn); } else { for(i=0;i<16;i++) M_C_K[i]=last[i]^M_C1[i]^key_2[i]; Encryption(M_C_K,key,Cn); } for(i=0;i<16;i++)mac[i]=Cn[i];} /*///////////////////////////主函数//////////////////////*/ int main(){ unsigned char Plaintext_1[16]={0x00};unsigned char Ciphertext[16]={0x00};unsigned char Plaintext_2[16]={0x00};unsigned char Mass[64],T[16]; int i,j,length,repeat;//输入明文 printf(“请输入需要加密的明文 :n”); for(i=0;i<16;i++)scanf(“%x”,&Plaintext_1[i]); //输入密钥 printf(“请输入密钥:n”);for(i=0;i<16;i++)scanf(“%x”,&key[i]); //加密 Encryption(Plaintext_1,key,Ciphertext); printf(“加密后的输出密文:n”); for(i=0;i<16;i++) printf(“%02x ”,Ciphertext[i]); printf(“n”); //解密 Dencryption(Ciphertext,key,Plaintext_2); printf(“解密后的输出明文:n”); for(i=0;i<16;i++) printf(“%02x ”,Plaintext_2[i]); printf(“n”); //CMAC printf(“请输入消息(64byte):n”);//输入消息 for(i=0;i<64;i++) { printf(“%02x ”,Mass[i]); if((i+1)%8==0) printf(“n”); } printf(“需要使用的次数repeat=:n”); scanf(“%d”,&repeat); for(j=0;j { printf(“请输入不同的密文分组长度length:n”); scanf(“%d”,&length); printf(“AES-CMAC输出结果: n”); AES_CMAC(Mass,key,length,T); for(i=0;i<16;i++) printf(“%02x ”, T[i]); printf(“n”); } return 0;}