zoukankan      html  css  js  c++  java
  • 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;
    }
  • 相关阅读:
    oracle登陆认证方式
    oracle用户管理
    oracle sqlplus常用命令
    瀑布开发模式和敏捷开发模式
    在C#中用RX库和await来实现直观的状态机
    C#实现简单的字符串加密
    双屏办公之体会
    利用json2csharp快速生成C#类
    .Net中的插件框架Managed Extensibility Framework
    解决NVidia显卡最大化和最小化窗口时的卡顿问题
  • 原文地址:https://www.cnblogs.com/voipman/p/5047912.html
Copyright © 2011-2022 走看看