http协议之digest认证实现

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了http协议之digest认证实现相关的知识,希望对你有一定的参考价值。

参考

http://blog.csdn.net/jszj/article/details/8918967

https://wenku.baidu.com/view/22be2dcf83d049649b6658ff.html

http://blog.csdn.net/i_lovefish/article/details/9816783


md5.h

#ifndef MD5_H

#define MD5_H


typedef struct

{

unsigned int count[2];

unsigned int state[4];

unsigned char buffer[64];

}MD5_CTX;



#define F(x,y,z) ((x & y) | (~x & z))

#define G(x,y,z) ((x & z) | (y & ~z))

#define H(x,y,z) (x^y^z)

#define I(x,y,z) (y ^ (x | ~z))

#define ROTATE_LEFT(x,n) ((x << n) | (x >> (32-n)))

#define FF(a,b,c,d,x,s,ac) \

          { \

          a += F(b,c,d) + x + ac; \

          a = ROTATE_LEFT(a,s); \

          a += b; \

          }

#define GG(a,b,c,d,x,s,ac) \

          { \

          a += G(b,c,d) + x + ac; \

          a = ROTATE_LEFT(a,s); \

          a += b; \

          }

#define HH(a,b,c,d,x,s,ac) \

          { \

          a += H(b,c,d) + x + ac; \

          a = ROTATE_LEFT(a,s); \

          a += b; \

          }

#define II(a,b,c,d,x,s,ac) \

          { \

          a += I(b,c,d) + x + ac; \

          a = ROTATE_LEFT(a,s); \

          a += b; \

          }                                            

void MD5Init(MD5_CTX *context);

void MD5Update(MD5_CTX *context, unsigned char *input, unsigned int inputlen);

void MD5Final(MD5_CTX *context, unsigned char digest[16]);

void MD5Transform(unsigned int state[4], unsigned char block[64]);

void MD5Encode(unsigned char *output, unsigned int *input, unsigned int len);

void MD5Decode(unsigned int *output, unsigned char *input, unsigned int len);


#endif


md5.cpp

#include <memory.h>

#include "md5.h"


unsigned char PADDING[] = { 0x80,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,

0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,

0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,

0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 };


void MD5Init(MD5_CTX *context)

{

context->count[0] = 0;

context->count[1] = 0;

context->state[0] = 0x67452301;

context->state[1] = 0xEFCDAB89;

context->state[2] = 0x98BADCFE;

context->state[3] = 0x10325476;

}

void MD5Update(MD5_CTX *context, unsigned char *input, unsigned int inputlen)

{

unsigned int i = 0, index = 0, partlen = 0;

index = (context->count[0] >> 3) & 0x3F;

partlen = 64 - index;

context->count[0] += inputlen << 3;

if (context->count[0] < (inputlen << 3))

context->count[1]++;

context->count[1] += inputlen >> 29;


if (inputlen >= partlen)

{

memcpy(&context->buffer[index], input, partlen);

MD5Transform(context->state, context->buffer);

for (i = partlen; i + 64 <= inputlen; i += 64)

MD5Transform(context->state, &input[i]);

index = 0;

}

else

{

i = 0;

}

memcpy(&context->buffer[index], &input[i], inputlen - i);

}

void MD5Final(MD5_CTX *context, unsigned char digest[16])

{

unsigned int index = 0, padlen = 0;

unsigned char bits[8];

index = (context->count[0] >> 3) & 0x3F;

padlen = (index < 56) ? (56 - index) : (120 - index);

MD5Encode(bits, context->count, 8);

MD5Update(context, PADDING, padlen);

MD5Update(context, bits, 8);

MD5Encode(digest, context->state, 16);

}

void MD5Encode(unsigned char *output, unsigned int *input, unsigned int len)

{

unsigned int i = 0, j = 0;

while (j < len)

{

output[j] = input[i] & 0xFF;

output[j + 1] = (input[i] >> 8) & 0xFF;

output[j + 2] = (input[i] >> 16) & 0xFF;

output[j + 3] = (input[i] >> 24) & 0xFF;

i++;

j += 4;

}

}

void MD5Decode(unsigned int *output, unsigned char *input, unsigned int len)

{

unsigned int i = 0, j = 0;

while (j < len)

{

output[i] = (input[j]) |

(input[j + 1] << 8) |

(input[j + 2] << 16) |

(input[j + 3] << 24);

i++;

j += 4;

}

}

