📄 md5.cpp
字号:
/** * @file md5.cpp * @brief 字符串的包装,md5单向散列函数,crypt单向散列函数(md5算法) * @author 泥偶 * @since 2003-09-26 * @date 2003-11-03 */#define HAVE_MEMCPY#include "xstring.hpp"namespace x{ namespace { #include "md5.c" /* magic sizes */ const int MD5_SIZE = 16; static unsigned char itoa64[] = /* 0 ... 63 => ascii - 64 */ "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; void _crypt_to64(char* s, unsigned long v, int n) { while (--n >= 0) { *s++ = itoa64[v&0x3f]; v >>= 6; } } // 这个函数是 /usr/src/lib/libcrypt/crypt-md5.c 抄来的,做了一些修改 char* crypt_md5(const char *pw, const char *salt) { static char *magic = "$1$"; /* * This string is magic for * this algorithm. Having * it this way, we can get * get better later on */ static char passwd[120], *p; static const char *sp, *ep; unsigned char final[MD5_SIZE]; int sl, pl, i; md5_ctx ctx, ctx1; unsigned long l; /* Refine the Salt first */ sp = salt; /* If it starts with the magic string, then skip that */ if (!strncmp(sp, magic, strlen(magic))) sp += strlen(magic); /* It stops at the first '$', max 8 chars */ for (ep=sp;*ep && *ep != '$' && ep < (sp+8);ep++) { continue; } /* get the length of the true salt */ sl = ep - sp; md5_init_ctx(&ctx); /* The password first, since that is what is most unknown */ md5_process_bytes(pw, strlen(pw), &ctx); /* Then our magic string */ md5_process_bytes(magic, strlen(magic), &ctx); /* Then the raw salt */ md5_process_bytes(sp, sl, &ctx); /* Then just as many characters of the MD5(pw, salt, pw) */ md5_init_ctx(&ctx1); md5_process_bytes(pw, strlen(pw), &ctx1); md5_process_bytes(sp, sl, &ctx1); md5_process_bytes(pw, strlen(pw), &ctx1); md5_finish_ctx(&ctx1, final); for (pl = strlen(pw); pl > 0; pl -= MD5_SIZE) { md5_process_bytes(final, pl>MD5_SIZE ? MD5_SIZE : pl, &ctx); } /* Don't leave anything around in vm they could use. */ memset(final, 0, sizeof final); /* Then something really weird... */ for (i = strlen(pw); i; i >>= 1) { if (i&1) { md5_process_bytes(final, 1, &ctx); } else { md5_process_bytes(pw, 1, &ctx); } } /* Now make the output string */ strcpy(passwd, magic); strncat(passwd, sp, sl); strcat(passwd, "$"); md5_finish_ctx(&ctx, final); /* * and now, just to make sure things don't run too fast * On a 60 Mhz Pentium this takes 34 msec, so you would * need 30 seconds to build a 1000 entry dictionary... */ for (i = 0; i < 1000; ++i) { md5_init_ctx(&ctx1); if (i & 1) { md5_process_bytes(pw, strlen(pw), &ctx1); } else { md5_process_bytes(final, MD5_SIZE, &ctx1); } if (i % 3) { md5_process_bytes(sp, sl, &ctx1); } if (i % 7) { md5_process_bytes(pw, strlen(pw), &ctx1); } if (i & 1) { md5_process_bytes(final, MD5_SIZE, &ctx1); } else { md5_process_bytes(pw, strlen(pw), &ctx1); } md5_finish_ctx(&ctx1, final); } p = passwd + strlen(passwd); l = (final[ 0]<<16) | (final[ 6]<<8) | final[12]; _crypt_to64(p, l, 4); p += 4; l = (final[ 1]<<16) | (final[ 7]<<8) | final[13]; _crypt_to64(p, l, 4); p += 4; l = (final[ 2]<<16) | (final[ 8]<<8) | final[14]; _crypt_to64(p, l, 4); p += 4; l = (final[ 3]<<16) | (final[ 9]<<8) | final[15]; _crypt_to64(p, l, 4); p += 4; l = (final[ 4]<<16) | (final[10]<<8) | final[ 5]; _crypt_to64(p, l, 4); p += 4; l = final[11] ; _crypt_to64(p, l, 2); p += 2; *p = '\0'; /* Don't leave anything around in vm they could use. */ memset(final, 0, sizeof final); return passwd; } } // namespace//---------------------------------------------------------------------------- /** 根据 <a href="http://www.faqs.org/rfcs/rfc1321">RSA Data Security, Inc. MD5 Message-Digest Algorithm</a>计算字符串的MD5散列。 这个散列是一个32个字符的十六进制数字。 如果可选的raw_output被设置成true,那将会返回16个字符长度的原始二进制格式。 @code * xstring str = "apple"; * if ("1f3870be274f6c49b3e31a0c6728957f" == str.md5()) * { * cout << "Would you like a green or red apple?"; * } @endcode raw_output参数是1.0.2test3版本新增的 @see crc32() sha1() */ xstring xstring::md5(bool raw_output) const { char digest[16]; md5_buffer(this->data(), this->size(), digest); xstring str(digest, sizeof(digest)); if (raw_output) { return str; } return str.bin2hex(); } /** @return 基于UNIX MD5的加密算法加密过的字符串。 CRYPT_MD5 - 基于MD5的加密算法。以@$1@$开始,附带12个字符的盐(salt)。 @see md5() */ xstring xstring::crypt(const xstring& salt) const { return xstring(crypt_md5(this->c_str(), salt.c_str())); }} // namespace x
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -