PAP認證方式原理和實現


PAP認證協議

基本描述:

  Password Authentication Protocol 口令認證協議

  PAP認證過程非常簡單,二次握手機制,使用明文格式發送用戶名和密碼,發起方為被認證方,可以做無限次的嘗試(暴力破解),只在鏈路建立的階段進行PAP認證,一旦鏈路建立成功將不再進行認證檢測。

     rfc參考:rfc2865.txt

使用場景:

  PPPOE撥號和Radius認證環境中。

     

加密原理:

       加密時將明文按照16字節分塊為p1, p2, ..., pi多個小塊。

     

描述
字段 意義
S 共享密鑰
RA 128位的請求認證碼
p1,p2,...,pi 將明文密碼按照16字節分塊
c(1),c(2),...,c(i) 加密后的密文串

 

 

 

 

 

 

  最終得到的加密密文串是 c(1)+c(2)+...+c(i)連接起來的串。

解密原理:

      解密時將密文按照16字節分塊為c(1), c(2), ..., c(i)多個小塊。

     

  最終得到的解密后的明文串是 p1+p2+...+pi連接起來的串。

代碼實現:

加密:

#define RAD_PSWDSEG_LEN   16
#define RAD_AUTHCATOR_LEN 16
#define RET_ERROR -1
#define RET_OK     0
std::string peerShareSecret_ = "88----89";
// ---------------------------------------------------------------------------
// int :PasswdXor
//
// Use for encrypt the password attribute.
// ---------------------------------------------------------------------------
//
int PasswdXor(const char *aPasswd, string &aOutPasswd)
{
    if (aPasswd == NULL) {
        return RET_ERROR;
    }
    char localPwd[RAD_PASSWORD_LEN+1] = {0};
    int  pwLen = strlen(aPasswd);

    // Pad the password. If the length of the passwd isn't multiples of 16, pad it.
    if (pwLen > RAD_PASSWORD_LEN) {
        return RET_ERROR;
    }
    char *pwStr = localPwd;
    strcpy(localPwd, aPasswd);

    int n = pwLen - (pwLen/RAD_PSWDSEG_LEN) * RAD_PSWDSEG_LEN;
    if (n != 0) {
        memset(pwStr+pwLen, 0, RAD_PSWDSEG_LEN - n);
        pwLen += 16 - n;
    }

    // Encrypted.
    char md5Input[RAD_SECRET_LEN + RAD_AUTHCATOR_LEN] = {0};
    char md5Output[RAD_AUTHCATOR_LEN] = {0};
    char * inStr = md5Input;
    int inlen = peerShareSecret_.length() + RAD_AUTHCATOR_LEN;
    strcpy(inStr, peerShareSecret_.c_str());
    inStr += peerShareSecret_.length();

    memcpy(inStr, (char *)authcator_, RAD_AUTHCATOR_LEN);
    int passEncodeLen = pwLen;
    for (; pwLen > 0; pwLen -= RAD_PSWDSEG_LEN) {
        MD5Calc((unsigned char *)md5Input, inlen, (unsigned char *)md5Output);
        int i ;
        for (i =0; i<RAD_PSWDSEG_LEN; ++i)
            pwStr[i] ^= md5Output[i];

        memcpy(inStr, pwStr, RAD_PSWDSEG_LEN);
        pwStr += RAD_PSWDSEG_LEN;
    }

    aOutPasswd = EndcodePwd(localPwd, passEncodeLen);
    return  RET_OK;
}

  

解密:

int PasswdDecodeXor(const char *aPasswd, string &aOutPasswd)
{
    if (aPasswd == NULL) {
        return RET_ERROR;
    }
    int pwLen = strlen(aPasswd);
    if (pwLen < 32) {
        return RET_ERROR;
    }
    char md5Input[RAD_SECRET_LEN + RAD_AUTHCATOR_LEN] = {0};
    char md5Output[RAD_AUTHCATOR_LEN] = {0};
    char * inStr = md5Input;
    int inlen = peerShareSecret_.length() + RAD_AUTHCATOR_LEN;
    strcpy(inStr, peerShareSecret_.c_str());
    inStr += peerShareSecret_.length();

    memcpy(inStr, (char *)authcator_, RAD_AUTHCATOR_LEN);
    aOutPasswd = "";
    for(int i = 0; i < pwLen / 32; i++){
        char pwStr[RAD_PSWDSEG_LEN + 1] = { 0 };
        string hexPass = fromHex(aPasswd+i*32, 32);
        memcpy(pwStr, hexPass.data(), 16);
        MD5Calc((unsigned char *)md5Input, inlen, (unsigned char *)md5Output);
        for (int i = 0; i < RAD_PSWDSEG_LEN; ++i)
            pwStr[i] ^= md5Output[i];
        pwStr[RAD_PSWDSEG_LEN] = 0x00;
        aOutPasswd += pwStr;
        if (strlen(pwStr) < RAD_PSWDSEG_LEN) {
            break;
        } else {
            memcpy(inStr, hexPass.data(), 16);
        }
    }
    return  RET_OK;
}

Done.


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM