Young & Rich

오늘은 HTTP 인증에 대해서 포스팅을 하도록 하겠습니다.

 

HTTP 인증에서 주로 사용되는 인증방법은 Basic, digest 2가지가 있습니다.

해당 2가지에 대해서 정리를 해보도록 하겠습니다.

 

[ HTTP Authentication ]

- Basic

ID:PW 를 Base64 Encoding 하여 인증, 보안에 취약함(패킷 캡처로 인증값을 취득하여 해킹 가능)

 

인증값 생성 : Base64(userid:passwd)

Authorization: Basic YmFKcmk6u2039s==

 

 

- Digest

Digest 같은 경우는 인증 정보를 생성할 때, Random 성분이 포함되어 있어서 Basic 보다 보안성이 뛰어납니다.

: 단순히 Packet 을 중간에 가로챈다고 하여 해킹 할 수 없습니다.

 

* 용어

cnonce : client nonce, client가 생성한 값

nonce : 인증의 Auth response 를 만드는데 필요한 랜덤 문자열, Server 단에서 제공합니다.

-> 해당 nonce가 random 으로 바뀌는 이유는 보안성 강화(해킹을 막기 위함) 입니다.

nc : nonce 를 요청한 횟 수, 요청할 때마다 +1 씩 증가

 

 

* 인증에 필요한 인자값 계산

- Algorithm이 MD or 정의되어있지 않았을 때 HA1

: HA1 = MD5(username:realm:passwd)

알고리즘이 SHA-1 또는 SHA-2 와 같이 요청할 경우 알고리즘을 사용해 해쉬값을 생성해야합니다.

 

- Algorithm이 MD5-sess 일 때 HA1

HA1 = MD5(MD5(username:realm:passwd):nonce:cnonce)

 

- qop가 auth 또는 정의되어 있지 않을 때 HA2

HA2 = MD5(method:digestURI)

 

- qop가 auth-int 일 때 HA2

HA2 = MD5(method:digestURI:MD5(entityBody))

 

- qop가 auth 또는 auth-int 일때 response

response = MD5(HA1:nonce:nonceCount:cnonce:qop:HA2)

 

- qop가 정의되어 있지 않을 때 response

response = MD5(HA1:nonce:HA2)

참조 : Digest 인증 Spec 문서

 

Digest access authentication - Wikipedia

Digest access authentication is one of the agreed-upon methods a web server can use to negotiate credentials, such as username or password, with a user's web browser. This can be used to confirm the identity of a user before sending sensitive information,

en.wikipedia.org

 

[ Digest Suedo Code ]

Basic 인증 요청
if (!200 OK)
{
    if (401 Not Authorized && Digest)
    {
        nonce, relam 파싱
 
        if (qop 가 있으면 "auth" or "auth-int")
        {
            cnonce, nc Create   // cnonce는 아래의 _create_nonce 함수 참조
            HA1, HA2 연산     // 위의 생성 규칙 참조
            response 생성                         // 위의 생성 규칙 참조
            HTTP API Request String 다시 생성
        }
        else
        {
            HA1, HA2 값으로 생성                 // 위의 생성 규칙 참조
            response 생성                         // 위의 생성 규칙 참조
            HTTP API Request String 다시 생성
        }
        HTTP API Request Server로 다시 Send
    }
}  
     
static void _create_nonce(char *nonce)
{
    static char digest_secret[17];
    memset(digest_secret, 0x00, 17);
    random_id((unsigned char*)digest_secret, 16);
    create_nonce(nonce, digest_secret);
}
 
static void random_id( unsigned char *dest, int len )
{
    int i;
    for( i = 0; i < len / 2; ++i )
        sprintf( (char *)(dest + i * 2), "%02X",
                (unsigned int)( random() & 0xff ) );
    dest[len] = 0;
}
 
=========================================================================
 
static char digest_secret[17];
static int secret_created = 0;
char clientnonce[128];
 
/*
 * Nonce format:
 *
 * Bytes  0- 3: date of nonce creation in seconds since epoch
 * Bytes  4-15: random bytes
 * Bytes 16-31: MD5( bytes[0..15] + ":" + digest secret )
 */
static void create_nonce(char *nonce, char *digest_secret )
{
    unsigned char token[16];
    unsigned char tmp[128], tmp2[128], output[128];
    char *v[2] = { nonce, digest_secret };
    struct timeval now;
    int i;
    gettimeofday( &now, NULL );
    PUT_32( token, now.tv_sec );
    random_bytes( token + 4, sizeof( token ) - 4 );
    for( i = 0; i < 16; ++i )
        sprintf( tmp + (i<<1), "%02x", token[i] );
    tmp[32] = 0;
    snprintf(tmp2, 128, "%s:%s", tmp, digest_secret);
    md5(tmp2, output);
    memcpy(nonce, tmp, 32);
    memcpy(nonce+32, output, strlen(output));
    nonce[32] = '\0';
}

=========================================================================

 

Basic 와 Digest 에 대해서 간단히 정리해보았습니다.

 

그럼 20000.

 

이 글을 공유합시다

facebook twitter googleplus kakaoTalk kakaostory naver band