一个极速MD5实现的代码

mmit 2020-12-20 01:00:53

//原始代码是网上找的,但存在问题,代码有缺句,而且处理的数据长度有限制
//已完善代码,解决了数据长度限制的问题
//注意汇编宏代码行末的\之后不能有任何内容,否则会影响展开,在这点上吃过亏,特此提醒一下。

#include <vcl.h>

struct MD5_CTX {
unsigned int state[4]; //encypted message context. state[0]是32位的无符号整数,注意内存字节顺序
unsigned long long count;
char str[33] = {0} ;
unsigned char buffer[64];
};

#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

#define a esi
#define b edi
#define c edx
#define d ebx
#define tmp1 eax
#define tmp2 ecx

#define x(i) [x+4*i]

#define FF(a, b, c, d, x, s, ac) \
__asm mov tmp1,b \
__asm and tmp1,c \
__asm mov tmp2,b \
__asm not tmp2 \
__asm and tmp2,d \
__asm or tmp2,tmp1 \
__asm lea a,[tmp2+a+ac] \
__asm add a,x \
__asm rol a,s \
__asm add a,b

#define GG(a, b, c, d, x, s, ac) \
__asm mov tmp1,b \
__asm and tmp1,d \
__asm mov tmp2,d \
__asm not tmp2 \
__asm and tmp2,c \
__asm or tmp2,tmp1 \
__asm lea a,[tmp2+a+ac] \
__asm add a,x \
__asm rol a,s \
__asm add a,b

#define HH(a,b,c, d, x, s, ac) \
__asm mov tmp2,b \
__asm xor tmp2,c \
__asm xor tmp2,d \
__asm lea a,[tmp2+a+ac] \
__asm add a,x \
__asm rol a,s \
__asm add a,b

#define II(a, b, c, d, x, s, ac) \
__asm mov tmp2,d \
__asm not tmp2 \
__asm or tmp2,b \
__asm xor tmp2,c \
__asm lea a,[tmp2+a+ac] \
__asm add a,x \
__asm rol a,s \
__asm add 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
};

