加密算法是信息技术领域经常使用的安全算法,使用场景包括了支付、电商、即使通讯等各类应用。在常用的对称加密算法中,AES(Advanced Encryption Standard)凭借安全性逐渐成为国际主流加密算法。对称/分组加密一般分为流加密(如OFB、CFB等)和块加密(如ECB、CBC等)。对于流加密,需要将分组密码转化为流模式工作。对于块加密(或称分组加密),如果要加密超过块大小的数据,就需要涉及填充和链加密模式。
ECB(Electronic Code Book 电子密码本)的缺点是不能隐藏明文的模式并且可能对明文进行主动攻击。在CWE(Common Weakness Enumeration 通用缺陷列表)中定义为“损坏或危险的加密算法”,但是在实际的开发中,由于开发者缺乏对加密算法认识或者偷懒(毕竟ECB模式不需要偏移向量iv,少了 一个变量)经常使用ECB加密模式,本文主要就ECB模式的加密原理及“明文主动攻击”进行由浅入深的阐述。
AES ECB加密模式原理
AES ECB加密的大致流程如图1所示,明文按照16字节分成n块,通过加密器对每一块进行加密获得n个密文块。最后一块通常不够16字节需要按照一定的填充规则进行填充。
图1:AES ECB加密流程图
图1中的加密器加密过程如图2所示。加密的轮次根据密钥长度确定,密钥长度128位则n=10,密钥长度为192位,则n=12,密钥长度为256次则n=16。明文块16个字节被排列成4×4的二维数组,每一轮的扩展密钥W(i,i+15)同样被排列成4×4密钥数组。。
图2:AES 加密器
从AES ECB模式加密原理可知明文分组和密文分组一一对应,例如明文:"this is block 10this si block 10this is block 10",可以分为三块“this is block 10”、”this si block 10”、”this is block 10”,加密后的对应的密文(字节):” 78 -128 64 -49 -89 100 -126 16 -103 -12 36 49 22 -56 86 -75 82 30 41 -119 -102 -90 58 -64 -2 101 -96 -31 60 ·-8 -1 -3 78 -128 64 -49 -89 100 -126 16 -103 -12 36 49 22 -56 86 -75”密文的前16字节和后16个字节对应明文的前16个字符和后16个字符,且是密文一致。因为在某些情况下,攻击者不需要破解密钥和密文就可以实现对密文的攻击。例如发送者发送“A phone number is +08612611112222 B phone number is +08612611110000”密文:“-67 106 -88 -115 12 47 -10 -24 -105 -13 124 66 -92 80 -126 -126 75 -71 92 31 -77 19 73 116 -34 123 81 -84 41 82 -95 120 26 -23 -18 -59 -87 3 107 -80 -124 114 -128 -77 11 -58 -54 -57 19 -20 62 -83 -59 -10 58 -74 66 28 110 14 -41 -65 -119 -94”。攻击者不需要知道密钥也不需要破解密文,直接对调密文第17-32和第49-64,接受者收到的消息解密后就变成“A phone number is +08612611110000 B phone number is +08612611112222””。
“对明文的主动攻击”
人为攻击一般分为被动攻击和主动攻击,被动攻击一种是指直接获取消息的内容,还有一种是对消息的某些特征进行分析,虽然不能得到完整的消息内容但也可以推测出信息的一些特点,而这些特点有可能是通信双方不想被泄露的。例如图3和图4,该图像的一个位图版本(图3)通过ECB模式可能会被加密成图4。在AES ECB模式中被动攻击一般情况下不会改变消息的内容,所以很难检测到,只能提前预防——禁止使用 ECB模式加密。
图3
图4
主动攻击是指对明文数据的篡改来产生对攻击有价值的密文数据,防止主动攻击一般都非常困难,需要提前预防,要求在安全架构层面需要更加专业的知识和经验。选择明文攻击是指密码分析者不仅可得到一些明文-密文对,还可以选择被加密的明文,并获得相应的密文。针对明文的攻击的举例:
假设条件:
攻击者不知道加密密钥和flag,但是可以通过构造特定的明文,在有限时间内爆破出flag。
第一步:输入字符串””,长度为0,返回密文“-64 74 29 -100 105 -44 -61 -73 104 42 -76 -97 11 66 -93 102 16”,可知flag长度[0,15],以为如果flag的长度为16也需要填充16个16;
第二步:依次输入“a”,“aa”,“aaa”……“aaaaaaaaaaaaaaaa”,发现输入“aaaaaaaaaa”密文长度为16,输入“aaaaaaaaaaa”密文长度为32可知“aaaaaaaaaa”+flag的长度是15,“aaaaaaaaaaa”+flag的长度为16(plain长度为16也需要填充16个字节);所以flag的长度为5。
第三步:爆破flag的第一位,因为1位有8bit位,有2的8次方(128)种可能,普通计算机爆破耗时可以忽略。假设flag=“ABCDE”,首先输入“aaaaaaaaaaaaaaa”+“ABCDE”,则第一块密文是 “aaaaaaaaaaaaaaaA”,对应“77 121 -104 -86 86 93 1 -101 119 -90 75 -105 0 55 4 18”,我们构造k属于[0,128]+’\0’,发现当104,对应ASCII码表的’h’, “aaaaaaaaaaaaaaak”和“aaaaaaaaaaaaaaaA”密文相同,则A=’h’。爆破B的时候输入“aaaaaaaaaaaaaa”获得“aaaaaaaaaaaaaahB”的密文即可爆破出B=e,再依次爆破出CDEF为“ello”,最终我们拿到flag为“hello”。
String empStr = ""; byte[] encBytes1 = AesEcbUtils.encrypt(empStr); System.out.println("encByte1 length: " + encBytes1.length); int len0 = encBytes1.length;//flag长度在[00,15]之间 //获取flag长度 for (int i = 1; i <= 16; ++i) { String tmpStr = getStringByCount(i); byte[] tmp = AesEcbUtils.encrypt(tmpStr); if (tmp.length != len0) { System.out.println("flag len: " + (16 - i)); break; } } //爆破flag第1位 String str1 = "aaaaaaaaaaaaaaa"; byte[] byte1 = AesEcbUtils.encrypt(str1); for (int i = 0; i <= 128; ++i) { char c = (char) ('String empStr = ""; byte[] encBytes1 = AesEcbUtils.encrypt(empStr); System.out.println("encByte1 length: " + encBytes1.length); int len0 = encBytes1.length;//flag长度在[00,15]之间 //获取flag长度 for (int i = 1; i <= 16; ++i) { String tmpStr = getStringByCount(i); byte[] tmp = AesEcbUtils.encrypt(tmpStr); if (tmp.length != len0) { System.out.println("flag len: " + (16 - i)); break; } } //爆破flag第1位 String str1 = "aaaaaaaaaaaaaaa"; byte[] byte1 = AesEcbUtils.encrypt(str1); for (int i = 0; i <= 128; ++i) { char c = (char) ('\0' + i); String str1Temp = str1 + (c); byte[] byte1Tmp = AesEcbUtils.encrypt(str1Temp); if (bytesArrayEqual(byte1, byte1Tmp, 16)) { System.out.println("A: " + (char) ('\0' + i)); } }' + i); String str1Temp = str1 + (c); byte[] byte1Tmp = AesEcbUtils.encrypt(str1Temp); if (bytesArrayEqual(byte1, byte1Tmp, 16)) { System.out.println("A: " + (char) ('String empStr = ""; byte[] encBytes1 = AesEcbUtils.encrypt(empStr); System.out.println("encByte1 length: " + encBytes1.length); int len0 = encBytes1.length;//flag长度在[00,15]之间 //获取flag长度 for (int i = 1; i <= 16; ++i) { String tmpStr = getStringByCount(i); byte[] tmp = AesEcbUtils.encrypt(tmpStr); if (tmp.length != len0) { System.out.println("flag len: " + (16 - i)); break; } } //爆破flag第1位 String str1 = "aaaaaaaaaaaaaaa"; byte[] byte1 = AesEcbUtils.encrypt(str1); for (int i = 0; i <= 128; ++i) { char c = (char) ('\0' + i); String str1Temp = str1 + (c); byte[] byte1Tmp = AesEcbUtils.encrypt(str1Temp); if (bytesArrayEqual(byte1, byte1Tmp, 16)) { System.out.println("A: " + (char) ('\0' + i)); } }' + i)); } }
总结
在本文中我们首先介绍了AES基本的加密原理和加密器加密流程,其次介绍了ECB模式中分组独立加密的安全性,攻击者可以直接对密文进行攻击或者加密无法隐藏明文数据模式。最后我们构造了一个简单的对AES ECB加密进行主动明文攻击例子(详细代码可在GitHub上获取)。写这么多的目的就是希望让普通人可以明白,我们在开发过程中使用加密的目的就是为了保护数据,因此必须慎重考虑选择最好的加密算法是首要考虑的安全因素。[来源:Freebuf]
2025年十大员工管理软件推荐,助力高效团队管理
各位团队管理者们!是不是总感觉团队管理就像一场混乱的战役?员工们工作进度参差不齐,沟通仿佛隔着一层迷雾,任务分配更是毫无头绪?别着急,今天给大家介绍十款员工管理软件,绝对能让你的团队管理效率蹭蹭往上涨,工作开展得顺顺利利!一、升级团队管理,先从软件入手咱们都清楚,一个优秀的团队,光有一群才华出众的员工可不够,还得有一套...
立刻行动!教你简单几步为移动硬盘添加密码
你是不是常常担心,存着重要文件和珍贵照片的移动硬盘,哪天要是不小心丢了,或者被别人轻易翻看?今儿就教你个超简单的法子,给移动硬盘上把 “锁”,让它变成只属于你的私密保险箱!一、为啥要给移动硬盘设密码?咱们日常用的移动硬盘,就像个随身携带的“小仓库”,里头装着各种各样重要的东西。要是没做好安全措施,这些宝贵的数据,就跟放...
五款必备硬件监控软件,让你的设备更安全
咱们手里的电子设备那可是非常重要的,不论是工作学习还是娱乐放松,都离不开它们。但你有没有想过,这些设备要是突然出了啥毛病,数据丢了或者运行慢了,那可咋整?别急,今天就给大伙推荐五款超实用的硬件监控软件,它们能帮你把设备看得死死的,让安全不再是难题!一、为啥需要硬件监控软件?咱们平时用电脑是不是经常遇到卡顿、发热严重的情...
电脑远程监控系统能监测哪些内容?揭示背后真相
在这个数字时代,电脑简直就是咱们工作、学习和生活的好帮手。但麻烦也跟着来了,电脑安全问题越来越让人头疼。你是不是老担心,自己不在电脑跟前的时候,有人偷偷用你的电脑?或者重要的数据正被人悄悄偷走?别愁啦,电脑远程监控系统就是来解决这些问题的。今天,咱们就好好聊聊电脑远程监控到底能监测啥,还有这里面的门道。一、实时监控,啥...
三步搞定移动硬盘加密,数据安全不再难
咱们手里的数据可都是我们的宝贝。工作里攒下的资料,生活中拍的那些私人照片,还有学习时候记的笔记,每一份都藏着咱们的心血和回忆。可现在移动存储设备到处都是,数据丢了或者被别人偷看的风险也跟着变大了。你是不是老为移动硬盘里那些重要数据咋保密发愁呀?今天就教你个又简单又好用的办法 —— 花三步就能给移动硬盘加密,让数据安全再...