md5 Length Extension Attack
来源:互联网 发布:电视盒子软件2017 编辑:程序博客网 时间:2024/05/17 09:38
描述
设msg为原始消息(对于攻击者来说是未知的),padding为msg的补齐部分,append为附加的数据。
根据msg的长度可以推算出padding(如果长度未知则可以从1开始暴力枚举),根据md5(msg)可以计算出md5(msg + padding + append)。
原理分析
md5算法对消息进行分组,每组64个字节,不足64个字节的部分用padding补齐。padding补齐的规则是,在最末一个字节之后补充0x80,其余部分填充为0x00,padding最后的8个字节用来表示需要哈希的消息的位长度。补齐总是进行的,即如果消息的长度刚好是64个字节的整数倍,则也需要补齐64个字节。
在对消息进行分组以及padding后,md5算法依次对魅族消息进行压缩,经过64轮数学变换。在这个过程中,一开始会有定义好的初始化向量,为4个中间值,初始化向量是标准里定义的,为
vi[0] = 0x67452301
vi[1] = 0xEFCDAB89
vi[2] = 0x98BADCFE
vi[3] = 0x10325476
md5 length extension attack的理论基础,就是将已知的压缩后的结果,直接拿过来作为新的压缩输入。在这个过程中,只需要上一次压缩后的结果,而不需要知道原来的消息内容
所以把md5(msg)还原为4个变量替换掉vi中的4个变量即可计算出md5(msg + padding + append)的值
参考
- [rfc1321](https://www.ietf.org/rfc/rfc1321.txt
应对方法
计算md5时,加密前的字符串的最后一位用双方约定的secret_key即可。
代码
#include <stdio.h>#include <string.h>#include <iostream>#include <string>#include <vector>using namespace std;typedef unsigned char uint_8;typedef unsigned short uint_16;typedef unsigned int uint_32;typedef unsigned long long uint_64;#define ustring basic_string<unsigned char>//十进制转16进制string int2hex(uint_32 a){ string hexStr = ""; if(a == 0){ hexStr += "0"; }else{ uint_32 i; char str[2] = "0"; while(a > 0){ i = a % 16; a >>= 4; if(i <= 9){ hexStr = to_string((long long unsigned int)i) + hexStr; }else{ str[0] = (char)(i - 10 + (int)'a'); hexStr = string(str) + hexStr; } } } return hexStr;}uint_32 hex2int(string s){ if(s == "0"){ return 0; } uint_32 a = 0, b; for(int i = 0; i < s.length(); i++){ a <<= 4; if(s[i] >= '0' && s[i] <= '9'){ b = (int) (s[i] - '0'); }else if(s[i] >= 'a' && s[i] <= 'z'){ b = (int) (s[i] - 'a') + 10; }else if(s[i] >= 'A' && s[i] <= 'Z'){ b = (int) (s[i] - 'A') + 10; }else{ b = 0; } a += b; } return a;}void str2ascii(const unsigned char *str, int length){ for(int i = 0; i < length; i++){ if(i > 0) printf(" "); cout << int2hex((int)str[i]); }}uint_32 rotate_left(uint_32 x, uint_32 n){ return (x << n) | (x >> (32-n));}uint_32 F(uint_32 X, uint_32 Y, uint_32 Z){ return (X&Y)|((~X)&Z);}uint_32 G(uint_32 X, uint_32 Y, uint_32 Z){ return (X&Z)|(Y&(~Z));}uint_32 H(uint_32 X, uint_32 Y, uint_32 Z){ return X^Y^Z;}uint_32 I(uint_32 X, uint_32 Y, uint_32 Z){ return Y^(X|(~Z));}void FF(uint_32 &a, uint_32 b, uint_32 c, uint_32 d, uint_32 m, uint_32 s, uint_32 t){ a=b+rotate_left((a+F(b,c,d)+m+t), s);}void GG(uint_32 &a, uint_32 b, uint_32 c, uint_32 d, uint_32 m, uint_32 s, uint_32 t){ a=b+rotate_left((a+G(b,c,d)+m+t), s);}void HH(uint_32 &a, uint_32 b, uint_32 c, uint_32 d, uint_32 m, uint_32 s, uint_32 t){ a=b+rotate_left((a+H(b,c,d)+m+t), s);}void II(uint_32 &a, uint_32 b, uint_32 c, uint_32 d, uint_32 m, uint_32 s, uint_32 t){ a=b+rotate_left((a+I(b,c,d)+m+t), s);}class Md5{public: static string encrypt(ustring input); static void length_extension_attack(ustring md5Str, ustring appendStr); static ustring md5_padding(ustring input); static ustring md5_padding_with_length(ustring input, uint_64 bitLen = 0, uint_64 writeBitLen = 0); static ustring to_ustring(string input); static string to_string(ustring input);protected: static string encrypt_with_vec(ustring paddingStr, vector<uint_32> vi);};string Md5::encrypt(ustring input){ /*{{{*/ vector<uint_32> vi(4); vi[0] = 0x67452301; vi[1] = 0xEFCDAB89; vi[2] = 0x98BADCFE; vi[3] = 0x10325476; ustring paddingStr = md5_padding(input); return encrypt_with_vec(paddingStr, vi); /*}}}*/}string Md5::encrypt_with_vec(ustring paddingStr, vector<uint_32> vi){ /*{{{*/ if(vi.size() < 4){ printf("vi至少要有4各元素"); return ""; } uint_32 a=vi[0], b=vi[1], c=vi[2], d=vi[3]; uint_32 aa, bb, cc, dd; uint_32 m[16]; uint_64 length = paddingStr.length(); int i, j; for(i = 0; i < length / 64; i++){ for(j = 0; j < 64; j += 4){ m[j / 4] = (uint_32)paddingStr[i * 64 + j] + ((uint_32)paddingStr[i * 64 + j + 1] << 8) + ((uint_32)paddingStr[i * 64 + j + 2] << 16) + ((uint_32)paddingStr[i * 64 + j + 3] << 24); } aa = a; bb = b; cc = c; dd = d; /*{{{第一轮*/ FF(a,b,c,d,m[0],7,0xd76aa478); FF(d,a,b,c,m[1],12,0xe8c7b756); FF(c,d,a,b,m[2],17,0x242070db); FF(b,c,d,a,m[3],22,0xc1bdceee); FF(a,b,c,d,m[4],7,0xf57c0faf); FF(d,a,b,c,m[5],12,0x4787c62a); FF(c,d,a,b,m[6],17,0xa8304613); FF(b,c,d,a,m[7],22,0xfd469501); FF(a,b,c,d,m[8],7,0x698098d8); FF(d,a,b,c,m[9],12,0x8b44f7af); FF(c,d,a,b,m[10],17,0xffff5bb1); FF(b,c,d,a,m[11],22,0x895cd7be); FF(a,b,c,d,m[12],7,0x6b901122); FF(d,a,b,c,m[13],12,0xfd987193); FF(c,d,a,b,m[14],17,0xa679438e); FF(b,c,d,a,m[15],22,0x49b40821); /*}}}*/ /*{{{第二轮*/ GG(a,b,c,d,m[1],5,0xf61e2562); GG(d,a,b,c,m[6],9,0xc040b340); GG(c,d,a,b,m[11],14,0x265e5a51); GG(b,c,d,a,m[0],20,0xe9b6c7aa); GG(a,b,c,d,m[5],5,0xd62f105d); GG(d,a,b,c,m[10],9,0x02441453); GG(c,d,a,b,m[15],14,0xd8a1e681); GG(b,c,d,a,m[4],20,0xe7d3fbc8); GG(a,b,c,d,m[9],5,0x21e1cde6); GG(d,a,b,c,m[14],9,0xc33707d6); GG(c,d,a,b,m[3],14,0xf4d50d87); GG(b,c,d,a,m[8],20,0x455a14ed); GG(a,b,c,d,m[13],5,0xa9e3e905); GG(d,a,b,c,m[2],9,0xfcefa3f8); GG(c,d,a,b,m[7],14,0x676f02d9); GG(b,c,d,a,m[12],20,0x8d2a4c8a); /*}}}*/ /*{{{第三轮*/ HH(a,b,c,d,m[5],4,0xfffa3942); HH(d,a,b,c,m[8],11,0x8771f681); HH(c,d,a,b,m[11],16,0x6d9d6122); HH(b,c,d,a,m[14],23,0xfde5380c); HH(a,b,c,d,m[1],4,0xa4beea44); HH(d,a,b,c,m[4],11,0x4bdecfa9); HH(c,d,a,b,m[7],16,0xf6bb4b60); HH(b,c,d,a,m[10],23,0xbebfbc70); HH(a,b,c,d,m[13],4,0x289b7ec6); HH(d,a,b,c,m[0],11,0xeaa127fa); HH(c,d,a,b,m[3],16,0xd4ef3085); HH(b,c,d,a,m[6],23,0x04881d05); HH(a,b,c,d,m[9],4,0xd9d4d039); HH(d,a,b,c,m[12],11,0xe6db99e5); HH(c,d,a,b,m[15],16,0x1fa27cf8); HH(b,c,d,a,m[2],23,0xc4ac5665); /*}}}*/ /*{{{第四轮*/ II(a,b,c,d,m[0],6,0xf4292244); II(d,a,b,c,m[7],10,0x432aff97); II(c,d,a,b,m[14],15,0xab9423a7); II(b,c,d,a,m[5],21,0xfc93a039); II(a,b,c,d,m[12],6,0x655b59c3); II(d,a,b,c,m[3],10,0x8f0ccc92); II(c,d,a,b,m[10],15,0xffeff47d); II(b,c,d,a,m[1],21,0x85845dd1); II(a,b,c,d,m[8],6,0x6fa87e4f); II(d,a,b,c,m[15],10,0xfe2ce6e0); II(c,d,a,b,m[6],15,0xa3014314); II(b,c,d,a,m[13],21,0x4e0811a1); II(a,b,c,d,m[4],6,0xf7537e82); II(d,a,b,c,m[11],10,0xbd3af235); II(c,d,a,b,m[2],15,0x2ad7d2bb); II(b,c,d,a,m[9],21,0xeb86d391); /*}}}*/ a += aa; b += bb; c += cc; d += dd; } uint_32 i4[4] = {a, b, c, d}; string md5Str = "", tmpStr; for(i = 0; i < 4; i++){ tmpStr = ""; for(j = 0; j < 4; j++){ tmpStr += int2hex((i4[i] >> 4) & 0XF) + int2hex(i4[i] & 0XF); i4[i] >>= 8; } md5Str += tmpStr; } return md5Str; /*}}}*/}ustring Md5::md5_padding(ustring input){ // 填充长度 return md5_padding_with_length(input);}/* * @param bitLen : 填充后的字符串的位长度,不包括最后64位用于存储原始字符串长度的位数 */ustring Md5::md5_padding_with_length(ustring input, uint_64 bitLen, uint_64 writeBitLen){ /*{{{填充长度*/ int bitLenMod; uint_32 strLen; uint_64 inputBitLen; inputBitLen = (uint_64)input.length() * 8; bitLenMod = inputBitLen % 512; if(bitLen == 0){ if(bitLenMod < 448){ bitLen = inputBitLen + 448 - bitLenMod; }else{ bitLen = inputBitLen + 512 - (bitLenMod - 448); } } strLen = (bitLen / 8) + 8; ustring str; str.resize(strLen, '\0'); int i, j; for(i = 0; i < input.length(); i++){ str[i] = input[i]; } str[i++] = 0X80; for(; i < strLen - 8; i++){ str[i++] = 0; } //最后8个字符为填充前的长度 if(writeBitLen == 0){ writeBitLen = inputBitLen; } for(i = strLen - 8; i < strLen; i++, writeBitLen >>= 8){ str[i] = 0XFF & writeBitLen; } return str; /*}}}*/}ustring Md5::to_ustring(string input){ ustring str; str.resize(input.size()); for(int i = 0; i < input.size(); i++){ str[i] = (uint_8) input[i]; } return str;}string Md5::to_string(ustring input){ string str; str.resize(input.size()); for(int i = 0; i < input.size(); i++){ str[i] = (char) input[i]; } return str;}void Md5::length_extension_attack(ustring input, ustring appendStr){ /*{{{*/ string md5Str = Md5::encrypt(input); vector<uint_32> m(4); int i, j; for(i = 0; i < 32; i += 8){ m[i >> 3] = 0; for(j = 6; j >= 0; j -= 2){ m[i >> 3] <<= 8; m[i >> 3] |= hex2int(md5Str.substr(i + j, 2)); } } ustring newStr, paddingStr; string guessedMd5, realMd5; newStr = md5_padding(input) + appendStr; realMd5 = encrypt(newStr); cout << "md5_padding(newStr): " << endl; cout << "realMd5 : " << realMd5 << endl; paddingStr = md5_padding_with_length(appendStr, 448, newStr.length() * 8); guessedMd5 = encrypt_with_vec(paddingStr, m); cout << "guessedMd5 : " << guessedMd5 << endl; /*}}}*/}int main (int argc,char *argv[]){ string md5Str; ustring input; input = Md5::to_ustring("0.12204316770657897"); ustring appendStr = Md5::to_ustring("axis is smart!"); md5Str = Md5::encrypt(input); cout << "md5(" << Md5::to_string(input) << ") = " << md5Str << endl; Md5::length_extension_attack(input, appendStr); return 0; }
阅读全文
0 0
- md5 Length Extension Attack
- Length Extension Attack
- Hash length extension attacks 分析
- Attack
- Attack
- extension
- Extension
- Extension
- CC2640R2F BLE5.0 蓝牙协议栈数据长度扩展功能(LE Data Length Extension)
- ({}+{}).length
- length & length()
- rose AttAck
- Sybil attack
- Sybil Attack
- Replay attack
- Test attack
- Network Attack
- Attack Tools
- dp题目
- Kosaraju算法
- conda更换国内下载镜像
- leetcode 86. Partition List
- 用Python建立最简单的web服务器
- md5 Length Extension Attack
- ssl协议,openssl,创建私有CA
- VS2010中使用sprintf出现warning C4997: 'sprintf': This function or variable may be unsafe.
- 【Scikit-Learn 中文文档】随机梯度下降
- js判断浏览器的关闭标签动作和刷新的事件
- JS使用canvas给图片打马赛克
- 链表知识技巧
- 局域网中的几大分类,包含以太网,FDDI网,令牌环网,ATM网
- APACHE