Fork me on GitHub

【加解密】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;
}
posted @ 2015-12-15 13:24  Mr.YF  阅读(1737)  评论(0编辑  收藏  举报