void MD5Transform(unsigned int state[4], unsigned char block[64])

{

unsigned int a = state[0];

unsigned int b = state[1];

unsigned int c = state[2];

unsigned int d = state[3];

unsigned int x[64];

MD5Decode(x, block, 64);

FF(a, b, c, d, x[0], 7, 0xd76aa478); /* 1 */

FF(d, a, b, c, x[1], 12, 0xe8c7b756); /* 2 */

FF(c, d, a, b, x[2], 17, 0x242070db); /* 3 */

FF(b, c, d, a, x[3], 22, 0xc1bdceee); /* 4 */

FF(a, b, c, d, x[4], 7, 0xf57c0faf); /* 5 */

FF(d, a, b, c, x[5], 12, 0x4787c62a); /* 6 */

FF(c, d, a, b, x[6], 17, 0xa8304613); /* 7 */

FF(b, c, d, a, x[7], 22, 0xfd469501); /* 8 */

FF(a, b, c, d, x[8], 7, 0x698098d8); /* 9 */

FF(d, a, b, c, x[9], 12, 0x8b44f7af); /* 10 */

FF(c, d, a, b, x[10], 17, 0xffff5bb1); /* 11 */

FF(b, c, d, a, x[11], 22, 0x895cd7be); /* 12 */

FF(a, b, c, d, x[12], 7, 0x6b901122); /* 13 */

FF(d, a, b, c, x[13], 12, 0xfd987193); /* 14 */

FF(c, d, a, b, x[14], 17, 0xa679438e); /* 15 */

FF(b, c, d, a, x[15], 22, 0x49b40821); /* 16 */


  /* Round 2 */

GG(a, b, c, d, x[1], 5, 0xf61e2562); /* 17 */

GG(d, a, b, c, x[6], 9, 0xc040b340); /* 18 */

GG(c, d, a, b, x[11], 14, 0x265e5a51); /* 19 */

GG(b, c, d, a, x[0], 20, 0xe9b6c7aa); /* 20 */

GG(a, b, c, d, x[5], 5, 0xd62f105d); /* 21 */

GG(d, a, b, c, x[10], 9, 0x2441453); /* 22 */

GG(c, d, a, b, x[15], 14, 0xd8a1e681); /* 23 */

GG(b, c, d, a, x[4], 20, 0xe7d3fbc8); /* 24 */

GG(a, b, c, d, x[9], 5, 0x21e1cde6); /* 25 */

GG(d, a, b, c, x[14], 9, 0xc33707d6); /* 26 */

GG(c, d, a, b, x[3], 14, 0xf4d50d87); /* 27 */

GG(b, c, d, a, x[8], 20, 0x455a14ed); /* 28 */

GG(a, b, c, d, x[13], 5, 0xa9e3e905); /* 29 */

GG(d, a, b, c, x[2], 9, 0xfcefa3f8); /* 30 */

GG(c, d, a, b, x[7], 14, 0x676f02d9); /* 31 */

GG(b, c, d, a, x[12], 20, 0x8d2a4c8a); /* 32 */


  /* Round 3 */

HH(a, b, c, d, x[5], 4, 0xfffa3942); /* 33 */

HH(d, a, b, c, x[8], 11, 0x8771f681); /* 34 */

HH(c, d, a, b, x[11], 16, 0x6d9d6122); /* 35 */

HH(b, c, d, a, x[14], 23, 0xfde5380c); /* 36 */

HH(a, b, c, d, x[1], 4, 0xa4beea44); /* 37 */

HH(d, a, b, c, x[4], 11, 0x4bdecfa9); /* 38 */

HH(c, d, a, b, x[7], 16, 0xf6bb4b60); /* 39 */

HH(b, c, d, a, x[10], 23, 0xbebfbc70); /* 40 */

HH(a, b, c, d, x[13], 4, 0x289b7ec6); /* 41 */

HH(d, a, b, c, x[0], 11, 0xeaa127fa); /* 42 */

HH(c, d, a, b, x[3], 16, 0xd4ef3085); /* 43 */

HH(b, c, d, a, x[6], 23, 0x4881d05); /* 44 */

HH(a, b, c, d, x[9], 4, 0xd9d4d039); /* 45 */

HH(d, a, b, c, x[12], 11, 0xe6db99e5); /* 46 */

HH(c, d, a, b, x[15], 16, 0x1fa27cf8); /* 47 */

HH(b, c, d, a, x[2], 23, 0xc4ac5665); /* 48 */


 /* Round 4 */

II(a, b, c, d, x[0], 6, 0xf4292244); /* 49 */

II(d, a, b, c, x[7], 10, 0x432aff97); /* 50 */

II(c, d, a, b, x[14], 15, 0xab9423a7); /* 51 */

II(b, c, d, a, x[5], 21, 0xfc93a039); /* 52 */

II(a, b, c, d, x[12], 6, 0x655b59c3); /* 53 */

II(d, a, b, c, x[3], 10, 0x8f0ccc92); /* 54 */

II(c, d, a, b, x[10], 15, 0xffeff47d); /* 55 */

II(b, c, d, a, x[1], 21, 0x85845dd1); /* 56 */

II(a, b, c, d, x[8], 6, 0x6fa87e4f); /* 57 */

II(d, a, b, c, x[15], 10, 0xfe2ce6e0); /* 58 */

II(c, d, a, b, x[6], 15, 0xa3014314); /* 59 */

II(b, c, d, a, x[13], 21, 0x4e0811a1); /* 60 */

II(a, b, c, d, x[4], 6, 0xf7537e82); /* 61 */

II(d, a, b, c, x[11], 10, 0xbd3af235); /* 62 */

II(c, d, a, b, x[2], 15, 0x2ad7d2bb); /* 63 */

II(b, c, d, a, x[9], 21, 0xeb86d391); /* 64 */

state[0] += a;

state[1] += b;

state[2] += c;

state[3] += d;

}


