I've checked the compiler output with -O3 under gcc and it does the loop unrolling. so it's rather redundant to that. but not bad
Code: Select all
uint32_t __s1[] = {7, 12, 17, 22};
uint32_t __s2[] = {5, 9, 14, 20};
uint32_t __s3[] = {4, 11, 16, 23};
uint32_t __s4[] = {6, 10, 15, 21};
uint32_t __k1[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15};
uint32_t __k2[] = {1, 6, 11, 0, 5, 10, 15, 4, 9, 14, 3, 8, 13, 2, 7, 12};
uint32_t __k3[] = {5, 8, 11, 14, 1, 4, 7, 10, 13, 0, 3, 6, 9, 12, 15, 2};
uint32_t __k4[] = {0, 7, 14, 5, 12, 3, 10, 1, 8, 15, 6, 13, 4, 11, 2, 9};
Code: Select all
#include <math.h>
#include <time.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n))))
#define F(x,y,z) (((x) & (y)) | ((~(x)) & (z)))
#define G(x,y,z) (((x) & (z)) | ((y) & (~(z))))
#define H(x,y,z) ((x) ^ (y) ^ (z))
#define I(x,y,z) ((y) ^ ((x) | (~(z))))
void md5_genT(uint32_t *T)
{
uint_fast32_t i;
for(i = 0; i < 64; ++i) {
T[i] = (uint32_t)(4294967296.0 * fabs(sin((float)(i+1))));
//printf("%08x\n", T[i]);
//sleep(1);
}
}
#define unroll
void md5_hash(uint8_t *message, uint_fast32_t mlength, uint32_t *T, unsigned char * digest)
{
uint8_t nmlength;
static const uint32_t __s1[] = {7, 12, 17, 22};
static const uint32_t __s2[] = {5, 9, 14, 20};
static const uint32_t __s3[] = {4, 11, 16, 23};
static const uint32_t __s4[] = {6, 10, 15, 21};
static const uint32_t __k1[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15};
static const uint32_t __k2[] = {1, 6, 11, 0, 5, 10, 15, 4, 9, 14, 3, 8, 13, 2, 7, 12};
static const uint32_t __k3[] = {5, 8, 11, 14, 1, 4, 7, 10, 13, 0, 3, 6, 9, 12, 15, 2};
static const uint32_t __k4[] = {0, 7, 14, 5, 12, 3, 10, 1, 8, 15, 6, 13, 4, 11, 2, 9};
// uint32_t X[16];
uint32_t *X;
uint32_t i, j, ii, k;
uint32_t AA, BB, CC, DD;
uint32_t A, B, C, D;
// do padding so message is a multiple of 512 bits (64 bytes)
if((mlength%64) == 0)
{
nmlength = mlength + 64;
}else{
nmlength = mlength + (64 - (mlength%64));
}
uint8_t nm[nmlength+1];
//nm = (uint8_t*)malloc(nmlength);
memcpy(nm, message, mlength);
memset(&nm[mlength], 0, nmlength-mlength);
nm[mlength] = 0x80;
((uint32_t*)&nm[nmlength - 8])[0] = mlength * 8;
((uint32_t*)&nm[nmlength - 8])[1] = 0;
// hash padded message (nmessage)
AA = 0x67452301; BB = 0xefcdab89; CC = 0x98badcfe; DD = 0x10325476;
for(i = 0; i < (nmlength/64); ++i)
{
// create table
// for(j = 0; j < 16; j++) {
// X[j] = *(int *)&nm[i * 64 + j * 4];
// }
X = (uint32_t *)&nm[i * 64];
A = AA;
B = BB;
C = CC;
D = DD;
#ifdef unroll
/// round one (unrolled)
A = B + ROTATE_LEFT((A + F(B, C, D) + X[0] + 0xd76aa478), __s1[0]);
D = A + ROTATE_LEFT((D + F(A, B, C) + X[1] + 0xe8c7b756), __s1[1]);
C = D + ROTATE_LEFT((C + F(D, A, B) + X[2] + 0x242070db), __s1[2]);
B = C + ROTATE_LEFT((B + F(C, D, A) + X[3] + 0xc1bdceee), __s1[3]);
A = B + ROTATE_LEFT((A + F(B, C, D) + X[4] + 0xf57c0faf), __s1[0]);
D = A + ROTATE_LEFT((D + F(A, B, C) + X[5] + 0x4787c62a), __s1[1]);
C = D + ROTATE_LEFT((C + F(D, A, B) + X[6] + 0xa8304613), __s1[2]);
B = C + ROTATE_LEFT((B + F(C, D, A) + X[7] + 0xfd469501), __s1[3]);
A = B + ROTATE_LEFT((A + F(B, C, D) + X[8] + 0x698098d8), __s1[0]);
D = A + ROTATE_LEFT((D + F(A, B, C) + X[9] + 0x8b44f7af), __s1[1]);
C = D + ROTATE_LEFT((C + F(D, A, B) + X[10] + 0xffff5bb1), __s1[2]);
B = C + ROTATE_LEFT((B + F(C, D, A) + X[11] + 0x895cd7be), __s1[3]);
A = B + ROTATE_LEFT((A + F(B, C, D) + X[12] + 0x6b901122), __s1[0]);
D = A + ROTATE_LEFT((D + F(A, B, C) + X[13] + 0xfd987193), __s1[1]);
C = D + ROTATE_LEFT((C + F(D, A, B) + X[14] + 0xa679438e), __s1[2]);
B = C + ROTATE_LEFT((B + F(C, D, A) + X[15] + 0x49b40821), __s1[3]);
/// round two (unrolled)
A = B + ROTATE_LEFT((A + G(B, C, D) + X[1] + 0xf61e2562), __s2[0]);
D = A + ROTATE_LEFT((D + G(A, B, C) + X[6] + 0xc040b340), __s2[1]);
C = D + ROTATE_LEFT((C + G(D, A, B) + X[11] + 0x265e5a51), __s2[2]);
B = C + ROTATE_LEFT((B + G(C, D, A) + X[0] + 0xe9b6c7aa), __s2[3]);
A = B + ROTATE_LEFT((A + G(B, C, D) + X[5] + 0xd62f105d), __s2[0]);
D = A + ROTATE_LEFT((D + G(A, B, C) + X[10] + 0x02441453), __s2[1]);
C = D + ROTATE_LEFT((C + G(D, A, B) + X[15] + 0xd8a1e681), __s2[2]);
B = C + ROTATE_LEFT((B + G(C, D, A) + X[4] + 0xe7d3fbc8), __s2[3]);
A = B + ROTATE_LEFT((A + G(B, C, D) + X[9] + 0x21e1cde6), __s2[0]);
D = A + ROTATE_LEFT((D + G(A, B, C) + X[14] + 0xc33707d6), __s2[1]);
C = D + ROTATE_LEFT((C + G(D, A, B) + X[3] + 0xf4d50d87), __s2[2]);
B = C + ROTATE_LEFT((B + G(C, D, A) + X[8] + 0x455a14ed), __s2[3]);
A = B + ROTATE_LEFT((A + G(B, C, D) + X[13] + 0xa9e3e905), __s2[0]);
D = A + ROTATE_LEFT((D + G(A, B, C) + X[2] + 0xfcefa3f8), __s2[1]);
C = D + ROTATE_LEFT((C + G(D, A, B) + X[7] + 0x676f02d9), __s2[2]);
B = C + ROTATE_LEFT((B + G(C, D, A) + X[12] + 0x8d2a4c8a), __s2[3]);
/// round three (unrolled)
A = B + ROTATE_LEFT((A + H(B, C, D) + X[5] + 0xfffa3942), __s3[0]);
D = A + ROTATE_LEFT((D + H(A, B, C) + X[8] + 0x8771f681), __s3[1]);
C = D + ROTATE_LEFT((C + H(D, A, B) + X[11] + 0x6d9d6122), __s3[2]);
B = C + ROTATE_LEFT((B + H(C, D, A) + X[14] + 0xfde5380c), __s3[3]);
A = B + ROTATE_LEFT((A + H(B, C, D) + X[1] + 0xa4beea44), __s3[0]);
D = A + ROTATE_LEFT((D + H(A, B, C) + X[4] + 0x4bdecfa9), __s3[1]);
C = D + ROTATE_LEFT((C + H(D, A, B) + X[7] + 0xf6bb4b60), __s3[2]);
B = C + ROTATE_LEFT((B + H(C, D, A) + X[10] + 0xbebfbc70), __s3[3]);
A = B + ROTATE_LEFT((A + H(B, C, D) + X[13] + 0x289b7ec6), __s3[0]);
D = A + ROTATE_LEFT((D + H(A, B, C) + X[0] + 0xeaa127fa), __s3[1]);
C = D + ROTATE_LEFT((C + H(D, A, B) + X[3] + 0xd4ef3085), __s3[2]);
B = C + ROTATE_LEFT((B + H(C, D, A) + X[6] + 0x04881d05), __s3[3]);
A = B + ROTATE_LEFT((A + H(B, C, D) + X[9] + 0xd9d4d039), __s3[0]);
D = A + ROTATE_LEFT((D + H(A, B, C) + X[12] + 0xe6db99e5), __s3[1]);
C = D + ROTATE_LEFT((C + H(D, A, B) + X[15] + 0x1fa27cf8), __s3[2]);
B = C + ROTATE_LEFT((B + H(C, D, A) + X[2] + 0xc4ac5665), __s3[3]);
/// round four (unrolled)
A = B + ROTATE_LEFT((A + I(B, C, D) + X[0] + 0xf4292244), __s4[0]);
D = A + ROTATE_LEFT((D + I(A, B, C) + X[7] + 0x432aff97), __s4[1]);
C = D + ROTATE_LEFT((C + I(D, A, B) + X[14] + 0xab9423a7), __s4[2]);
B = C + ROTATE_LEFT((B + I(C, D, A) + X[5] + 0xfc93a039), __s4[3]);
A = B + ROTATE_LEFT((A + I(B, C, D) + X[12] + 0x655b59c3), __s4[0]);
D = A + ROTATE_LEFT((D + I(A, B, C) + X[3] + 0x8f0ccc92), __s4[1]);
C = D + ROTATE_LEFT((C + I(D, A, B) + X[10] + 0xffeff47d), __s4[2]);
B = C + ROTATE_LEFT((B + I(C, D, A) + X[1] + 0x85845dd1), __s4[3]);
A = B + ROTATE_LEFT((A + I(B, C, D) + X[8] + 0x6fa87e4f), __s4[0]);
D = A + ROTATE_LEFT((D + I(A, B, C) + X[15] + 0xfe2ce6e0), __s4[1]);
C = D + ROTATE_LEFT((C + I(D, A, B) + X[6] + 0xa3014314), __s4[2]);
B = C + ROTATE_LEFT((B + I(C, D, A) + X[13] + 0x4e0811a1), __s4[3]);
A = B + ROTATE_LEFT((A + I(B, C, D) + X[4] + 0xf7537e82), __s4[0]);
D = A + ROTATE_LEFT((D + I(A, B, C) + X[11] + 0xbd3af235), __s4[1]);
C = D + ROTATE_LEFT((C + I(D, A, B) + X[2] + 0x2ad7d2bb), __s4[2]);
B = C + ROTATE_LEFT((B + I(C, D, A) + X[9] + 0xeb86d391), __s4[3]);
#else
ii = 0;
// round one
for(k = 0; k < 4; ++k)
{
A = B + ROTATE_LEFT((A + F(B, C, D) + X[__k1[k*4+0]] + T[ii+0]), __s1[0]);
D = A + ROTATE_LEFT((D + F(A, B, C) + X[__k1[k*4+1]] + T[ii+1]), __s1[1]);
C = D + ROTATE_LEFT((C + F(D, A, B) + X[__k1[k*4+2]] + T[ii+2]), __s1[2]);
B = C + ROTATE_LEFT((B + F(C, D, A) + X[__k1[k*4+3]] + T[ii+3]), __s1[3]);
ii += 4;
}
// round two
for(k = 0; k < 4; ++k)
{
A = B + ROTATE_LEFT((A + G(B, C, D) + X[__k2[k*4+0]] + T[ii+0]), __s2[0]);
D = A + ROTATE_LEFT((D + G(A, B, C) + X[__k2[k*4+1]] + T[ii+1]), __s2[1]);
C = D + ROTATE_LEFT((C + G(D, A, B) + X[__k2[k*4+2]] + T[ii+2]), __s2[2]);
B = C + ROTATE_LEFT((B + G(C, D, A) + X[__k2[k*4+3]] + T[ii+3]), __s2[3]);
ii += 4;
}
// round three
for(k = 0; k < 4; ++k)
{
A = B + ROTATE_LEFT((A + H(B, C, D) + X[__k3[k*4+0]] + T[ii+0]), __s3[0]);
D = A + ROTATE_LEFT((D + H(A, B, C) + X[__k3[k*4+1]] + T[ii+1]), __s3[1]);
C = D + ROTATE_LEFT((C + H(D, A, B) + X[__k3[k*4+2]] + T[ii+2]), __s3[2]);
B = C + ROTATE_LEFT((B + H(C, D, A) + X[__k3[k*4+3]] + T[ii+3]), __s3[3]);
ii += 4;
}
// round four
for(k = 0; k < 4; ++k)
{
A = B + ROTATE_LEFT((A + I(B, C, D) + X[__k4[k*4+0]] + T[ii+0]), __s4[0]);
D = A + ROTATE_LEFT((D + I(A, B, C) + X[__k4[k*4+1]] + T[ii+1]), __s4[1]);
C = D + ROTATE_LEFT((C + I(D, A, B) + X[__k4[k*4+2]] + T[ii+2]), __s4[2]);
B = C + ROTATE_LEFT((B + I(C, D, A) + X[__k4[k*4+3]] + T[ii+3]), __s4[3]);
ii += 4;
}
#endif
AA = AA + A;
BB = BB + B;
CC = CC + C;
DD = DD + D;
}
*((int*)(&digest[ 0])) = AA;
*((int*)(&digest[ 4])) = BB;
*((int*)(&digest[ 8])) = CC;
*((int*)(&digest[12])) = DD;
return;
}
int do_next_sequence(char *sequence, int charset_length, int length);
int main(int argc, char *argv[])
{
int x, len, t;
clock_t start,end;
float dif;
int loops = 0;
char *sequence;
char *message;
char temp[2];
char charset[] = {'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k',
'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
'w', 'x', 'y', 'z'}; // lower_alpha
uint32_t T[64];
uint32_t Ti[64];
md5_genT(&Ti[0]);
unsigned char digest[16];
unsigned char raw_inhash[16];
if( argc < 3 )
return 1;
len = atoi( argv[2] );
sequence = (char *)malloc( len );
message = (char *)malloc( len );
memset(sequence, 0, len);
for(t = 0; t < 16; t++)
{
sscanf(&argv[1][t*2], "%2x", &raw_inhash[t]);
}
start = clock();
while( do_next_sequence(sequence, sizeof(charset), len) )
{
for(x = len-1; x >= 0; --x) {
message[x] = charset[sequence[x]];
}
message[len] = 0;
// START md5 string: input message
memcpy(&T[0], &Ti[0], 256);
md5_hash((uint8_t*)message, len, &T[0], digest);
// END md5 string: output digest
loops++;
if(*(int *)raw_inhash == *(int *)digest) {
if( memcmp( raw_inhash, digest, 16 ) == 0 )
{
end = clock();
dif = (end - start);
dif /= CLOCKS_PER_SEC;
printf("Collision Found!: %s is : %s\n Cracking took: %.2lfs\n Average h/s: %.2f h/s\n", argv[1], message, dif, (loops / dif));
return 0;
}
}
}
puts("No collision Found\n");
return 1;
}
int do_next_sequence(char *sequence, int charset_length, int length)
{
int x;
for(x = 0; sequence[x] == (charset_length-1); ++x)
{
if(x == (length-1))
{
return 0;
}
sequence[x] = 0;
}
++sequence[x];
return 1;
}