static void MD5Transform (unsigned int *state, unsigned char *block)
{
DWORD x[16];
__asm
{
mov tmp1, DWORD PTR [state]
mov a, DWORD PTR [tmp1]
mov b, DWORD PTR [tmp1+4]
mov c, DWORD PTR [tmp1+8]
mov d, DWORD PTR [tmp1+12]

push esi
push edi

xor ecx, ecx
mov esi, DWORD PTR [block]
lea edi, [x]
ROLL:
mov eax, DWORD PTR [esi+ecx]
mov DWORD PTR [edi+ecx], eax
add ecx, 4
cmp ecx, 64
jb ROLL

pop edi
pop esi
}

// Round 1
FF (a, b, c, d, x(0), S11, 0xd76aa478);
FF (d, a, b, c, x(1), S12, 0xe8c7b756);
FF (c, d, a, b, x(2), S13, 0x242070db);
FF (b, c, d, a, x(3), S14, 0xc1bdceee);
FF (a, b, c, d, x(4), S11, 0xf57c0faf);
FF (d, a, b, c, x(5), S12, 0x4787c62a);
FF (c, d, a, b, x(6), S13, 0xa8304613);
FF (b, c, d, a, x(7), S14, 0xfd469501);
FF (a, b, c, d, x(8), S11, 0x698098d8);
FF (d, a, b, c, x(9), S12, 0x8b44f7af);
FF (c, d, a, b, x(10), S13, 0xffff5bb1);
FF (b, c, d, a, x(11), S14, 0x895cd7be);
FF (a, b, c, d, x(12), S11, 0x6b901122);
FF (d, a, b, c, x(13), S12, 0xfd987193);
FF (c, d, a, b, x(14), S13, 0xa679438e);
FF (b, c, d, a, x(15), S14, 0x49b40821);

// Round 2
GG (a, b, c, d, x(1), S21, 0xf61e2562);
GG (d, a, b, c, x(6), S22, 0xc040b340);
GG (c, d, a, b, x(11), S23, 0x265e5a51);
GG (b, c, d, a, x(0), S24, 0xe9b6c7aa);
GG (a, b, c, d, x(5), S21, 0xd62f105d);
GG (d, a, b, c, x(10), S22, 0x2441453);
GG (c, d, a, b, x(15), S23, 0xd8a1e681);
GG (b, c, d, a, x(4), S24, 0xe7d3fbc8);
GG (a, b, c, d, x(9), S21, 0x21e1cde6);
GG (d, a, b, c, x(14), S22, 0xc33707d6);
GG (c, d, a, b, x(3), S23, 0xf4d50d87);
GG (b, c, d, a, x(8), S24, 0x455a14ed);
GG (a, b, c, d, x(13), S21, 0xa9e3e905);
GG (d, a, b, c, x(2), S22, 0xfcefa3f8);
GG (c, d, a, b, x(7), S23, 0x676f02d9);
GG (b, c, d, a, x(12), S24, 0x8d2a4c8a);

// Round 3
HH (a, b, c, d, x(5), S31, 0xfffa3942);
HH (d, a, b, c, x(8), S32, 0x8771f681);
HH (c, d, a, b, x(11), S33, 0x6d9d6122);
HH (b, c, d, a, x(14), S34, 0xfde5380c);
HH (a, b, c, d, x(1), S31, 0xa4beea44);
HH (d, a, b, c, x(4), S32, 0x4bdecfa9);
HH (c, d, a, b, x(7), S33, 0xf6bb4b60);
HH (b, c, d, a, x(10), S34, 0xbebfbc70);
HH (a, b, c, d, x(13), S31, 0x289b7ec6);
HH (d, a, b, c, x(0), S32, 0xeaa127fa);
HH (c, d, a, b, x(3), S33, 0xd4ef3085);
HH (b, c, d, a, x(6), S34, 0x4881d05);
HH (a, b, c, d, x(9), S31, 0xd9d4d039);
HH (d, a, b, c, x(12), S32, 0xe6db99e5);
HH (c, d, a, b, x(15), S33, 0x1fa27cf8);
HH (b, c, d, a, x(2), S34, 0xc4ac5665);

// Round 4
II (a, b, c, d, x(0), S41, 0xf4292244);
II (d, a, b, c, x(7), S42, 0x432aff97);
II (c, d, a, b, x(14), S43, 0xab9423a7);
II (b, c, d, a, x(5), S44, 0xfc93a039);
II (a, b, c, d, x(12), S41, 0x655b59c3);
II (d, a, b, c, x(3), S42, 0x8f0ccc92);
II (c, d, a, b, x(10), S43, 0xffeff47d);
II (b, c, d, a, x(1), S44, 0x85845dd1);
II (a, b, c, d, x(8), S41, 0x6fa87e4f);
II (d, a, b, c, x(15), S42, 0xfe2ce6e0);
II (c, d, a, b, x(6), S43, 0xa3014314);
II (b, c, d, a, x(13), S44, 0x4e0811a1);
II (a, b, c, d, x(4), S41, 0xf7537e82);
II (d, a, b, c, x(11), S42, 0xbd3af235);
II (c, d, a, b, x(2), S43, 0x2ad7d2bb);
II (b, c, d, a, x(9), S44, 0xeb86d391);

__asm
{
mov tmp1, DWORD PTR [state]
add DWORD PTR [tmp1], a
add DWORD PTR [tmp1+4], b
add DWORD PTR [tmp1+8], c
add DWORD PTR [tmp1+12], d
}
}

static void MD5Init (MD5_CTX &context)
{
context.count = 0;
context.state[0] = 0x67452301;
context.state[1] = 0xefcdab89;
context.state[2] = 0x98badcfe;
context.state[3] = 0x10325476;
}