digcalc.h

#pragma once


#define HASHLEN 16  

typedef char HASH[HASHLEN]; 

#define HASHHEXLEN 32  

typedef char HASHHEX[HASHHEXLEN+1]; 

#define IN 

#define OUT  /* calculate H(A1) as per HTTP Digest spec */

void DigestCalcHA1( IN char * pszAlg, IN char * pszUserName, IN char * pszRealm, IN char * pszPassword, IN char * pszNonce, IN char * pszCNonce, OUT HASHHEX SessionKey);  

/* calculate request-digest/response-digest as per HTTP Digest spec */ 

void DigestCalcResponse(IN HASHHEX HA1, /* H(A1) */  IN char * pszNonce, /* nonce from server */ IN char * pszNonceCount, /* 8 hex digits */ IN char * pszCNonce, /* client nonce */  IN char * pszQop, /* qop-value: "", "auth", "auth-int" */ IN char * pszMethod, /* method from the request */ IN char * pszDigestUri, /* requested URL */  IN HASHHEX HEntity, /* H(entity body) if qop="auth-int" */ OUT HASHHEX Response /* request-digest or response-digest */);


digcalc.cpp代码


#include "md5.h"

#include <string.h>

#include "digcalc.h" 


void CvtHex(IN HASH Bin, OUT HASHHEX Hex)

{

unsigned short i;

unsigned char j;

for (i = 0; i < HASHLEN; i++)

{

j = (Bin[i] >> 4) & 0xf;

if (j <= 9)  Hex[i * 2] = (j + ‘0‘);

else  Hex[i * 2] = (j + ‘a‘ - 10);

j = Bin[i] & 0xf; 

if (j <= 9)  Hex[i * 2 + 1] = (j + ‘0‘);

else  Hex[i * 2 + 1] = (j + ‘a‘ - 10);

};

Hex[HASHHEXLEN] = ‘\0‘;

};


/* calculate H(A1) as per spec */

void DigestCalcHA1(

IN char * pszAlg,

IN char * pszUserName,

IN char * pszRealm,

IN char * pszPassword,

IN char * pszNonce,

IN char * pszCNonce,

OUT HASHHEX SessionKey

)

{

MD5_CTX Md5Ctx;

HASH HA1;

MD5Init(&Md5Ctx);

MD5Update(&Md5Ctx, (unsigned char*)pszUserName, strlen(pszUserName));

MD5Update(&Md5Ctx, (unsigned char*)":", 1);

MD5Update(&Md5Ctx, (unsigned char*)pszRealm, strlen(pszRealm));

MD5Update(&Md5Ctx, (unsigned char*)":", 1);

MD5Update(&Md5Ctx, (unsigned char*)pszPassword, strlen(pszPassword));

MD5Final(&Md5Ctx,(unsigned char*)HA1);

if (strcmp(pszAlg, "md5-sess") == 0) {

MD5Init(&Md5Ctx);

MD5Update(&Md5Ctx, (unsigned char*)HA1, HASHLEN);

MD5Update(&Md5Ctx, (unsigned char*)":", 1);

MD5Update(&Md5Ctx, (unsigned char*)pszNonce, strlen(pszNonce));

MD5Update(&Md5Ctx, (unsigned char*)":", 1);

MD5Update(&Md5Ctx, (unsigned char*)pszCNonce, strlen(pszCNonce));

MD5Final(&Md5Ctx, (unsigned char*)HA1);

};

CvtHex(HA1, SessionKey);

};


