【加解密】CHAP算法C++实现
CHAP是一种挑战响应式协议。
CHAP全称为:Challenge Handshake Authentication Protocol。
CHAP密码 = 一个字节的标识符 + MD5(一个字节的标识符+明文密码+挑战码)
注:+号只是连接符,两个串之间没有任何多余字符;
如:
挑战码 = cce964fe4807b30ddcda0903413d1a3a560710a2
一个字节的标识符 = 0x97
明文密码 = 20151013
CHAP密码 = "97" + MD5(0x97 + 20151013 + fromHex(cce964fe4807b30ddcda0903413d1a3a560710a2))
CHAP密码 = 9721e6dda93ed253cfdcbc20bab959afed
即调用如下函数时,参数如下:
string reqChallenge = "cce964fe4807b30ddcda0903413d1a3a560710a2"; string challange = fromHex(reqChallenge.c_str(), reqChallenge.length()); string ChapPasswd; CHAPPasswdXor("20151013", 0x97, challange, ChapPasswd);
如下是一个CHAP协议的实现算法:
#include <string> #include "md5.h" #define RAD_PASSWORD_LEN 128 #define RAD_PSWDSEG_LEN 16 #define RAD_AUTHCATOR_LEN 16 std::string Hex(const char* cpSrcStr, int len, bool isUpper = false) { if (cpSrcStr == NULL) { return ""; } std::string ret(len * 2, 0x00); const char* hex = isUpper ? "0123456789ABCDEF" : "0123456789abcdef"; for (size_t i = 0; i < len; ++i) { unsigned char v = static_cast<unsigned char>(cpSrcStr[i]); ret[2*i] = hex[(v >> 4) & 0x0f]; ret[2*i+1] = hex[ v & 0x0f]; } return ret; } char asc_bcd(const char *aBcdStr) { unsigned char digit; digit = (aBcdStr[0] >= 'a' ? ((aBcdStr[0]) - 'a')+10 : (aBcdStr[0] - '0')); digit *= 16; digit += (aBcdStr[1] >= 'a' ? ((aBcdStr[1]) - 'a')+10 : (aBcdStr[1] - '0')); return digit; } std::string fromHex(const char* from, size_t len) { std::string ret(len / 2, 0x00); for (size_t ii = 0; ii < len / 2; ii++) ret[ii] = asc_bcd(from + ii * 2); return ret; } void MD5Calc(const unsigned char *input, unsigned int inlen, unsigned char *output) { MD5_CTX context; MD5Init(&context); MD5Update(&context, (unsigned char *)input, inlen); MD5Final(output, &context); } int CHAPPasswdXor(const char *aPasswd, unsigned char aIdentifier, const std::string& aChallenge, std::string &aOutPasswd) { char localPwd[RAD_PASSWORD_LEN+1] = {0}; int pwLen = strlen(aPasswd); if (pwLen > RAD_PASSWORD_LEN) { //LOG_INFO("%s:Password is too long."); return -1; } char *pwStr = localPwd; *pwStr++ = aIdentifier; strcpy(pwStr, aPasswd); pwStr += pwLen; // challenge is append if challenge is exist. memcpy(pwStr, aChallenge.data(), aChallenge.length()); pwLen += aChallenge.length() + 1; // Encrypted. char md5Output[RAD_AUTHCATOR_LEN+1] = {0}; MD5Calc((unsigned char *)localPwd, pwLen, (unsigned char *)md5Output); // get the CHAP password pwStr = localPwd; *pwStr++ = aIdentifier; memcpy(pwStr, md5Output, RAD_AUTHCATOR_LEN); aOutPasswd = Hex(localPwd, RAD_PSWDSEG_LEN+1); return 0; }