static void MD5Update (MD5_CTX &context, unsigned char *in, unsigned int inLen)
{
unsigned int i, index, partLen ;

index = (context.count >> 3) & 0x3Full ; //此前已读入的数据字节数模除64,得出不足64字节的部分,此部分应在此前存入buffer
context.count += (inLen << 3) ; //加本次新增的数据比特位数(字节数*8)
partLen = 64 - index; //64字节buffer剩余空间

if (inLen < partLen) i = 0 ;
else {
CopyMemory (&context.buffer[index], in, partLen) ; //先装满buffer,最后一次Final会确保装满
MD5Transform (context.state, context.buffer) ; //装满后运算之
index = 0 ; //索引复位
for (i = partLen; i + 63 < inLen; i += 64) MD5Transform (context.state, in + i) ; //如果后续字节满64,则继续运算之
}
CopyMemory (&context.buffer[index], in + i, inLen - i); //不足64字节的部分读入buffer,待MD5Final时运算
}

static void MD5Final (MD5_CTX &context)
{
unsigned int index, padLen ;
unsigned long long bits = context.count ;
index = (context.count >> 3) & 0x3Full ;
padLen = (index < 56) ? (56 - index) : (120 - index) ;
MD5Update (context, PADDING, padLen); //填充一个2进制的1和若干个0使其长度模512与448同余
MD5Update (context, (unsigned char*)&bits, 8); //数据的真实长度以64bit表示附加在填充结果后面
unsigned char* p = (unsigned char*)context.state ; //将数值解码为字符串
for (int i = 0; i < 16; i++) {
unsigned char j ;
j = p[i] & 0xF ; if (j < 10) context.str[i*2+1] = j + '0' ; else context.str[i*2+1] = j - 10 + 'a' ; //需要大写MD5码将此处的a改为A即可
j = p[i] >> 4 ; if (j < 10) context.str[i*2] = j + '0' ; else context.str[i*2] = j - 10 + 'a' ;
}
}
//========================================================================
//以下是用于C++builder的封装,不用可以连同文件首行的 #include <vcl.h>一起删去
UnicodeString MD5_String (unsigned char* buff, unsigned int len)
{
int ok = 0;
MD5_CTX context;

try {
MD5Init (context);
MD5Update (context, buff, len);
MD5Final (context);
ok = 1;
}
catch(...) {
ok = 0;
}
if (ok == 0) return L"" ; //如果出错则返回空字符串
else return context.str ;
}
//========================================================================
UnicodeString MD5_File(const UnicodeString filename)
{
if (!FileExists(filename)) return L"" ;
int len, ok = 0;
FILE *fp = NULL;
MD5_CTX context;
unsigned char* buf = NULL;

fp = _wfopen (filename.c_str(), L"rb") ;
if (NULL == fp) return L"" ;
try {
try {
buf = new unsigned char[20480]; //每次读入文件的字节数,这个数字可以根据需要更改
MD5Init (context);
while (0 != (len = fread (buf, 1, 20480, fp))) MD5Update (context, buf, len);
MD5Final (context);
ok = 1;
}
catch (...) {
ok = 0 ;
}
}
__finally {
delete[] buf ;
fclose (fp) ;
}

if (ok == 0) return L""; //如果出错则返回空字符串
else return context.str;
}
//========================================================================
...全文
305 7 打赏 收藏 转发到动态 举报
写回复
用AI写文章
7 条回复
切换为时间正序
请发表友善的回复…
发表回复
ooolinux 2021-01-31
  • 打赏
  • 举报
回复
引用 6 楼 早打大打打核战争的回复:
[quote=引用 5 楼 ooolinux 的回复:][quote=引用 4 楼 早打大打打核战争 的回复:]你们把楼主的辛勤劳动都否定了~

楼主用汇编运算肯定快,轮子还是有价值的。[/quote]

我只是随便一说,你不要太认真~
[/quote] 不过一般人有库函数就直接用了,除非大量运算追求速度的~
  • 打赏
  • 举报
回复
引用 5 楼 ooolinux 的回复:
[quote=引用 4 楼 早打大打打核战争 的回复:]你们把楼主的辛勤劳动都否定了~

楼主用汇编运算肯定快,轮子还是有价值的。[/quote]

我只是随便一说,你不要太认真~
  • 打赏
  • 举报
回复
你们把楼主的辛勤劳动都否定了~
ooolinux 2021-01-30
  • 打赏
  • 举报
回复
引用 2 楼 sczyq 的回复:
现在都使用 #include <System.Hash.hpp> 了, 还要那么麻烦去整这些

