md5穷举加速方法
MD5加速可采用碰撞方法,不在本文讨论范围。
通常情况下,对MD5加密值穷举都是通过明文加密后进行比对,相同则得到明文,下面列举一个JAVA版的MD5消息摘要:
public class MD5
{
/*
* A Java implementation of the RSA Data Security, Inc. MD5 Message
* Digest Algorithm, as defined in RFC 1321.
* Based on the JavaScript implementation of Paul Johnston
* Copyright (C) Paul Johnston 1999 - 2000.
* See http://pajhome.org.uk/site/legal.html for details.
* Java Version by Thomas Weber (Orange Interactive GmbH)
*/
/*
* Convert a 32-bit number to a hex string with ls-byte first
*/
String hex_chr = "0123456789abcdef";
private String rhex(int num)
{
StringBuilder str = new StringBuilder();
for(int j = 0; j <= 3; j++){
str.append( hex_chr.charAt((num >> (j * 8 + 4)) & 0x0F) )
.append( hex_chr.charAt((num >> (j * 8)) & 0x0F) );
}
return str.toString();
}
/*
* Convert a string to a sequence of 16-word blocks, stored as an array.
* Append padding bits and the length, as described in the MD5 standard.
*/
private int[] str2blks_MD5(String str)
{
int nblk = ((str.length() + 8) >> 6) + 1;
int[] blks = new int[nblk * 16];
int i = 0;
for(i = 0; i < nblk * 16; i++) {
blks[i] = 0;
}
for(i = 0; i < str.length(); i++) {
blks[i >> 2] |= str.charAt(i) << ((i % 4) * 8);
}
blks[i >> 2] |= 0x80 << ((i % 4) * 8);
blks[nblk * 16 - 2] = str.length()*8;
return blks;
}
/*
* Add integers, wrapping at 2^32
*/
private int add(int x, int y)
{
return ((x&0x7FFFFFFF) + (y&0x7FFFFFFF)) ^ (x&0x80000000) ^ (y&0x80000000);
}
/*
* Bitwise rotate a 32-bit number to the left
*/
private int rol(int num, int cnt)
{
return (num << cnt) | (num >>> (32 - cnt));
}
/*
* These functions implement the basic operation for each round of the
* algorithm.
*/
private int cmn(int q, int a, int b, int x, int s, int t)
{
return add(rol(add(add(a, q), add(x, t)), s), b);
}
private int ff(int a, int b, int c, int d, int x, int s, int t)
{
return cmn((b & c) | ((~b) & d), a, b, x, s, t);
}
private int gg(int a, int b, int c, int d, int x, int s, int t)
{
return cmn((b & d) | (c & (~d)), a, b, x, s, t);
}
private int hh(int a, int b, int c, int d, int x, int s, int t)
{
return cmn(b ^ c ^ d, a, b, x, s, t);
}
private int ii(int a, int b, int c, int d, int x, int s, int t)
{
return cmn(c ^ (b | (~d)), a, b, x, s, t);
}
/*
* Take a string and return the hex representation of its MD5.
*/
public String calcMD5(String str)
{
int[] x = str2blks_MD5(str);
int a = 0x67452301;
int b = 0xEFCDAB89;
int c = 0x98BADCFE;
int d = 0x10325476;
for(int i = 0; i < x.length; i += 16)
{
int olda = a;
int oldb = b;
int oldc = c;
int oldd = d;
a = ff(a, b, c, d, x[i+ 0], 7 , 0xD76AA478);
d = ff(d, a, b, c, x[i+ 1], 12, 0xE8C7B756);
c = ff(c, d, a, b, x[i+ 2], 17, 0x242070DB);
b = ff(b, c, d, a, x[i+ 3], 22, 0xC1BDCEEE);
a = ff(a, b, c, d, x[i+ 4], 7 , 0xF57C0FAF);
d = ff(d, a, b, c, x[i+ 5], 12, 0x4787C62A);
c = ff(c, d, a, b, x[i+ 6], 17, 0xA8304613);
b = ff(b, c, d, a, x[i+ 7], 22, 0xFD469501);
a = ff(a, b, c, d, x[i+ 8], 7 , 0x698098D8);
d = ff(d, a, b, c, x[i+ 9], 12, 0x8B44F7AF);
c = ff(c, d, a, b, x[i+10], 17, 0xFFFF5BB1);
b = ff(b, c, d, a, x[i+11], 22, 0x895CD7BE);
a = ff(a, b, c, d, x[i+12], 7 , 0x6B901122);
d = ff(d, a, b, c, x[i+13], 12, 0xFD987193);
c = ff(c, d, a, b, x[i+14], 17, 0xA679438E);
b = ff(b, c, d, a, x[i+15], 22, 0x49B40821);
a = gg(a, b, c, d, x[i+ 1], 5 , 0xF61E2562);
d = gg(d, a, b, c, x[i+ 6], 9 , 0xC040B340);
c = gg(c, d, a, b, x[i+11], 14, 0x265E5A51);
b = gg(b, c, d, a, x[i+ 0], 20, 0xE9B6C7AA);
a = gg(a, b, c, d, x[i+ 5], 5 , 0xD62F105D);
d = gg(d, a, b, c, x[i+10], 9 , 0x02441453);
c = gg(c, d, a, b, x[i+15], 14, 0xD8A1E681);
b = gg(b, c, d, a, x[i+ 4], 20, 0xE7D3FBC8);
a = gg(a, b, c, d, x[i+ 9], 5 , 0x21E1CDE6);
d = gg(d, a, b, c, x[i+14], 9 , 0xC33707D6);
c = gg(c, d, a, b, x[i+ 3], 14, 0xF4D50D87);
b = gg(b, c, d, a, x[i+ 8], 20, 0x455A14ED);
a = gg(a, b, c, d, x[i+13], 5 , 0xA9E3E905);
d = gg(d, a, b, c, x[i+ 2], 9 , 0xFCEFA3F8);
c = gg(c, d, a, b, x[i+ 7], 14, 0x676F02D9);
b = gg(b, c, d, a, x[i+12], 20, 0x8D2A4C8A);
a = hh(a, b, c, d, x[i+ 5], 4 , 0xFFFA3942);
d = hh(d, a, b, c, x[i+ 8], 11, 0x8771F681);
c = hh(c, d, a, b, x[i+11], 16, 0x6D9D6122);
b = hh(b, c, d, a, x[i+14], 23, 0xFDE5380C);
a = hh(a, b, c, d, x[i+ 1], 4 , 0xA4BEEA44);
d = hh(d, a, b, c, x[i+ 4], 11, 0x4BDECFA9);
c = hh(c, d, a, b, x[i+ 7], 16, 0xF6BB4B60);
b = hh(b, c, d, a, x[i+10], 23, 0xBEBFBC70);
a = hh(a, b, c, d, x[i+13], 4 , 0x289B7EC6);
d = hh(d, a, b, c, x[i+ 0], 11, 0xEAA127FA);
c = hh(c, d, a, b, x[i+ 3], 16, 0xD4EF3085);
b = hh(b, c, d, a, x[i+ 6], 23, 0x04881D05);
a = hh(a, b, c, d, x[i+ 9], 4 , 0xD9D4D039);
d = hh(d, a, b, c, x[i+12], 11, 0xE6DB99E5);
c = hh(c, d, a, b, x[i+15], 16, 0x1FA27CF8);
b = hh(b, c, d, a, x[i+ 2], 23, 0xC4AC5665);
a = ii(a, b, c, d, x[i+ 0], 6 , 0xF4292244);
d = ii(d, a, b, c, x[i+ 7], 10, 0x432AFF97);
c = ii(c, d, a, b, x[i+14], 15, 0xAB9423A7);
b = ii(b, c, d, a, x[i+ 5], 21, 0xFC93A039);
a = ii(a, b, c, d, x[i+12], 6 , 0x655B59C3);
d = ii(d, a, b, c, x[i+ 3], 10, 0x8F0CCC92);
c = ii(c, d, a, b, x[i+10], 15, 0xFFEFF47D);
b = ii(b, c, d, a, x[i+ 1], 21, 0x85845DD1);
a = ii(a, b, c, d, x[i+ 8], 6 , 0x6FA87E4F);
d = ii(d, a, b, c, x[i+15], 10, 0xFE2CE6E0);
c = ii(c, d, a, b, x[i+ 6], 15, 0xA3014314);
b = ii(b, c, d, a, x[i+13], 21, 0x4E0811A1);
a = ii(a, b, c, d, x[i+ 4], 6 , 0xF7537E82);
d = ii(d, a, b, c, x[i+11], 10, 0xBD3AF235);
c = ii(c, d, a, b, x[i+ 2], 15, 0x2AD7D2BB);
b = ii(b, c, d, a, x[i+ 9], 21, 0xEB86D391);
a = add(a, olda);
b = add(b, oldb);
c = add(c, oldc);
d = add(d, oldd);
}
return rhex(a) + rhex(b) + rhex(c) + rhex(d); ---- 标注1
}
}
该算法效率相对于 java.security.MessageDigest 比较差,但是给我们提供了分析。
加速方法: 在 标注1 处,得到了整型 a b c d,然后调用 rhex 函数对整型进行操作得到8字节的字符串,
在这里,我们可以去掉rhex的计算,直接比对a b c d的值,使得运算量减少,如下面的方法(JAVA版):
public boolean math(String str, int[] targetDigest)
{
int[] x = str2blks_MD5(str);
int a = 0x67452301;
int b = 0xEFCDAB89;
int c = 0x98BADCFE;
int d = 0x10325476;
for(int i = 0; i < x.length; i += 16)
{
int olda = a;
int oldb = b;
int oldc = c;
int oldd = d;
a = ff(a, b, c, d, x[i+ 0], 7 , 0xD76AA478);
d = ff(d, a, b, c, x[i+ 1], 12, 0xE8C7B756);
c = ff(c, d, a, b, x[i+ 2], 17, 0x242070DB);
b = ff(b, c, d, a, x[i+ 3], 22, 0xC1BDCEEE);
a = ff(a, b, c, d, x[i+ 4], 7 , 0xF57C0FAF);
d = ff(d, a, b, c, x[i+ 5], 12, 0x4787C62A);
c = ff(c, d, a, b, x[i+ 6], 17, 0xA8304613);
b = ff(b, c, d, a, x[i+ 7], 22, 0xFD469501);
a = ff(a, b, c, d, x[i+ 8], 7 , 0x698098D8);
d = ff(d, a, b, c, x[i+ 9], 12, 0x8B44F7AF);
c = ff(c, d, a, b, x[i+10], 17, 0xFFFF5BB1);
b = ff(b, c, d, a, x[i+11], 22, 0x895CD7BE);
a = ff(a, b, c, d, x[i+12], 7 , 0x6B901122);
d = ff(d, a, b, c, x[i+13], 12, 0xFD987193);
c = ff(c, d, a, b, x[i+14], 17, 0xA679438E);
b = ff(b, c, d, a, x[i+15], 22, 0x49B40821);
a = gg(a, b, c, d, x[i+ 1], 5 , 0xF61E2562);
d = gg(d, a, b, c, x[i+ 6], 9 , 0xC040B340);
c = gg(c, d, a, b, x[i+11], 14, 0x265E5A51);
b = gg(b, c, d, a, x[i+ 0], 20, 0xE9B6C7AA);
a = gg(a, b, c, d, x[i+ 5], 5 , 0xD62F105D);
d = gg(d, a, b, c, x[i+10], 9 , 0x02441453);
c = gg(c, d, a, b, x[i+15], 14, 0xD8A1E681);
b = gg(b, c, d, a, x[i+ 4], 20, 0xE7D3FBC8);
a = gg(a, b, c, d, x[i+ 9], 5 , 0x21E1CDE6);
d = gg(d, a, b, c, x[i+14], 9 , 0xC33707D6);
c = gg(c, d, a, b, x[i+ 3], 14, 0xF4D50D87);
b = gg(b, c, d, a, x[i+ 8], 20, 0x455A14ED);
a = gg(a, b, c, d, x[i+13], 5 , 0xA9E3E905);
d = gg(d, a, b, c, x[i+ 2], 9 , 0xFCEFA3F8);
c = gg(c, d, a, b, x[i+ 7], 14, 0x676F02D9);
b = gg(b, c, d, a, x[i+12], 20, 0x8D2A4C8A);
a = hh(a, b, c, d, x[i+ 5], 4 , 0xFFFA3942);
d = hh(d, a, b, c, x[i+ 8], 11, 0x8771F681);
c = hh(c, d, a, b, x[i+11], 16, 0x6D9D6122);
b = hh(b, c, d, a, x[i+14], 23, 0xFDE5380C);
a = hh(a, b, c, d, x[i+ 1], 4 , 0xA4BEEA44);
d = hh(d, a, b, c, x[i+ 4], 11, 0x4BDECFA9);
c = hh(c, d, a, b, x[i+ 7], 16, 0xF6BB4B60);
b = hh(b, c, d, a, x[i+10], 23, 0xBEBFBC70);
a = hh(a, b, c, d, x[i+13], 4 , 0x289B7EC6);
d = hh(d, a, b, c, x[i+ 0], 11, 0xEAA127FA);
c = hh(c, d, a, b, x[i+ 3], 16, 0xD4EF3085);
b = hh(b, c, d, a, x[i+ 6], 23, 0x04881D05);
a = hh(a, b, c, d, x[i+ 9], 4 , 0xD9D4D039);
d = hh(d, a, b, c, x[i+12], 11, 0xE6DB99E5);
c = hh(c, d, a, b, x[i+15], 16, 0x1FA27CF8);
b = hh(b, c, d, a, x[i+ 2], 23, 0xC4AC5665);
a = ii(a, b, c, d, x[i+ 0], 6 , 0xF4292244);
d = ii(d, a, b, c, x[i+ 7], 10, 0x432AFF97);
c = ii(c, d, a, b, x[i+14], 15, 0xAB9423A7);
b = ii(b, c, d, a, x[i+ 5], 21, 0xFC93A039);
a = ii(a, b, c, d, x[i+12], 6 , 0x655B59C3);
d = ii(d, a, b, c, x[i+ 3], 10, 0x8F0CCC92);
c = ii(c, d, a, b, x[i+10], 15, 0xFFEFF47D);
b = ii(b, c, d, a, x[i+ 1], 21, 0x85845DD1);
a = ii(a, b, c, d, x[i+ 8], 6 , 0x6FA87E4F);
d = ii(d, a, b, c, x[i+15], 10, 0xFE2CE6E0);
c = ii(c, d, a, b, x[i+ 6], 15, 0xA3014314);
b = ii(b, c, d, a, x[i+13], 21, 0x4E0811A1);
a = ii(a, b, c, d, x[i+ 4], 6 , 0xF7537E82);
d = ii(d, a, b, c, x[i+11], 10, 0xBD3AF235);
c = ii(c, d, a, b, x[i+ 2], 15, 0x2AD7D2BB);
b = ii(b, c, d, a, x[i+ 9], 21, 0xEB86D391);
a = add(a, olda);
b = add(b, oldb);
c = add(c, oldc);
d = add(d, oldd);
}
if(a == targetDigest[0] && b == targetDigest[1]
&& c == targetDigest[2] && d == targetDigest[3])
return true;
return false;
}
下面举例 12032412 (密文为 cba90cf380f4a2acce203de9970b81a4 ),其中math函数的str参数就是输入需要散列的明文(比如12032412),
那如何根据cba90cf380f4a2acce203de9970b81a4 得到 targetDigest(包含4位整数的数组,其实就是 a=targetDigest[0],b=targetDigest[1] .... )如何得到呢?根据下面得到:
JAVA版:
public static int[] md5HexStringToInt(String targetDigest)
{
int h_targetDigest[] = new int[4];
for (int c=0;c<targetDigest.length();c+=8) {
int x = c2c(targetDigest.charAt(c)) <<4 | c2c(targetDigest.charAt(c+1));
int y = c2c(targetDigest.charAt(c+2)) << 4 | c2c(targetDigest.charAt(c+3));
int z = c2c(targetDigest.charAt(c+4)) << 4 | c2c(targetDigest.charAt(c+5));
int w = c2c(targetDigest.charAt(c+6)) << 4 | c2c(targetDigest.charAt(c+7));
h_targetDigest[c/8] = w << 24 | z << 16 | y << 8 | x;
}
return h_targetDigest;
}
然后穷举程式变为(类比程式,根据实际更变):
int[] temp = md5HexStringToInt("cba90cf380f4a2acce203de9970b81a4");
for(...){
if(m.math(需要散列的明文, temp)){
break;
}
}
C++版:
typedef unsigned int uint;
typedef unsigned char uchar;
uchar c2c (char c){
return (uchar)((c > '9') ? (c - 'a' + 10) : (c - '0'));
}
uint h_targetDigest[4];
for (int c=0;c<targetDigest.size();c+=8) {
uint x = c2c(targetDigest[c]) <<4 | c2c(targetDigest[c+1]);
uint y = c2c(targetDigest[c+2]) << 4 | c2c(targetDigest[c+3]);
uint z = c2c(targetDigest[c+4]) << 4 | c2c(targetDigest[c+5]);
uint w = c2c(targetDigest[c+6]) << 4 | c2c(targetDigest[c+7]);
h_targetDigest[c/8] = w << 24 | z << 16 | y << 8 | x;
}

浙公网安备 33010602011771号