在项目中遇到过对相同的字符串进行md5加密,结果与对接平台(使用http协议)得出来的md5值不一致的问题。经过多次比对排查,发现如果待加密的字符串中含有中文,就会出现两方结果不一致的问题,分析原因,是双方数据传输过程中采用的编码方式不一致导致的。vs项目中默认的字符集是多字节,而http协议传输中大多使用的是utf8。所以vs中把待加密的字符串转为utf8字节序,再进行md5加密,双方的md5值就能够保持一致了。
关于md5的加密方法实现,网上可以搜到很多,各个语言版本都有介绍。但大多数文章都没有对中文加密进行一些着重提示,导致在使用过程中一旦加密字符串含有中文而校验双方采用的编码方式又不一致,就会出现校验不通过。下面就举例来说明这些情况。
下文采用的md5加密方法取自:
http://blog.csdn.net/gf771115/article/details/24584199
我就直接拿来用了,其它版本的md5加密方法都可以拿来验证。
加密结果与站长之家提供的md5加密工具进行比对。
1. 第一种验证情况 加密字符串中没有中文
int main()
{
cout << "md5 of 'abc123': " << md5("abc123") << endl;
system("pause");
return 0;
}
比对截图 两者结果一致
2. 第二种验证情况 加密字符串包含中文
int main()
{
cout << "md5 of 'abc123中文': " << md5("abc123中文") << endl;
system("pause");
return 0;
}
比对截图 可以看出两者的加密结果已经不一样了
3. 第三种验证情况 加密字符串包含中文但先进行utf8的编码转换再加密
关于编码转换可以看我上一篇博文中的介绍
// Convert GBK to UTF8
int ConvertGBK2UTF8(const char* szGBK, char* szUTF8, int nUTF8Size)
{
if (!szGBK || !szUTF8) return 0;
int nWcharCnt = MultiByteToWideChar(CP_ACP, 0, szGBK, -1, NULL, 0);
WCHAR* pWcharTmp = new WCHAR[nWcharCnt];
memset(pWcharTmp, 0, sizeof(WCHAR) * nWcharCnt);
MultiByteToWideChar(CP_ACP, 0, szGBK, -1, pWcharTmp, nWcharCnt);
int nMbyteLen = WideCharToMultiByte(CP_UTF8, 0, pWcharTmp, -1, NULL, 0, NULL, NULL);
int nRet = 0;
if (nMbyteLen <= nUTF8Size) {
nRet = WideCharToMultiByte(CP_UTF8, 0, pWcharTmp, -1, szUTF8, nMbyteLen, NULL, NULL);
}
delete[] pWcharTmp;
pWcharTmp = NULL;
return nRet;
}
int main()
{
char szUTF8[512] = {0};
ConvertGBK2UTF8("abc123中文", szUTF8, sizeof(szUTF8));
cout << "md5 of utf8 'abc123中文': " << md5(szUTF8) << endl;
system("pause");
return 0;
}
比对截图 经过编码转换两者的加密结果已经一致了