|
You are right, my comments should have been limited to short passwords only. For a strong password brute force could take ~800 years. The hacker may assume the password has certain characteristics... I don't know what they do. If you hide your method (adding secret-text to input password) it makes trial and error even harder. I guess it depends on how paranoid the programmer is.
|
|
|
|
|
Thought you like to know, "A" to "zzzzzzzz", using the roughly 90 readable keyboard keys (4304672100000000 combos), and computing 1 million MD5 digests per second(good MD5 implimentation on multi ghz box), it'll still take you 136 years to go through all combinations.
|
|
|
|
|
(continuing thread @ 2004)
what if I tell u I have all 4304672100000000 combos stored on my PC and a single sql table lookup can retrieve your password immediately? of course for that to happen, I have to spend $20Million to buy thousands of harddisks.
|
|
|
|
|
see http://www.langfine.com/rsa_md5.htm
|
|
|
|
|
Revision from MD5 original code, you can digest BINARY file (Napster MP3) and password string(MSN Messenger authentication)
Usage:
CString szBuf;
CMD5 md5;
unsigned char digest[16];
unsigned char szPassword[40];
sscanf(lpszParam, "MD5 S %s", (char *)szPassword);
lstrcat((char *)szPassword, m_szPassword);
md5.MD5Init();
md5.MD5Update((unsigned char *)szPassword, lstrlen((LPCSTR)szPassword));
md5.MD5Final(digest);
szBuf.Format(_T("%s S %s"), m_szSecurityPackage, HexToString((LPCTSTR)digest));
m_MSNSock.MSNSend("USR", szBuf);
|
|
|
|
|
// MD5.h: interface for the CMD5 class.
//
//////////////////////////////////////////////////////////////////////
#if !defined(AFX_MD5_H__8F46026A_1138_4441_BE43_CB9189B1CEEB__INCLUDED_)
#define AFX_MD5_H__8F46026A_1138_4441_BE43_CB9189B1CEEB__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
/* UINT4 defines a four byte word */
typedef unsigned long int UINT4;
class CMD5
{
public:
/* MD5 context. */
typedef struct {
unsigned long int state[4]; /* state (ABCD) */
unsigned long int count[2]; /* number of bits, modulo 2^64 (lsb first) */
unsigned char buffer[64]; /* input buffer */
} MD5_CTX;
public:
CMD5();
virtual ~CMD5();
public:
void MD5Init();
void MD5Update( unsigned char *input, /* input block */
unsigned int inputLen /* length of input block */);
void MD5Final(unsigned char digest[16] /* message digest */);
protected:
void MD5Transform(UINT4 [4], unsigned char [64]);
void Encode(unsigned char *, UINT4 *, unsigned int);
void Decode(UINT4 *, unsigned char *, unsigned int);
private:
MD5_CTX m_context;
};
|
|
|
|
|
#include "stdafx.h"
#include "MSNClient.h"
#include "MD5.h"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
/* Constants for MD5Transform routine. */
#define S11 7
#define S12 12
#define S13 17
#define S14 22
#define S21 5
#define S22 9
#define S23 14
#define S24 20
#define S31 4
#define S32 11
#define S33 16
#define S34 23
#define S41 6
#define S42 10
#define S43 15
#define S44 21
/* F, G, H and I are basic MD5 functions. */
#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)))
/* ROTATE_LEFT rotates x left n bits. */
#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n))))
/* FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4.
Rotation is separate from addition to prevent recomputation.
*/
#define FF(a, b, c, d, x, s, ac) { \
(a) += F ((b), (c), (d)) + (x) + (UINT4)(ac); \
(a) = ROTATE_LEFT ((a), (s)); \
(a) += (b); \
}
#define GG(a, b, c, d, x, s, ac) { \
(a) += G ((b), (c), (d)) + (x) + (UINT4)(ac); \
(a) = ROTATE_LEFT ((a), (s)); \
(a) += (b); \
}
#define HH(a, b, c, d, x, s, ac) { \
(a) += H ((b), (c), (d)) + (x) + (UINT4)(ac); \
(a) = ROTATE_LEFT ((a), (s)); \
(a) += (b); \
}
#define II(a, b, c, d, x, s, ac) { \
(a) += I ((b), (c), (d)) + (x) + (UINT4)(ac); \
(a) = ROTATE_LEFT ((a), (s)); \
(a) += (b); \
}
static unsigned char PADDING[64] = {
0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CMD5::CMD5()
{
}
CMD5::~CMD5()
{
}
/* MD5 initialization. Begins an MD5 operation, writing a new context.
*/
void CMD5::MD5Init()
{
m_context.count[0] = m_context.count[1] = 0;
/* Load magic initialization constants. */
m_context.state[0] = 0x67452301;
m_context.state[1] = 0xefcdab89;
m_context.state[2] = 0x98badcfe;
m_context.state[3] = 0x10325476;
}
/* MD5 block update operation. Continues an MD5 message-digest
operation, processing another message block, and updating the
context.
*/
void CMD5::MD5Update (
unsigned char *input, /* input block */
unsigned int inputLen /* length of input block */
)
{
unsigned int i, index, partLen;
/* Compute number of bytes mod 64 */
index = (unsigned int)((m_context.count[0] >> 3) & 0x3F);
/* Update number of bits */
if ((m_context.count[0] += ((UINT4)inputLen << 3))
< ((UINT4)inputLen << 3))
m_context.count[1]++;
m_context.count[1] += ((UINT4)inputLen >> 29);
partLen = 64 - index;
/* Transform as many times as possible.
*/
if (inputLen >= partLen)
{
memcpy(&m_context.buffer[index], input, partLen);
MD5Transform (m_context.state, m_context.buffer);
for (i = partLen; i + 63 < inputLen; i += 64)
MD5Transform (m_context.state, &input[i]);
index = 0;
}
else
i = 0;
/* Buffer remaining input */
memcpy(&m_context.buffer[index], &input[i], inputLen-i);
}
/* MD5 finalization. Ends an MD5 message-digest operation, writing the
the message digest and zeroizing the context.
*/
void CMD5::MD5Final(
unsigned char digest[16] /* message digest */
)
{
unsigned char bits[8];
unsigned int index, padLen;
/* Save number of bits */
Encode (bits, m_context.count, 8);
/* Pad out to 56 mod 64.
*/
index = (unsigned int)((m_context.count[0] >> 3) & 0x3f);
padLen = (index < 56) ? (56 - index) : (120 - index);
MD5Update(PADDING, padLen);
/* Append length (before padding) */
MD5Update(bits, 8);
/* Store state in digest */
Encode(digest, m_context.state, 16);
/* Zeroize sensitive information.
*/
memset(&m_context, 0, sizeof(m_context));
}
|
|
|
|
|
/* MD5 basic transformation. Transforms state based on block.
*/
void CMD5::MD5Transform(
UINT4 state[4],
unsigned char block[64]
)
{
UINT4 a = state[0], b = state[1], c = state[2], d = state[3], x[16];
Decode (x, block, 64);
/* Round 1 */
FF (a, b, c, d, x[ 0], S11, 0xd76aa478); /* 1 */
FF (d, a, b, c, x[ 1], S12, 0xe8c7b756); /* 2 */
FF (c, d, a, b, x[ 2], S13, 0x242070db); /* 3 */
FF (b, c, d, a, x[ 3], S14, 0xc1bdceee); /* 4 */
FF (a, b, c, d, x[ 4], S11, 0xf57c0faf); /* 5 */
FF (d, a, b, c, x[ 5], S12, 0x4787c62a); /* 6 */
FF (c, d, a, b, x[ 6], S13, 0xa8304613); /* 7 */
FF (b, c, d, a, x[ 7], S14, 0xfd469501); /* 8 */
FF (a, b, c, d, x[ 8], S11, 0x698098d8); /* 9 */
FF (d, a, b, c, x[ 9], S12, 0x8b44f7af); /* 10 */
FF (c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */
FF (b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */
FF (a, b, c, d, x[12], S11, 0x6b901122); /* 13 */
FF (d, a, b, c, x[13], S12, 0xfd987193); /* 14 */
FF (c, d, a, b, x[14], S13, 0xa679438e); /* 15 */
FF (b, c, d, a, x[15], S14, 0x49b40821); /* 16 */
/* Round 2 */
GG (a, b, c, d, x[ 1], S21, 0xf61e2562); /* 17 */
GG (d, a, b, c, x[ 6], S22, 0xc040b340); /* 18 */
GG (c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */
GG (b, c, d, a, x[ 0], S24, 0xe9b6c7aa); /* 20 */
GG (a, b, c, d, x[ 5], S21, 0xd62f105d); /* 21 */
GG (d, a, b, c, x[10], S22, 0x2441453); /* 22 */
GG (c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */
GG (b, c, d, a, x[ 4], S24, 0xe7d3fbc8); /* 24 */
GG (a, b, c, d, x[ 9], S21, 0x21e1cde6); /* 25 */
GG (d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */
GG (c, d, a, b, x[ 3], S23, 0xf4d50d87); /* 27 */
GG (b, c, d, a, x[ 8], S24, 0x455a14ed); /* 28 */
GG (a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */
GG (d, a, b, c, x[ 2], S22, 0xfcefa3f8); /* 30 */
GG (c, d, a, b, x[ 7], S23, 0x676f02d9); /* 31 */
GG (b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */
/* Round 3 */
HH (a, b, c, d, x[ 5], S31, 0xfffa3942); /* 33 */
HH (d, a, b, c, x[ 8], S32, 0x8771f681); /* 34 */
HH (c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */
HH (b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */
HH (a, b, c, d, x[ 1], S31, 0xa4beea44); /* 37 */
HH (d, a, b, c, x[ 4], S32, 0x4bdecfa9); /* 38 */
HH (c, d, a, b, x[ 7], S33, 0xf6bb4b60); /* 39 */
HH (b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */
HH (a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */
HH (d, a, b, c, x[ 0], S32, 0xeaa127fa); /* 42 */
HH (c, d, a, b, x[ 3], S33, 0xd4ef3085); /* 43 */
HH (b, c, d, a, x[ 6], S34, 0x4881d05); /* 44 */
HH (a, b, c, d, x[ 9], S31, 0xd9d4d039); /* 45 */
HH (d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */
HH (c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */
HH (b, c, d, a, x[ 2], S34, 0xc4ac5665); /* 48 */
/* Round 4 */
II (a, b, c, d, x[ 0], S41, 0xf4292244); /* 49 */
II (d, a, b, c, x[ 7], S42, 0x432aff97); /* 50 */
II (c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */
II (b, c, d, a, x[ 5], S44, 0xfc93a039); /* 52 */
II (a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */
II (d, a, b, c, x[ 3], S42, 0x8f0ccc92); /* 54 */
II (c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */
II (b, c, d, a, x[ 1], S44, 0x85845dd1); /* 56 */
II (a, b, c, d, x[ 8], S41, 0x6fa87e4f); /* 57 */
II (d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */
II (c, d, a, b, x[ 6], S43, 0xa3014314); /* 59 */
II (b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */
II (a, b, c, d, x[ 4], S41, 0xf7537e82); /* 61 */
II (d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */
II (c, d, a, b, x[ 2], S43, 0x2ad7d2bb); /* 63 */
II (b, c, d, a, x[ 9], S44, 0xeb86d391); /* 64 */
state[0] += a;
state[1] += b;
state[2] += c;
state[3] += d;
/* Zeroize sensitive information. */
memset(x, 0, sizeof (x));
}
/* Encodes input (UINT4) into output (unsigned char). Assumes len is
a multiple of 4.
*/
void CMD5::Encode(
unsigned char *output,
UINT4 *input,
unsigned int len
)
{
unsigned int i, j;
for (i = 0, j = 0; j < len; i++, j += 4)
{
output[j] = (unsigned char)(input[i] & 0xff);
output[j+1] = (unsigned char)((input[i] >> 8) & 0xff);
output[j+2] = (unsigned char)((input[i] >> 16) & 0xff);
output[j+3] = (unsigned char)((input[i] >> 24) & 0xff);
}
}
/* Decodes input (unsigned char) into output (UINT4). Assumes len is
a multiple of 4.
*/
void CMD5::Decode(
UINT4 *output,
unsigned char *input,
unsigned int len
)
{
unsigned int i, j;
for (i = 0, j = 0; j < len; i++, j += 4)
output[i] = ((UINT4)input[j]) | (((UINT4)input[j+1]) << 8) |
(((UINT4)input[j+2]) << 16) | (((UINT4)input[j+3]) << 24);
}
|
|
|
|
|
If the length of input string can't exceed 64?
and where is the output string?thank you.
|
|
|
|
|
Hi all,
Your class is cool, but im having problems to use it with and MFC project like an DLL or OCX control, its seems that only works in Win32 Application.
When the class MD5class.cpp is complied an error is generated with following message:
error:"unexpected end of file while looking for precompiled header directive"
I want to know what im doing wrong.
PS: Im using the Microsoft Visual C/C++ 6.0 compiler.
|
|
|
|
|
hi, It is easy to help you.
only add #include "stdafx.h" in your error file's head
That is ok.
|
|
|
|
|
However, by do so, there is another error as below,
>>
"d:\project\passwordtest\md5c.c(5) : fatal error C1853: 'Debug/PasswordTest.pch' is not a precompiled header file created with this compiler"
Can anybody help to tackle it ?
Thanks in Advance!;P
|
|
|
|
|
In VC6 go to your project settings, and under the 'C/C++' tab select 'Precompiled Headers'.
Click on the radio button for either "not using precompiled headers" or "automatic use of precompiled headers".
That ought to let you compile it.
|
|
|
|
|
project->settings->c/c++->precompiled headers->Not using precompiled headers.
Greetz, plinius.
|
|
|
|
|
Hi all,
Your class is cool, but im having problems to use it with and MFC project like an DLL or OCX control, its seems that only works in Win32 Application.
When the class MD5class.cpp is complied an error is generated with following message:
error:"unexpected end of file while looking for precompiled header directive"
I want to know what im doing wrong.
PS: Im using the Microsoft Visual C/C++ 6.0 compiler.
|
|
|
|
|
Probably something to do with the file options in the project. You can tell them not to use PCH files or you could include stdafx.h in the file causing the trouble.
I often find this message goes away with a rebuild all.
|
|
|
|
|
In this case we are combining C++ and C code, so just adding '#include stdafx.h' to md5class.cpp is nessasary but not sufficent.
To use this code in an Appwizard project, on the Visual Studio menu go to C++ -> catagory "precompiled headers". Select "automatic use of precompiled headers through header: stdafx.h" for all configurations.
"Rebuild all" and the problem should be fixed.
I'm going to update the article to include an MFC sample in the near future.
|
|
|
|
|
As it has been suggested, the error you are getting is because you have not included your precompiled header file (generally stdafx.h) from the MD5class.cpp file.
|
|
|
|
|
The download link has been fixed. There was a problem with my connection half way through posting the article and I was unable to complete the upload.
These things happen - the article should be considered on its own merits and not based on my connection problems!
cheers,
Chris Maunder
|
|
|
|
|
|
|