实用~
THash A record that implements the common methods for all hash types.
THashBobJenkins A record that implements the Jenkins hash type.
THashMD5 A record that implements the MD5 hash type.
THashSHA1 A record that implements the SHA-1 hash type.
THashSHA2 A record that implements the SHA-2 hash type.
ooolinux 2021-01-30
  • 打赏
  • 举报
回复
引用 4 楼 早打大打打核战争 的回复:
你们把楼主的辛勤劳动都否定了~

楼主用汇编运算肯定快,轮子还是有价值的。
sczyq 2021-01-29
  • 打赏
  • 举报
回复
现在都使用 #include <System.Hash.hpp> 了, 还要那么麻烦去整这些
  • 打赏
  • 举报
回复
你的代码应该是从这个C代码改的,这个C代码本来就是针对64字节数据块的处理,要做任意长度数据的MD5,需要多次调用数据块hash,不是它的问题

#include <stdint.h>

void md5_compress(uint32_t state[4], const uint8_t block[64]) {
#define LOADSCHEDULE(i) \
schedule[i] = (uint32_t)block[i * 4 + 0] << 0 \
| (uint32_t)block[i * 4 + 1] << 8 \
| (uint32_t)block[i * 4 + 2] << 16 \
| (uint32_t)block[i * 4 + 3] << 24;

uint32_t schedule[16];
LOADSCHEDULE( 0)
LOADSCHEDULE( 1)
LOADSCHEDULE( 2)
LOADSCHEDULE( 3)
LOADSCHEDULE( 4)
LOADSCHEDULE( 5)
LOADSCHEDULE( 6)
LOADSCHEDULE( 7)
LOADSCHEDULE( 8)
LOADSCHEDULE( 9)
LOADSCHEDULE(10)
LOADSCHEDULE(11)
LOADSCHEDULE(12)
LOADSCHEDULE(13)
LOADSCHEDULE(14)
LOADSCHEDULE(15)

#define ROTL32(x, n) (((0U + (x)) << (n)) | ((x) >> (32 - (n)))) // Assumes that x is uint32_t and 0 < n < 32
#define ROUND0(a, b, c, d, k, s, t) ROUND_TAIL(a, b, d ^ (b & (c ^ d)), k, s, t)
#define ROUND1(a, b, c, d, k, s, t) ROUND_TAIL(a, b, c ^ (d & (b ^ c)), k, s, t)
#define ROUND2(a, b, c, d, k, s, t) ROUND_TAIL(a, b, b ^ c ^ d , k, s, t)
#define ROUND3(a, b, c, d, k, s, t) ROUND_TAIL(a, b, c ^ (b | ~d) , k, s, t)
#define ROUND_TAIL(a, b, expr, k, s, t) \
a = 0U + a + (expr) + UINT32_C(t) + schedule[k]; \
a = 0U + b + ROTL32(a, s);

uint32_t a = state[0];
uint32_t b = state[1];
uint32_t c = state[2];
uint32_t d = state[3];

ROUND0(a, b, c, d, 0, 7, 0xD76AA478)
ROUND0(d, a, b, c, 1, 12, 0xE8C7B756)
ROUND0(c, d, a, b, 2, 17, 0x242070DB)
ROUND0(b, c, d, a, 3, 22, 0xC1BDCEEE)
ROUND0(a, b, c, d, 4, 7, 0xF57C0FAF)
ROUND0(d, a, b, c, 5, 12, 0x4787C62A)
ROUND0(c, d, a, b, 6, 17, 0xA8304613)
ROUND0(b, c, d, a, 7, 22, 0xFD469501)
ROUND0(a, b, c, d, 8, 7, 0x698098D8)
ROUND0(d, a, b, c, 9, 12, 0x8B44F7AF)
ROUND0(c, d, a, b, 10, 17, 0xFFFF5BB1)
ROUND0(b, c, d, a, 11, 22, 0x895CD7BE)
ROUND0(a, b, c, d, 12, 7, 0x6B901122)
ROUND0(d, a, b, c, 13, 12, 0xFD987193)
ROUND0(c, d, a, b, 14, 17, 0xA679438E)
ROUND0(b, c, d, a, 15, 22, 0x49B40821)
ROUND1(a, b, c, d, 1, 5, 0xF61E2562)
ROUND1(d, a, b, c, 6, 9, 0xC040B340)
ROUND1(c, d, a, b, 11, 14, 0x265E5A51)
ROUND1(b, c, d, a, 0, 20, 0xE9B6C7AA)
ROUND1(a, b, c, d, 5, 5, 0xD62F105D)
ROUND1(d, a, b, c, 10, 9, 0x02441453)
ROUND1(c, d, a, b, 15, 14, 0xD8A1E681)
ROUND1(b, c, d, a, 4, 20, 0xE7D3FBC8)
ROUND1(a, b, c, d, 9, 5, 0x21E1CDE6)
ROUND1(d, a, b, c, 14, 9, 0xC33707D6)
ROUND1(c, d, a, b, 3, 14, 0xF4D50D87)
ROUND1(b, c, d, a, 8, 20, 0x455A14ED)
ROUND1(a, b, c, d, 13, 5, 0xA9E3E905)
ROUND1(d, a, b, c, 2, 9, 0xFCEFA3F8)
ROUND1(c, d, a, b, 7, 14, 0x676F02D9)
ROUND1(b, c, d, a, 12, 20, 0x8D2A4C8A)
ROUND2(a, b, c, d, 5, 4, 0xFFFA3942)
ROUND2(d, a, b, c, 8, 11, 0x8771F681)
ROUND2(c, d, a, b, 11, 16, 0x6D9D6122)
ROUND2(b, c, d, a, 14, 23, 0xFDE5380C)
ROUND2(a, b, c, d, 1, 4, 0xA4BEEA44)
ROUND2(d, a, b, c, 4, 11, 0x4BDECFA9)
ROUND2(c, d, a, b, 7, 16, 0xF6BB4B60)
ROUND2(b, c, d, a, 10, 23, 0xBEBFBC70)
ROUND2(a, b, c, d, 13, 4, 0x289B7EC6)
ROUND2(d, a, b, c, 0, 11, 0xEAA127FA)
ROUND2(c, d, a, b, 3, 16, 0xD4EF3085)
ROUND2(b, c, d, a, 6, 23, 0x04881D05)
ROUND2(a, b, c, d, 9, 4, 0xD9D4D039)
ROUND2(d, a, b, c, 12, 11, 0xE6DB99E5)
ROUND2(c, d, a, b, 15, 16, 0x1FA27CF8)
ROUND2(b, c, d, a, 2, 23, 0xC4AC5665)
ROUND3(a, b, c, d, 0, 6, 0xF4292244)
ROUND3(d, a, b, c, 7, 10, 0x432AFF97)
ROUND3(c, d, a, b, 14, 15, 0xAB9423A7)
ROUND3(b, c, d, a, 5, 21, 0xFC93A039)
ROUND3(a, b, c, d, 12, 6, 0x655B59C3)
ROUND3(d, a, b, c, 3, 10, 0x8F0CCC92)
ROUND3(c, d, a, b, 10, 15, 0xFFEFF47D)
ROUND3(b, c, d, a, 1, 21, 0x85845DD1)
ROUND3(a, b, c, d, 8, 6, 0x6FA87E4F)
ROUND3(d, a, b, c, 15, 10, 0xFE2CE6E0)
ROUND3(c, d, a, b, 6, 15, 0xA3014314)
ROUND3(b, c, d, a, 13, 21, 0x4E0811A1)
ROUND3(a, b, c, d, 4, 6, 0xF7537E82)
ROUND3(d, a, b, c, 11, 10, 0xBD3AF235)
ROUND3(c, d, a, b, 2, 15, 0x2AD7D2BB)
ROUND3(b, c, d, a, 9, 21, 0xEB86D391)

state[0] = 0U + state[0] + a;
state[1] = 0U + state[1] + b;
state[2] = 0U + state[2] + c;
state[3] = 0U + state[3] + d;
}

13,826

社区成员

发帖
与我相关
我的任务
社区描述
C++ Builder相关内容讨论区
社区管理员
  • 基础类社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