/* calculate request-digest/response-digest as per HTTP Digest spec */

void DigestCalcResponse(

IN HASHHEX HA1, /* H(A1) */

IN char * pszNonce, /* nonce from server */

IN char * pszNonceCount, /* 8 hex digits */

IN char * pszCNonce, /* client nonce */

IN char * pszQop, /* qop-value: "", "auth", "auth-int" */

IN char * pszMethod, /* method from the request */

IN char * pszDigestUri, /* requested URL */

IN HASHHEX HEntity, /* H(entity body) if qop="auth-int" */

OUT HASHHEX Response /* request-digest or response-digest */

)

{

MD5_CTX Md5Ctx;

HASH HA2;

HASH RespHash;

HASHHEX HA2Hex;

// calculate H(A2)

MD5Init(&Md5Ctx);

MD5Update(&Md5Ctx, (unsigned char*)pszMethod, strlen(pszMethod));

MD5Update(&Md5Ctx, (unsigned char*)":", 1);

MD5Update(&Md5Ctx, (unsigned char*)pszDigestUri, strlen(pszDigestUri));

if (strcmp(pszQop, "auth-int") == 0) {

MD5Update(&Md5Ctx, (unsigned char*)":", 1);

MD5Update(&Md5Ctx, (unsigned char*)HEntity, HASHHEXLEN);

};

MD5Final(&Md5Ctx, (unsigned char*)HA2);

CvtHex(HA2, HA2Hex);

// calculate response

MD5Init(&Md5Ctx);

MD5Update(&Md5Ctx, (unsigned char*)HA1, HASHHEXLEN);

MD5Update(&Md5Ctx, (unsigned char*)":", 1);

MD5Update(&Md5Ctx, (unsigned char*)pszNonce, strlen(pszNonce));

MD5Update(&Md5Ctx, (unsigned char*)":", 1);

if (*pszQop) {

MD5Update(&Md5Ctx, (unsigned char*)pszNonceCount, strlen(pszNonceCount));

MD5Update(&Md5Ctx, (unsigned char*)":", 1);

MD5Update(&Md5Ctx, (unsigned char*)pszCNonce, strlen(pszCNonce));

MD5Update(&Md5Ctx, (unsigned char*)":", 1);

MD5Update(&Md5Ctx, (unsigned char*)pszQop, strlen(pszQop));

MD5Update(&Md5Ctx, (unsigned char*)":", 1);

};

MD5Update(&Md5Ctx, (unsigned char*)HA2Hex, HASHHEXLEN);

MD5Final(&Md5Ctx, (unsigned char*)RespHash);

CvtHex(RespHash, Response);

};



测试例子

#include <string>

#include <iostream>

#include "digcalc.h"


using namespace std;


int main()

{

char * pszNonce = "6a0b8f835608eea4f39550723102660b:1503972485455";

char * pszCNonce = "bda3fcdddabaeb5ae9dd14b45fba9adb";

char * pszUser = "admin";

char * pszRealm = "test1.1.2";

char * pszPass = "admin12345";

char * pszAlg = "md5";

char szNonceCount[9] = "00000001";

char * pszMethod = "GET";

char * pszQop = "auth";

char * pszURI = "/ISAPI/Security/userCheck";

HASHHEX HA1;

HASHHEX HA2 = "";

HASHHEX Response;

DigestCalcHA1(pszAlg, pszUser, pszRealm, pszPass, pszNonce,

pszCNonce, HA1);

DigestCalcResponse(HA1, pszNonce, szNonceCount, pszCNonce, pszQop,

pszMethod, pszURI, HA2, Response);

printf("Response = %s\n", Response);


}


以上是关于http协议之digest认证实现的主要内容,如果未能解决你的问题,请参考以下文章

http协议之digest(摘要)认证,详细讲解并附Java SpringBoot源码

HTTP Digest认证

HTTP用户认证追加协议以及相关技术简单学习

http digest鉴权

Http协议之libcurl实现

HTTP协议之基本认证