본문 바로가기

진리는어디에

ASN.1

ASN.1 이라는 것이 무엇인가?

.. 라고 묻는다면..구조화된 데이터(예를 들어 C++ 구조체 혹은 클래스 같은 것들.)에 대해서 기술하고, 인코딩하며, 그 데이터를 전송하고, 수신 하는 경우 디코딩 하는 방법들을 설명하는데 사용되는 일종의 표현법이다...라고 일단 설명 할 수 있겠다.

하지만 사실 이렇게 말하면 머리 속에 무슨 내용인지 쉽게 그림이 그려지지 않는다.(아..지금 이 글을 보는 그대는 그려지는가? 미안하다. 나는 그렇지 않다. 그래서 더 설명 해야겠다)

일단 ASN.1 이 기술한다는 구조화된 데이터,. 즉, 객체(object)라 하면 인/디코딩 하는데 있어 머신혹은 사용하는 언어 따라 천차만별의 방법을 가지는 경우가 종종 있다. ASN.1은 이런 방법에 대해서 어느정도 정규화된 규칙을 제
한다는 것이다.

하지만, 이것이 약간 역설적인 것이(아무도 그렇게 생각하지는 않지만 나는 그렇게 생각한다)..
ASN.1은 정보를 표현하는 추상적인 문법에 대해서는 정의를 하고 있지만 해당 정보가 인코딩 되는 방법에 대해서는 제약을 두고 있지 않다는 것이다. 따라서 여기저기서 다양한 ASN.1 인코딩 규칙들이 생겨날 수 있었고, 각 인코딩 규칙들은 데이터 값, 즉 정보들을 실질적으로 인코딩하여 바이너리 스트림으로 만들어 낼 수 있는 transfer syntax를 각 인코딩 버젼별로 생성해 낸다.

표준 ASN.1 인코딩 룰들로는 아래와 같은 것들이 있다 :

    - Basic Encoding Rules (BER)
    - Canonical Encoding Rules (CER)
    - Distinguished Encoding Rules (DER)
    - XML Encoding Rules (XER)
    - Packed Encoding Rules (PER)
    - Generic String Encoding Rules (GSER)

위의 각 ASN.1 인코딩 룰을 포함하여 ASN.1은 머신 아키텍쳐나 언어에 상관 없이 데이터 구조체를 기술함으로써 서로 다른 환경에 있는 두 어플리케이션간의 구조화된 데이터 전송을 가능하게 한다.

Example - ASN.1 표기법을 이용해 정의 된 FooProtocol 데이터 구조체 :

FooProtocol DEFINITIONS ::= BEGIN

    FooQuestion ::= SEQUENCE {
        trackingNumber INTEGER,
        question       IA5String
    }

    FooAnswer ::= SEQUENCE {
        questionNumber INTEGER,
        answer         BOOLEAN
    }

END

위의 코드에 잠깐 사족을 달자면, FooQuestion과 FooAnswer과 정의 되어 있지만, 사실 Answer가 먼저 보내지고, 그 응답으로 Question이 온다고 하더라도 ASN.1에서는 상관하지 않는다. ASN.1 이 정의하고 있는 것은  어디까지나 구조화된 데이터에 한정 될 뿐이고, 메시지의 전송 순서에 대해서는 관여하지 않는다.

다시 본론으로 돌아가서, 만일 FooProtocol을 따르는 메시지가 있다고 가정하자. 메시지는 아래와 같다  :

myQuestion FooQuestion ::= {
    trackingNumber     5,
    question           "Anybody there?"
}

이 메시지를 네트워크를 통해 수신측으로 전송하려면 위의 메시지를 바이너리 데이터 스트림으로 변환 해야 할 필요가 있다. 위에서도 계속 이야기 했지만 ASN.1은 이것을 위해 많은 방법을 정의하고 있고, 오늘 여기서는 그 방법 중 가장 간단한 방법인 Distinguished Encoding Rules (DER) 를 통해 데이터가 어떻게 인코딩 되는지 살펴 보도록 하겠다.

아래 예제는 위의 구조화된 데이터가 DER 포멧에 의해 인코딩 된 결과를 나타낸다 :

30 -- 'SEQUENCE' 임을 표시하는 태그
13 -- 전체 구조체의 길이를 16진수로 표시

02 -- 'INTEGER' 임을 표시하는 태그
01 -- 데이터의 길이를 16진수로 표시
05 -- 값

16 -- 'IA5String' 임을 표시하는 태그
0e -- 데이터의 길이를 16진수로 표시
41 6e 79 62 6f 64 79 20 74 68 65 72 65 3f -- value ("Anybody there?" in ASCII)

참고로, DER에서 사용하고 있는 방식은  tag-length-value, 줄여서 TLV 라고 부르는 방식으로, 데이터 타입, 길이 값을 한 쌍으로 하여 묶어서 표시하는 방법이다.

암튼 위의 결과로 얻어지는 바이너리 스트림은 아래 처럼 된다. :

30 13 02 01 05 16 0e 41  6e 79 62 6f 64 79 20 74  68 65 72 65 3f

그렇다면 수신 측에서는 어떻게 해야 하는가? 수신측은 송신측과 같은 인코딩 룰을 사용해야 한다. 그리고 태그를 표시하기 위해 사용되는 바이트, 길이를 표시하기 위해 사용되는 바이트 등의 정보, 태그에 해당하는 데이터 구조체에 대한 정보는 미리 공유가 되어 있어야 한다. 간단하게 말하면 수신측, 송신측 동일한 DER 규칙과, 동일한 FooProtocol을 알고 있어야만 한다는 이야기다.

그 정보들을 기반으로 하여 수신측은 위의 바이트 스트림을 원래의 'myQuestion' 객체로 되 돌릴 수 있는 것이다(사실 myQuestion과 동일한 정보를 가지고 있는 객체를 하나 복사 할 수 있다는 것이 보다 더 정확한 표현일 듯 하다).

여기 까지 간단히 ASN.1에 대한 기본 개념과 기본 인코딩 룰에 대해서 알아 보았다.
이 문서로 궁금증을 모두 다 채우지 못한 분들은 아래의 링크들을 권한다 :
 * http://en.wikipedia.org/wiki/Abstract_Syntax_Notation_One : 위키피디아. ASN.1에 대한 설명
 * http://www.ncbi.nlm.nih.gov/Sitemap/Summary/asn1.html : ASN.1 요약
 * http://support.microsoft.com/kb/252648/ko : ASN.1과 BER에 대한 간단한 소개 - 한글
 * http://blog.naver.com/shieldguy?Redirect=Log&logNo=80023719812 - ASN.1에 대해서 기본 부터 자세히 적은 한글 사이트
유익한 글이었다면 공감(❤) 버튼 꾹!! 추가 문의 사항은 댓글로!!