choiwonwoo.egloos.com
U a Thinking? U a Dream? D a Passion?

개발자마을

by choiwonwoo
카테고리
My Story & Article
My Thi/Dre/Pas
Dev Article
Dev Information(C#)
Dev Reference Site
Dev Security
Dev Web
Dev Tool
Dev Database
Dev Network
DEV C
Dev Linux
ServerDevResource
JAVA
Powered by egloos
rss

skin by 이글루스
Egloos | Log-in
Web Session ID
앞서 해킹기법에서 스니핑(sniffing)에 대해서 살펴보았다. telnet, ftp, pop3 등의 비암호화 프로토콜 어플리케이션은 스니핑 공격을 통하여 사용자 계정 및 암호 도용에 취약할 수 있음을 알게 되었다. 마찬가지로 우리가 웹 브라우징시 사용하는 HTTP 프로토콜도 이러한 도용에 취약할 수 있다.

HTTP Session Hijacking(혹은 Session ID Hijacking)이라는 공격 기법은 웹 브라우징시 세션 관리를 위해 사용되는 Session ID를 스니핑이나 무작위 추측 공격(brute-force guessing)을 통해서 도용하는 기법이다. 먼저 이러한 공격에 대한 기초적인 배경지식으로 HTTP 프로토콜의 특성 및 Session ID에 대해 이해해보도록 하겠다.


HTTP 프로토콜의 특성

HTTP는 기본적으로 비연결유지(stateless) 프로토콜이다. 반면, telnet과 ftp와 같은 프로토콜은 클라이언트와 서버 사이에 하나의 연결(session)이 성립되어 통신하는 프로토콜이다. 따라서, 우리가 보통 웹 브라우저를 열어 URL을 입력하고 해당 홈페이지에 들어간다는 것은 해당 홈페이지에 포함되어 있는 페이지(html), 그림(jpg, gif 등), 자바스크립트(js) 등을 다운받기 위해 개별적인 여러 개의 80 요청(request)을 발송한 후 서버로부터 각각의 응답(reply)

을 받는 것을 의미한다.

이러한 일련의 요청과 응답이 이루어진 후 해당 서버와의 통신은 다시 종료된다. 위와 같은 기본적인 지식을 알고 있다면 다음과 같은 질문을 할 수 있다. HTTP는 비연결유지 프로토콜이라고 하였는데 Session Hijacking 이란 공격은 어떻게 가능한 것인가? 이는 HTTP 세션 관리를 위해 사용되는 Session ID를 통해서 가능하다.


Session ID란 무엇인가?

웹 서버는 다수의 웹 페이지 요청자를 구별하기 위하여 각각의 사용자의 세션에 대해서 임의의 긴 문자열 값인 Session ID를 부여한다. 사용자가 홈페이지 방문시 혹은 인증 로그인시에 생성된다. 이러한 Session ID는 사용자의 계정, 암호, 그 밖의 IP 주소, timestamp 등의 여러 파라미터들을 조합하여 생성할 수 있다.


Session ID는 사용자와 일련의 웹 서핑 동작을 연결시켜줌으로써 웹 사이트 로그인 후 다른 페이지 방문시마다 매번 로그인을 하지 않아도 되는 편리함을 제공해준다.

우리가 신문 홈페이지나 포털 사이트에 들어갈 때 광고 배너가 자동으로 바뀐다던지, 쇼핑몰이나 인터넷 서적몰에서 구매 카트의 목록이 유지되는 것은 모두 이러한 원리이다. 즉, Session ID를 통해 인증과 인가(authentication
& authorization)라는 세션 관리를 수행할 수 있다.


Session ID는 어디에 존재하는가?

Session ID는 우리가 흔히 듣는 쿠키(cookie)라는 곳에 저장되는 것이 일반적이다. 그러나 가끔은 웹 브라우저 주소창 URL이나 HTML 페이지 폼 소스 상의 hidden 필드에 포함되어 드러나기도 한다.

1)

쿠키


2)

웹 브라우저 주소창의 URL


3)

웹 페이지 폼 소스 상의 hidden field



Session ID의 취약성은 무엇인가?

웹 서버에서의 Session ID 생성 기법 및 관리 기법에 따라서 다음과 같은 취약점이 존재할 수 있다.

  • 강력하지 못한 알고리즘(Weak Algorithm)

    : session ID 스트링 값을 생성함에 있어서 공격자가 reverse 엔지니어링이 가능한 쉬운 알고리즘으로 생성될 경우 cracking이나 brute-force guessing 공격의 위험이 있다.

  • 길이가 짧은 Session ID : 강력한 암호 알고리즘을 사용하더라도 그 길이가 충분하지 않고 짧은 경우에는 cracking이나 brute-force guessing 공격의 위험이 있다.

  • 계정 잠금 기능 미비 : 로그인 패스워드의 특정 회수 실패에 대해서는 보통 계정잠금 기능이나 해당 IP 차단 기능을 구현하고 있습니다. 그러나 보통 Session ID에 대한 무결성 침해나 특성 회수 실패에 대해서는 이러한 잠금 기능 구현이 미비하다. 따라서, brute-force guessing 공격의 위험이 있다.

  • 무한 만료의 Session ID : 사용자의 로그 아웃 이후에도 서버측에서 해당 세션 ID값을 폐기하지 않고 무한정 유효 인정한다면 cookie sniffing이나 프락시 서버의 로그 취득을 통하여 session ID 공격이 가능하다.

  • 평문으로 전달되는 Session ID : 서버에서 클라이언트로의 session ID 쿠키 전달 방식이 비암호화 방식일 경우에는 sniffing을 통하여 해당 값이 노출되어 공격 받을 수 있다. 특히 Session ID 값 자체가 사용자명이나 암호 등의 평문으로 구성되어 있는 경우에는 직접적인 공격이 가능하다.

    위와 같은 취약성에 대한 Session ID 공격의 유형은 다음과 같다.


    Session ID 공격유형

  • 직접적인 Cookie Sniffing을 통한 Session ID 도용

  • 간접 우회 공격을 통한 Session ID 도용

  • Brute-force guessing을 통한 Session ID 도용

    지금까지 Session ID가 무엇인지, 어떤 형태로 존재하는지, 왜 취약한지에 대해서 알아보았다. 다음에는 실제 공격 유형에 대해 살펴보고, 대응 방안에 대해서도 논의해 보도록 하겠다.

  • # by choiwonwoo | 2007/08/29 12:02 | Dev Web | 트랙백 | 덧글(0)
    [펌] Linux Network Engine for Online Game
    문서상태 작성: 이홍기(orinmir _at_ gmail.com)
    등록일: 2003년 4월 20일
    문서버전: 0.1.1
    수정일:
       v0.1.2 ; 2003-04-21; 문서 저작권 수정

    일러 두기 : 본 문서는 select와 rtsignal사이의 구현상의 차이점과 온라인 게임에 적합한 서버의 구조를 간단하게 정리한 문서이다. 실제로 구현을 해 본 바로는 /dev/epoll이 rtsignal보다는 좀더 안정적인 것 같았다. 그 부분에 대해서도 갱신해 나갈 예정이다.
    받기   * linux network game engine for rtsignal (doc)
      * rtsignal patch: one-sig-perfd-2.4.19.patch, one-sig-perfd-2.4.13.patch
      * /dev/epoll patch : ep_patch-2.4.19-0.32.diff, ep_patch-2.4.18-0.32.diff
    내용 Linux RealTime Signal 기반의 온라인 게임 서버 엔진의 구현

    문서 위치: http://chonga.pe.kr/computer/linux/linux-netengine/

    최초 작성일: 2002-11-05

    최종 수정일: 2003-04-21


    목차

    0. 머리말

    1. 개요 및 소개

    2. 이론 및 배경

    3. 구현 과정

    4. 결론 및 검토

    5. 참고 문헌

     

     

    0. 머리말

     본 문서의 저작자는 이홍기(orinmir _at_ gmail.com)이며, 이 곳에 사용된 자료의 내용과 자료의 그림에 대한 발췌 및 수정 후 재 배포시 저자에 대한 정보를 포함해야하며 그 때에는 저자의 허락을 받도록 한다.

     

    1. 개요 및 소개

      Linux는 OS 개발의 역사에 있어서 Open source project의 견인차 역할을 하고 있는 OS로 embedded system에서부터 고성능 서버의 OS에 이르기까지 주목 받고 있다.

      온라인 게임은 현대 게임 산업의 화두다. 지역 네트웍이나 30명 미만의 동시 접속으로만 이루어진 형태의 초기 온라인 게임에서 지금은 동시접속 1만명 이상을 처리하는 대용량 온라인 게임의 등장으로 관련 분야에 대한 관심이 높다. 실제로 온라인 게임 서버는 일반적인 네트웍 기술을 기반으로 특화된 형태의 독립서버라 볼 수 있다.

     

      온라인 게임 서버의 범주에서 볼 때, 고성능이면서 대용량의 처리를 하려면 패킷의 송수신 처리부와 데이터 처리부의 최적화가 핵심이며 이에 대한 여러가지 구현 방법이 존재한다. TCP/IP 기반의 네트웍 환경에서 일반적으로 사용되는 BSD socket의 고전적인 구현 방법으로는 select/poll을 이용한 io multiplexing(혹은 polling 방식)이 오래된 만큼 안정적이다. 하지만 이 방법은 말 그대로 kernel에서 처리되는 network io를 주기적인 polling에 의해 감시하므로 고성능 대용량 서버에서는 불필요한 CPU 부하를 유발하며 분명한 한계가 존재한다. 이에 대한 대안으로 여러 가지 vendor별 개선안이 나와있으며, linux에서는 RT Signal을 사용한 개선방법이 제공된다. 본 글에서는 이 RT Signal 방식을 이용한 네트웍 처리부를 통해 기존 방식에 비해 개선된 소켓 서버를 이용해 게임 서버의 기본 엔진을 구현에 대해 정리하고자 한다. 성능에 대한 평가는 추후 작업으로 남겨둔다.

     

    2. 이론 및 배경

      BSD socket의 태동과 함께 하나 이상의 소켓 접속을 처리하는 서버에서 사용된 방법은 io multiplexing 방식으로 select()와 poll() 시스템 콜을 통한 polling 방식이었다. 이 방법은 지금까지도 unix 서버 프로그램의 대부분에서 사용되는 방식 중의 하나이며 전통적인 unix 프로그램은 이 방식과 함께 프로그램의 구조 역시 single thread을 선호하였다. Unix kernel은 초기에 multi threaded application에 대한 지원이 없이 설계되었기 때문이기도 하다.

      현재에 이르러서는 unix에서도 SMP(Symmetric Multiprocessing) 시스템의 범용화와 더불어 posix thread를 대부분 지원하고 있고, 이와 더불어 전통적인 polling 방식이 시스템 자원의 낭비를 초래하고 있어 개선점을 찾으려는 시도가 많아졌다. 이를 해결하기 위해 표 1)과 같이 여러가지 개선 방식을 vendor 별로 지원하고 있으며, 최근에 들어서 linux에서도 여러 가지 패치를 통해 새로운 socket 처리 방식을 지원하고 있다.

     

    표 1) 소켓 서버의 vendor별 개선 방식

     

    개선 방법

    설명

    안정성

    MS

    Windows

    IOCP(io completion port)[iocp]

    GetQueuedCompletionStatus()

    호출을 통해 커널로부터 직접 socket event queue를 받음.

    대부분의 상용

    게임서버에서 채용

    Solaris

    /dev/poll

    [devpoll1]

    Poll()방식의 완벽한 대체, 장치 개념으로 처리

    sun에서 지원

    FreeBSD

    kqueue/kevent

    [kqueue]

    event poll과 유사

    안정적이라는 평

    Linux

    Realtime signal[rtsig1]

    Sigwaitinfo()호출을 통한 POLL_IN event 받음

    Signal overflow

    단점

    Realtime signal/fd

    Realtime signal 방식과 같으나

    Signal overflow 문제 해결

    몇가지 웹서버에서

    테스트 됨

    /dev/poll

    Solaris /dev/poll과 유사

    Sun의 /dev/poll

    보다 성능 월등히 떨어짐[devpoll2]

    /dev/epoll [rtsig2]

    Solaris /dev/poll과 유사

    현재 테스트 코드 나옴 /dev/poll보다 성능이 뛰어남.

     

      각 vendor별 지원 방식은 대동소이하며 방식은 커널로부터 관심 있는 socket 중, 이벤트가 있는 것만 받아오는 식이다. 기존의 polling 방식이 갖는 문제점은 single thread 기반이어서 timeout 시간을 두면서 looping을 하도록 되어 있다는 점이다. timeout 이후의 시간에 다른 processing을 할 수 있도록 하는 것이 일반적이다. 이와 더불어 최대 1000개의 소켓 접속을 받을 수 있다면, 1000개의 소켓에 대해 매 시간 polling을 하여 event의 발생 유무를 확인하도록 되어 있다.

      그림 1)과 같이 polling 방식은 Kernel space에서 가진 1000개의 소켓 정보를 그대로 User space로 복사해 온 후, 전체 목록을 들면서 비교하는 방식을 취한다. 높은 성능을 내기 위해서는 timeout 시간을 적게하여 검사시간을 짧게하여 Packet 전송, 수신 효율을 높여야하는 문제점과 사용하지 않는 소켓 정보를 모두 검사해야하는 문제점이 있다. 따라서 그림 2)와 같이 일반적으로 이 구현을 고성능 서버에서 사용하는 경우 1개의 소켓 접속만  이루어져도 이 프로세스에 의해 CPU 사용률이 90% 이상으로 증가하며, 소켓 접속이 많아지면 많아질수록 응답 속도도 떨어질 가능성이 있다.

     

    그림 1) polling 방식(select() )과 RTsignal 방식의 비교

     

    그림 2) polling 방식의 구현 예

      본 글에서 Linux의 RTSignal을 도입하게 된 것은 기존 방식의 대안 중 하나이면서 linux kernel 2.2부터 RealTime Signal(Posix RealTime Signal)을 지원하기 시작했기 때문이다. Linux의 RT signal방식은 과부하 상황에서 overflow가 일어나는 기존 signal 기반 프로그램들보다는 명확하게 polling 방식을 대체할 수 있는 방법이다. (poll()에서 사용하는 POLL_IN, POLL_OUT, POLL_ERR 등을 그대로 사용할 수 있다.) RT Signal의 장점이라면, signal을 등록해놓고 해당하는 이벤트가 발생하기 전까지는 sigwaitinfo system call을 통해 대기하고 있다가, 이벤트가 발생하면, 정해둔 signal handler를 통해 처리를 하며 timeout도 지원한다. 기존의 구현 방식에 비해 낮은 CPU점유율과 빠른 응답 속도, high load에서도 안정되고 일관된 성능을 유지하고 있다. 이러한 방식을 또한 event-dispatch 방식이라고도 한다. [rtsig3]

      하지만 기본적으로 제공되는 RT Signal의 단점은 제한된 signal resource로 인해, 고부하에서 signal overflow가 되면 더이상 새로운 접속을 처리할 수 없게 된다. 이 때에는 기존의 poll()쪽으로 처리를 돌려 해결하는 혼합된 구현 방법을 함께 쓰기도 한다. 기본적으로 linux에서 지원하는 방법은 기존의 polling 방식과 병행해야하는 문제점이 있다.[phhttpd] 최근에 이르러 이를 극복한 방법으로 1개의 file descriptor당 하나씩 signal을 할당하고 그 개수 만큼 가지게 하여, 자원 만큼을 수용할 수 있는 방식의 패치가 Luban에 의해 제안되었다. 이 프로젝트에서는 이 방식을 사용하여 작성하기도 결정하였다.

      타 OS의 개선 방법에 비해 linux에서 새로 도입된 이 방식은 EWOULDBLOCK 등에 대한 에러 처리를 지원하지 않기 때문에 이에 대한 것을 설계 시점에서 같이 해주어야 했다. 따라서 그림 3)과 같은 producer/consumer구조를 도입했다. 우선 IO Event Queue를 두어 같은 형태로 POLL_IN, POLL_OUT, POLL_REMOVE를 처리하도록 하였는데, 이 구조는 INPUT event는 sigwaitinfo()의 호출에서 POLL_IN에 해당하는 socket read event가 발생하였을 경우에 wake up이 되고 IO Event Queue에 push함으로써 thread의 기반 구조에서 producer의 역할을 하게 된다. 마찬가지로 게임 서버가 실행되면서 이벤트가 발생하는데 이때 POLL_OUT이라면 이에 해당하는 socket write event로 정의하고 객체의 object가 제거되면 POLL_REMOVE에 해당하는 socket close event를 발생시켜 IOEvent Queue에 producer thread의 역할을 하게 된다. Consumer thread는 Event Dispatching Thread를 통해 IO Event Queue를 pop을 하여 각각의 경우를 read(), write(), close()에 대응시켜 이벤트를 처리하며, 각각의 시스템 콜에서 EWOULDBLOCK과 같은 socket error를 만나면 또 다시 IO Event Queue에 그 상황에 맞는 Event를 만들어 다시 넣어주는 과정을 통해 소켓의 reading/ writing buffer 제어를 해준다.

    그림 3) RealTime Signal I/O의 구현

      결론적으로 RTSignal 방식을 사용함으로써 기존 방식에 비해, 시스템 자원을 효율적인 활용 할 수 있고, event dispatch방식으로 threaded application에 적합한 구조로 쓰여질 수 있다. 예상되는 문제점으로는 threaded application이 갖는 성능 공유 객체에 대한 thread간 경쟁에 대한 성능 배분을 어떻게 최적화하느냐에 따라 성능이 크게 좌우될 가능성이 높다.


    3. 구현과정

     

      앞서 설명한 RT signal을 이용한 소켓 서버의 개선 점을 토대로 polling 방식과 RealTime Signal을 이용한 I/O 부분을 각각 구현하여 기본 소켓 서버를 구현한다. 게임 서버의 기본이 되는 게임 객체 처리와 Packet 분석 및 처리 과정을 통한 게임 서버 엔진을 만들고 엔진 성능 테스트를 위한 더미 클라이언트를 만든다.

     

    개발 환경

     

    Server

    Client

    비 고

    OS

    Linux

    Kernel 2.4.19

    Microsoft Windows

     

    Compiler

    Gnu c/c++ 2.95.2

    Borland C++ Builder 5

     

     

     Server 의 설정

     Server에서 linux kernel은 2002년 11월 25일 현재 최신 안정 버전인 2.4.19를 사용하였다.[liinuxknldn] 대부분의 network server는 socket을 기반으로 하고 있으며, kernel에서 설정하는 socket 개수은 file descriptor의 한계에 따라 제한된다. 따라서 이에 대한 kernel 설정 작업은 필수적이다. 또한 Realtime signal을 사용하기 위해서는 Realtime signal per File descriptor 에 대한 패치를 해야한다. Kernel의 설정과 함께 /dev/epoll 에 대한 세팅도 할 수 있으며 참고적으로 추가했다.

     

     

    내 용

    Max socket 설정

    에 대한

    Kernel 수정

     

    include/linux/fs.h:

      increase NR_FILE from 4096 to 65536 

      increase NR_RESERVED_FILES from 10 to 128

     

    fs/inode.c:

     increase MAX_INODE from 16384 to 262144 

    참고: MAX_INODE는 NR_FILE의 3배정도 (2.4.19에서 max없음)

     

    Include/linux/limits.h

      NR_OPEN->15000

    Rtsignal per fd

    Luban ‘s patch 적용 [rtsigdn]

    dev/epoll

    Eventpoll 적용 [epolldn]

    Realtime Signal과 더불어 eventpoll도 함께 패치를

    적용하고 아래와 같이 char 장치를 하나 만든다.

    mknod /dev/epoll c 10 124

    Sysctl 설정

    echo 20 > /proc/sys/net/ipv4/tcp_fin_timeout

    echo 8192 >  /proc/sys/net/ipv4/tcp_max_syn_backlog

    echo 1200 > /proc/sys/net/ipv4/tcp_keepalive_time

    echo 1 > /proc/sys/net/ipv4/tcp_syncookies

    Shell 설정

    Shell에서 설정한 socket max에 대해 재설정을 해주어야한다

    $ ulimit –n 15000

     

     

      프로젝트는 크게 Server Engine과 ClientEngine 부분으로 나눌 수 있다. (표2) 참조.) 프로젝트의 이름은 물고기 등을 몰면서 논다는 의미의 몰이와 놀이의 합성어로 MoriNori(몰이놀이)로 지었다.

     

    표 2) 프로젝트 모듈 설명

    프로젝트 폴더

    내용

    파일 명

    ServerEngine

    자료구조 및 Packet 정보 등 의 공유 라이브러리

    Queue* , DLinkList*, BST*

    MAP은 n x n 2차원 좌표계 구조로 지원

    Map*

    Packet 처리부

    PacketParser*

    소켓과 소켓서버에 대한

    라이브러리

    Socket*

    SocketServer*

    Network*

    게임 기본 객체의 처리

    ServerBasic*

    ClientEngine

    서버와 네트웍 쪽의 기본라이브러리는 공유하며 더미 접속클라이언트 기능과 객체 동기 테스트 기능

    *

     

     그림 3)의 Realtime signal의 I/O를 Network 라이브러리에 구현을 한 상태로, 사용자 접속을 받아 소켓 버퍼를 제어하게 되면, 그 다음으로는 Game에서 쓰이는 Packet 형태로 가공을 하게 되는데, 그림 4)에서 Network Module에서 Input Packet과 Output Packet의 형태로 CPacket class를 통해 게임으로 들어오고 나가는 Packet이 관리된다. 이 때, 사용자로부터 입력된 Packet을 실제로 소비하는 부분이 Packet Parser이며 Game Object Loop에서 다시 사용자에게 보내지는 Output Packet을 발생시킨다. Packet Parser를 통해 유입된 Packet은 Game Object Loop를 통해 PC(Playerable Character, 사용자가 조종하는 객체) 객체의 행동을 담당하게 되며, 컴퓨터 인공지능으로 PC가 아닌 다른 MONSTER 객체를 처리하게 된다. 또한 Game Global Loop에서 게임내에서의 날씨 변화 등에 대해 처리하며, Output Packet에 영향을 미친다. 여기까지 2가지 Game Loop가 등장하는데 이 것에는 tick이라는 단위가 도입되는데, 이 tick은 한 Loop당 1/10 sec 와 같은 현실적인 Loop 수행에 관련된 응답 시간이 요구된다. 이 tick을 통해 게임내 객체는 tick단위의 동기화가 일어난다.

    그림 4) 게임 서버의 구조

      게임 클라이언트의 구조는 게임 서버의 구조와 어느 정도는 일치하지만, 대용량의 사용자를 처리하는 개념이 아닌 나 자신이 조종하는 PC 객체의 시야 범위 내에서의 객체 이동에만 관심이 있으므로 네트웍 부분과 Packet 처리에 있어서는 간소화 된다.

     

    그림 5) 게임 클라이언트의 구조

     

    서버 엔진의 구현

     

    [기본 라이브러리]

      프로젝트 초기에 기본적인 자료구조와 쓰레드 관련 함수들은 c++기반으로 작성하였다. 기본적으로 class기반의 SGI에서 나온 standard template library(stl)에서 자료구조를 제공하고 있지만 코드의 간명함과 threaded application에서의 저수준에서의 최적화, 실행 바이너리 사이즈를 줄일 수 있는 장점이 있어 대부분을 직접 구현 하였다. Thread에 관련된 라이브러리는 기존의 c thread library로 정의되어 있는 pthread_* 부분을 class로 감싸주었다.[pthread]

     

    클래스 이름

    설명

    비고

    CMutex

    객체 상호배제 lock/unlock

     

    CRWLock

    Read/Write Lock

     

    CCondition

    Condition 동기

     

    CThread

    Posix thread의 create

    Join, schedule 등을 감싼

    Thread 라이브러리

     

    CThreadWrapper

    Thread의 startup 동기 지원

    CThread를 감쌌다.

    CQueue

    Locked Queue

    CMutex

    Condition

    CQueueLockedPBuffer

    Multiple pop queue를

    지원한 Locked Queue

    기존 CQueue에 array로

    여러개를 pop

    CQueueBuffer

    BYTE Buffer처리를 위한

    Queue

    Socket Buffer로 사용

    CDLinkedList

    기본 적인 Locked List

     

    BST

    Locked Binary Searching Tree

     

     

     

    [네트웍 엔진의 구현]

      게임 서버에서의 네트웍 엔진은 일반적인 네트웍 서버의 형태를 따르며, 몇가지 측면에서 성능 개선 위한 방식을 사용한다. 기본적으로 본 프로젝트에서는 비교하고자하는 polling방식과 RTSignal 방식의 큰 차이가 있고, 의사코드에서 보는 바와 같이 client별로 socket을 Add/Delete해주는 Do_AddSocket(), Do_CloseSocket()과 buffering을 해주는 Do_Read(), Do_Write와 같은 부분은 서로 공유하게된다. socket을 accept하는 부분의 부하를 줄이기 위해 하나의 독립된 thread로 처리하였다.

     

     accept thread의 의사코드(pseudo-code)

    while(1)

    {

        s = accept ( serversocket)

        if (is_valid_socket(s) ) {

            Do_AddSocket(s);

        }

    }

     

     Polling 방식은 관심이 있는 Socket 정보를 서버에서 처리할 수 있는 MAXSOCKET의 FD list에 FD_SET 명령을 사용하여 세팅하고 select() 시스템호출을 통해 넘겨받은 결과 개수에 따라 다시 MAXSOCKET 만큼을 반복하면서 FD_ISSET으로 어떤 종류의 event인지 검사하는 구조다.

     

     select polling의 의사코드

    while(1)

    {

         // socket fdset recompute

    FD_ZERO(INPUTFD); FD_ZERO(OUTPUTFD); FD_ZERO(EXCEPTFD)

        For ( s=0 ;s<= MAXSOCKET;s++) {

             If (is_valid_client_socket(s) )  {

                 FD_SET(s,INPUTFD);

    FD_SET(s,OUTPUTFD);

    FD_SET(s,EXCEPTFD);

             }

        }

        resultcount = select (MAXSOCKET+1, INPUTFD, OUTPUTFD, EXCEPTFD, TIMEOUT{sec=0,usec=1000});

     

    For ( s=0 ;s<= MAXSOCKET && resultcount>0 ;s++) {

             If (is_valid_client_socket(s) )  {

                 If (FD_ISSET(s,INPUTFD)) {

    resultcount --;

                      Do_read(s); // 실패시 socket 삭제

                 }

    If (FD_ISSET(s,OUTPUTFD)) {

    resultcount --;

                      Do_write(s); // 실패시 socket 삭제

                 }

    If (FD_ISSET(s,EXCEPTFD)) {

    resultcount --;

                      Do_ReadOOB(s); // Out of Bound 긴급 패킷(거의 쓰이지 않음)

                 }

         } // for

    } // while

     

     RTSignal은 socket의 생성과 소멸시에 추가적인 작업이 필요하며 Signal 처리 thread에서Socket IO Event Dispatch에서 사용될 POLLIN/POLLOUT/POLLREMOVE에 해당하는 IOEvent를 생성하며, 게임 루프에서 클라이언트로 패킷을 만들어 내거나 강제로 삭제해야하는 경우 그때 마다 POLLOUT/POLLREMOVE IOEvent를 생성하게된다. 이렇게 생성된 IOEvent는 Event Dispatch Thread 의사코드와 같이 이를 통해 소비된다. 모든 IO Event Queue에서 pop 처리는 CQueueLockedPBuffer를 사용하며 array로 query하여 한꺼번에 처리해여 함수 호출에 대한 overhead를 줄이도록 하였다.

     

     RTSignal에서의 Do_AddSocket 호출시에 추가해야하는 정보

    fcntl(SOCKETFD, F_SETFL, O_RDWR | O_NONBLOCK | O_ASYNC);
    fcntl(SOCKETFD, F_SETSIG, SIGRTMIN);
    fcntl(SOCKETFD, F_SETOWN, getpid()); // pid는 sigwaitinfo가 일어나는 thread pid

    fcntl(SOCKETFD, F_SETAUXFL, O_ONESIGFD);

     

    RTSignal에서의 Do_CloseSocket 호출시에 추가해야하는 정보

    fcntl(SOCKETFD,F_SETFL,O_RDWR);

     

    RTSignal에서의 Signal 처리 Thread 의사코드

    While (1) {

    sigemptyset(&signalset);

        sigaddset(&signalset,SIGRTMIN);

        pthread_sigmask(SIG_BLOCK, &signalset, NULL); // pthread signal block 무시하기

    signum=sigwaitinfo(&signalset,&siginfo);

    if (signum==SIGRTMIN) {

         SOCKETFD=siginfo.si_fd;

         revents=siginfo.si_band;

         si_code=siginfo.si_code;

    if (si_code==POLL_IN) {

           if (revents & (POLLIN)) {

                insertIOEvent(SOCKETFD,RTSIG_EVENT_POLLIN)

           }

         else if (si_code==POLL_OUT) {

    if (revents & (POLLOUT)) {

                insertIOEvent(SOCKETFD,RTSIG_EVENT_POLLOUT)

           }

         }

         else {

    insertIOEvent(SOCKETFD,RTSIG_EVENT_POLLREMOVE)

         }

    }

    } // while

     

    RTSignal에서의 IO Event Dispatch Thread 의사코드

    While (1) {

    IOEvent = POP_IOEVENT_FROM_QUEUE();

        If (IOEvent.event == RTSIG_EVENT_POLLIN) {

            Do_Read(IOEvent.SOCKETFD);

        }

       else if (IOEvent.event==RTSIG_EVENT_POLLOUT) {

           Do_Write(IOEvent.SOCKETFD);

       } else {

           Do_CloseSocket(IOEvent.SOCKETFD);

       }

    } // while

     

     

    [서버의 객체 처리]

     빠른 응답 속도를 위해 UserID를 기반으로하는 BST(Binary Searching Tree)와 SocketID와 UserID에 대응하는 array를 통해 searching 최적화를 시도하였다. 2진 트리로 구성하면 검색 시간이 2분 검색과 같은 0(log2n)이 되고 자료의 집합이 유동적일 때 행렬이나 리스트를 이용하는 것보다 효율적이므로 사용자의 접속이 순차적인 순서가 아닌 유동적인 접속이 이루어지므로 사용자 객체의 목록 관리에 BST를 사용하였다.[ds]

     사용자의 객체를 찾기 위해서는 다음과 같은 과정을 거친다

     

    순서

    내용

    속도

    1

    SocketID로 UserID를 찾음

    배열검색(O(1))

    2

    UserID의 객체 검색

    BST검색(O(log2n))

     

     

    [패킷의 정의와 처리]

      여기서 정의한 게임 패킷은 3 byte의 Header part와 가변 길이의 Data part로 구성되며 structure 기반의 Packet 정의와 메모리 복사를 통한 빠른 Packet 생성을 고려하여 작성되었다. 서버상에서의 패킷은 CPacket 클래스를 통해 socket 정보를 포함한 Packet 정보를 사용한다.

     

    패킷의 정의

    Header

    Data

    CMD(1B)

    LENGTH(2B)

    BODY (Header LENGTH BYTE)

     

     

    Packet 처리 Thread의 의사코드

    While (1) {

    PacketArray = POP_PACKET_FROM_INPUTQUEUE();

    For (PacketArray loop) {

        Packet = PacketArray(NowIndex)

        Switch (GETPKTNO(Packet)) {

            Case ADD: processAddPacket(); break;

    Case DEL: processDelPacket(); break;

    Case MOVE: processMovePacket(); break;

    Case CHAT : procesChatPsacket(); break;

            }

    } // for

    } // while

     

     

    [맵에서의 게임 객체 동기화 처리]

     게임 객체는 게임상에서 자신의 등장을 주변에 알릴 필요가 있으며, 움직임이나 채팅 메시지와 더불어 다른 객체들과 동기를 맞출 필요가 있다. 일반적으로 게임내에서의 객체 동기는 시야범위 내로 한정하며 여기서는 240x240 평면을 하나의 시야범위로 처리하였다. 실제적으로 동기의 범위가 아래 그림과 같이 4x4 평면에서 검은색 좌표를 중심으로 1의 거리 만큼을 가진다면, 동기되어야할 객체는 맵 상에서 자신의 영역인 0을 포함한 9개의 블럭내에 있는 객체와의 동기가 이루어져야 한다.

     

    2

    2

    2

    2

    1

    1

    1

    2

    1

    0

    1

    2

    1

    1

    1

    2

     

     서버에서의 메시지 패킷의 전달 체계를 2가지로 나누어 놓았는데, sendSinglecast와 sendMulticast의 함수로 MessageManager에 포함되어 있다. sendSinglecast는 메시지를 받는 객체가 하나인 경우이고 sendMulticast인 경우는 시야범위내 동기 객체가 있을 경우에 사용하게 된다. 위의 시야 범위 동기를 예로 든다면 맵 상에서 영역 내에 등록된 객체의 목록(보통 UserID의 List)을 가져와 sendMulticast에서 이 목록을 참조해 정보 전송을 통해 객체 동기화를 한다. 현재는 전체 맵을 대상으로 시야 범위 동기하도록 구현되어 있다.

     

    [서버의 실행]

      ServerProject를 빌드하면 serverengine 이라는 binary 파일이 생성된다. 서버의 실행

    방법은 다음과 같다.

     

    testclient# ./serverengine

    MoriNori Game Server Engine : ver. 2002

     

    Usage : serverengine svrtype [maxsocket]

      svrtype

        1 : SELECT

        2 : RTSIG

        3 : DEV/EPOLL (test in progress)

     

      maxsocket default value is 1024

     

    testclient# ./serverengine 1

      (SELECT모드의 서버로 동작)

     

     

    더미 클라이언트의 구현

     더미 클라이언트는 스트레스 테스트 클라이언트와 게임 클라이언트의 두 가지 기능을 지원하는 프로그램으로 구성하였다. 클라이언트를 빌드하면 MoriNoriClient.exe 파일이 생성되는데 Windows 운영체제에서 이를 실행하면 더미 클라이언트 윈도가 나타난다.

     

    [스트레스 테스트 클라이언트]

      스트레스 테스트 클라이언트는 다수의 접속된 클라이언트를 다루기 위해 select를 이용하였다. select의 동작 방법은 이미 설명한 바 있으며, 여기서는 Packet의 송수신 속도를 측정하기 위해, 패킷을 보낼 때, 시간 태그를 설정하고 그에 대한 응답을 받았을 때 Packet 송수신 시간을 측정 한 후 계산하도록 하였다. Packet의 송신 량은 아래 그림과 같이 SendTick(ms)에서 기본값 1000ms(1초)을 주도록 하였고 테스트시에 1ms에서 2000ms 사이의 값을 넣어 주게 하였다. 이 와 더불어 select의 polling timeout값을 조절해주어야하는데, send tick보다는 낮은 값을 대입해야한다. 적절한 테스트 성능을 내기 위해서는 select timeout을 sec/usec 설정을 0/1000으로 설정한다.

     

    그림 6) 스트레스 테스트 클라이언트

     

    [객체 동기 테스트 클라이언트]

     본 프로젝트의 게임 서버 엔진으로서의 기능을 테스트하기 위한 엔진 테스트용 클라이언트를 만들었다. 기본적인 객체의 추가 삭제와 시야범위 내 이동 테스트를 통한 객체 동기와 채팅 메시지를 주고 받는 기능을 갖고 있다. 그림 5)의 클라이언트 엔진의 구조를 토대로 구현하였다. 게임 클라이언트에서 사용된 Socket은 blocking mode로 packet reading을 위한 read socket thread 를 두어 Packet Parser와 합친 상태로 서버로부터의 packet 송수신을 처리하게 하였고 검은 색 바탕을 가진 게임 Stage는 1초에 한번씩 화면을 갱신하도록 하였다.

     

     그림 7)은 2개의 Client를 띄워서 객체 동기를 테스트 한 예다.

    그림 7) 객체 동기 테스트 클라이언트

     

    4. 결론 및 검토

     지금까지 polling방식과 RTSignal 방식을 지원하는 네트웍 엔진을 구현하고 그것을 토대로 게임 서버의 엔진 구현과 더미 테스트 클라이언트를 작성하였다. 그리고 더미 테스트 클라이언트의 스트레스 테스트 기능을 이용한 네트웍 엔진의 성능 평가는 충분치 않아 보류하였다.

     

     네트웍 엔진으로서의 관점에서 볼 때 Polling방식은 RTSignal방식에 비해 시스템 자원의 대부분을 소비하고 있었으며, 1CPU 서버 시스템에서는 이 프로세스에 의해 거의 100%에 가까운 사용량을 보이며 다른 처리 Thread의 task 수행 시간이 현저히 줄어들어 어느정도 한계가 있음을 확인 할 수 있다. RTSignal의 경우는 단위 시간당 클라이언트의 접속에도 CPU 사용률에는 변화가 없었으며, 부하 클라이언트의 접속 후, 패킷의 송수신 부하 시에 5Mbps수준에서 25%정도의 CPU사용률을 보였으며 접속자 수와 송수신 부하량에 따라 서서히 증가함을 볼 수 있다. 게임 서버 엔진의 관점에서 보더라도 객체의 처리에서 오는 게임 프로세스상의 부하 점이 존재하기 때문에 SMP시스템이라면 성능이 어느정도 보장되지만 UP(UniProcessor)에서는 그 성능을 보장하기가 힘들다는 결론이 나온다. 따라서 RTSignal이 더 구현상으로는 유리하다고 볼 수 있다. Event 처리에 관련된 부분을 적용해본 결과 이 것에 적용한 Event Dispatching 구조는 특히 Multi threaded application의 thread간 메시지 전달 구조에 알맞다는 것을 알 수 있었다. 물론 Multi thread 구조가 Single thread 구조에 비해 더 나은 것은 테스크의 효율적인 할당과 여러 개의 CPU에 대한 스케쥴링의 효율성 때문이다. 하지만 객체를 공유하기 위해 공유 객체에 대한 locking 객체의 경쟁과 이벤트 발생에 드는 메모리 생성 속도 최적화에 따르는 설계의 어려움이 따르기 때문에 성능 비교에 있어 객관성을 떨어트릴 수 있는 부분이라고 생각한다.

     

      테스트 시에 발견한 RTSignal의 문제점은 아직 버그가 존재하기 때문에 안정성에서 기존 방식에 비해 부족함을 확인하였다. Socket 객체에 대한 Signal을 등록하는 시점과 등록된 시점 사이에 일어나는 event를 감지하지 못하기 때문에 그 사이에 들어온 이벤트는 무시된다. 이는 accept()에 관련된 새로운 시스템 호출을 도입하는 것으로 해결이 가능할 것 같다. 그리고 socket close시에 그에 대한 event가 종종 무시되어 CLOSE_WAIT으로 무한 대기를 하게 되는 경우도 있다. 이 경우에 대해서는 현재는 주기적인 socket의 유효성을 검사하는 코드를 추가하여 해결할 수 있지만 추후 개선이 필요한 부분이다.

     

     그럼에도 불구하고 고전적인 polling 방식을 벗어나 RTSignal과 같은 새로운 방식이 이미 다른 OS에서도 지원되거나 요구되고 있다. Linux에서 지원하는 RTSignal이 안정성이 확보된다면 자원의 효율적인 사용은 하드웨어의 비용적인 측면과 Multi threaded application에 적합한 구조의 개발 측면에서도 부합한다는 결론을 내렸다.

     

      이번 구현을 통해 네트웍 엔진에 대한 성능 평가와 게임 서버 엔진으로서의 기본적인 토대를 마련할 수 있었다. 네트웍 엔진에 대한 성능 평가에 초점을 두었기 때문에 실제적으로 중요한 게임 객체 동기화에 따르는 수행속도 최적화와 그에 대한 부하 조절 부분에 대한 구현과 성능 평가는 좀 더 고민해야할 과제다.

     


    5. 참고 문헌

     

    [iocp] Writing Windows NT Server Applications in MFC Using I/O Completion Ports

        http://chonga.pe.kr/computer/programming/ms/windows_iocp.html

     

    [devpoll1] A scalable and explicit event delivery mechanism for UNIX

        Gaurav Banga gaurav@netapp.com

        Network Appliance Inc., 2770 San Tomas Expressway, Santa Clara, CA 95051

        Jeffrey C. Mogul mogul@pa.dec.com

        Compaq Computer Corp. Western Research Lab., 250 University Ave., Palo Alto, CA,

    94301

        Peter Druschel druschel@cs.rice.edu

        Department of Computer Science, Rice University, Houston, TX, 77005

     

    [rtsig1] CITI Technical Report 00-4 : Scalable Network I/O in Linux

        Niels Provos, University of Michigan <provos@citi.umich.edu>

        Chuck Lever, Sun-Netscape Alliance <chuckl@netscape.com>

     

    [kqueue] Kqueue: A generic and scalable event notification facility

        Jonathan Lemon jlemon@FreeBSD.org FreeBSD Project

        http://people.freebsd.org/~jlemon/papers/kqueue.pdf

     

    [rtsig2] Analysis of RealTime Signals for Highly Concurrent Network I/O

        http://squid.visolve.com/developments/squid_rt_whitepaper.htm

     

    [c10k] Client 10000 project

        http://www.kegel.com/c10k.html

     

    [rtsig3] Scalability of Linux Event-Dispatch Mechanisms

        http://www.hpl.hp.com/techreports/2000/HPL-2000-174.html

     

    [phhttpd] zach brown's phhttpd using rtsignal

        http://www.zabbo.net/phhttpd/

     

    [devpoll2] Microbenchmark comparing poll, kqueue, and /dev/poll - 24 Oct 2000

        http://www.kegel.com/dkftpbench/Poller_bench.html

     

    [ds]

      Functionmental of Datastructure in C++ , HOROWITZ 외, Computer Science Press.

     

    [pthread]

      David R. Butenhof, Programming with POSIX Threads. Addison-Wesley, ISBN 0-201-63392-2.

     

    [linuxknldn]

      linux kernel 2.4.19 download

    http://www.kernel.org/pub/linux/kernel/v2.4/linux-2.4.19.tar.gz

     

    [epolldn]

      http://www.xmailserver.org/linux-patches/nio-improve.html#patches

     

    [rtsigdn]

      http://squid.visolve.com/developments/one-sig-perfd-2.4.x.patch

    # by choiwonwoo | 2007/08/14 09:54 | ServerDevResource | 트랙백 | 덧글(0)
    한글문제

    컴퓨터 속에서 맨날 한글을 봐오고 있으면서도 막상 한글 코드에 대해서 관심 있어 하는 프로그래머는 그리 많지 않은 듯 싶다. 그리고 관심을 가진다고 해도 잘 정리된 문서가 없는 듯 싶어서 내가 아는 내용을 살짝 정리해 봅니다.

    우선 한글은 조합형, 완성형, 확장 완성형, iso2022-kr, unicode 등으로 표현이 가능하며… 조합형, 완성형, 확장 완성형, iso2022-kr 등은 symbol table 과 한자 테이블 또한 가지고 있지만 여기서 관련된 내용은 거의 얘기하지 않을 겁니다.

    1. 조합형 (Johab)

      ASC II 범위에 있는 글자는 그대로 프린트하고 한글인 경우 MSB 를 1로 세팅하고 나머지 비트를 초성(5bit) / 중성(5bit) / 종성(5bit) 을 표현하는데 사용한다. 이론 상으로 한글 11172 자를 모두 표현해낼 수 있으며 한글 입력을 처리하기가 아주 쉽다. 다만 Microsoft 에서 완성형을 선택함에 따라 잊혀진 인코딩이 되어가고 있다.

    2. 완성형 (EucKR)

      ksx1001 에 정의되어 있으며 역시나 ASC II 범위의 글자는 그대로 프린트 한다. 한글의 경우 연속된 두 개의 바이트를 이용해서 표현하게 되며 첫번째 바이트와 두번째 바이트 모두 0xA1~0xFE 사이의 값을 가진다.

      한글은 2350 자 밖에 지원하지 않지만 MS windows 에서 선택함에 따라 널리 사용되고 있다.

    3. 확장완성형 (Unified Hangul Code)

      Microsoft 에서 EucKR 에 몇 가지 글자를 더 추가한 인코딩으로 UHC, cp949 등으로도 불린다. 빈 공간에 글자를 추가해 넣었기 때문에 바이너리 값 그대로 정렬을 시도할 경우 한글의 가나다라 순서대로 정렬되지 않는 문제가 있다.

      EucKR 과 마찬가지로 한글을 표현하는데는 2바이트를 사용하며 첫번째 바이트는 0×81~FE 사이 두번째 바이트는 0×41~5A, 0×61~7A, 0×81~FE 영역을 차지한다.

    4. iso2022-kr

      EucKR 을 7bit 만 사용하며 표현하는 방식으로 RFC1557 에 정의되어 있다. Designator Sequence (0×1B 24 29 43), SO (0×0E), SI (0×0F) 등을 이용해 EucKR 을 7bit 로 변환시킨다.

      Designator sequence 는 non ASC character 를 만나기 전에 아무 때나 한 번만 나와주면 되며, non asc character 를 만나면 SO 를 출력 후 다시 asc character 를 만날 때까지 0×7F 와 AND 연산을 해서 출력한다. (MSB 를 reset) 그러다가 asc character 를 만나게 되면 SI 를 찍고 나서 다음 글자들을 프린트하면 된다. 이런 과정을 반복하면 EucKR 은 iso2022-KR 로 변환된다.

      그 과정을 pseudo code 로 표현하자면 (위에 설명이 좀 복잡하게 보이는데 실제로 보면 간단하다.)

      print 0x1B 0x24 0x29 0x43 // Designator Sequencestats = ascwhile( char = get_next_char() ){    if( stats == asc ){        if( char & 0x80 ){            print 0x0E // SO            stats = non_asc        }    }    else{        if( !(char & 0x80) ){            print 0x0F // SI            stats = asc        }        else            char &= 0x7F;    }    print char}

      (위의 pseudo code 에서는 Designator Sequence 를 맨 앞에 출력을 했지만 iconv 등에서는 처음으로 non asc character 를 만났을 때 출력하고 있다.)

    위의 네가지 인코딩 이 그동안 많이 쓰여왔던 인코딩 들인데 국제화 시대인 지금은 오로지 한글만을 표현할 수 있는 저런 인코딩으로는 뭔가 부족하다. 그렇기 때문에 유니코드 콘소시움에서는 여러가지 언어를 함께 표현할 수 있도록 unicode 라는 글자집합(character set)을 만들어 냈으며, 유니코드를 표현하는 5가지의 encoding 을 제공하고 있다. (ucs2, ucs4, utf-7, utf-8, utf-16)

    1. ucs2

      2바이트 고정형 인코딩, unicode 와 4.0 버젼과 동일하다. Endian 관련해서 Big Endian 과 Little Endian 으로 표현이 가능하다.

    2. ucs4

      4바이트 고정형 인코딩. 길이를 제외하곤 ucs2 와 거의 동일하다.

    3. utf-7

      unicode 의 mail safe version. RFC1642 에 정의되어 있다. BASE64 와 비슷한 방식을 통해 unicode 를 7bit 로 표현하게 된다.

    4. utf-8

      가변형 인코딩으로 1바이트영역은 Asc II 와 100% 호환된다. 0×00 이 사용되지 않으므로 전통적으로 C 언어에서 사용해온 null terminated 방식을 사용하는데 문제가 없고 2바이트 이상을 사용하는 경우 특수한 규칙을 가지고 있기 때문에 validation 이 가능하다.

    5. utf-16

      ucs2 와 ucs4 를 적절하게 혼합해서 사용하는 방식으로 BMP (Basic Multilingual Plane) 에 들어있는 글자는 2 바이트로 표현하게 되고 그 외의 글자들은 4 바이트를 이용해서 표현하게 된다.

    utf-7 과 utf-8 을 제외하고는 byte order 가 중요시 되기 때문에 BOM(Byte Order Mark) 를 문서 맨 앞에 삽입해야 한다. 그렇기 때문에 Unicode 로 작성된 텍스트 파일의 경우 BOM 을 이용해 어떤 인코딩을 사용하는 지지 알아내는게 가능하다. (utf-8 을 위한 BOM 도 존재하지만 utf-8 의 경우 Byte Order 가 정해져 있기 때문에 BOM 을 의무적으로 삽입할 필요는 없다.)

    EncodingUTF-8UTF-16BEUTF-16LEUTF-32BEUTF-32LE
    ‘가’EA B0 80AC 0000 AC00 00 AC 0000 AC 00 00
    Smallest code point00000000000000000000
    Largest code point10FFFF10FFFF10FFFF10FFFF10FFFF
    Code unit size8 bits16 bits16 bits32 bits32 bits
    Byte orderN/Abig-endianlittle-endianbig-endianlittle-endian
    Byte order markEF BB BFFE FFFF FE00 00 FE FFFF FE 00 00
    Minimal bytes12244
    Maximal bytes44444

    대강 ucs2, ucs4, utf-8, utf-16, utf-32 의 특징을 정리하면 위의 표와 같다. UTF-8 의 경우엔 ASC II 와 호환이 되기 때문에 영어권 언어들에서 별다른 조작 없이도 문제를 일으키지 않게 되므로 널리 쓰이고 있다. UTF-8 과 UCS2 사이의 변환은 아래와 간단한 규칙을 통해 이루어지게된다.

    1. 0×00~0×7F 까지는 그냥 표시한다.
    2. 0×80~07FF 까지는 B110xxxxx 10xxxxxx (2바이트)
    3. 0×0800-FFFF 까지는 B1110xxxx 10xxxxxx 10xxxxxx (3바이트)
    4. 이후는 UCS4 영역이고 위와 같은 방식으로 4바이트까지 확장됩니다.

    보다시피 ASC II 는 그대로 표현하고 있습니다. 그리고 2바이트 이상을 사용하는 문자에서는 2진수 기준으로 앞에 붙어있는 1의 개수가 그 글자를 표시하는데 사용된 바이트 수를 나타내며, 2번째 바이트부터는 맨 앞에 10 을 붙여줌으로 이건 글자의 시작이 아니라는 걸 표시하게 됩니다. 위의 두 규칙을 지키면서 unicode 를 2진수로 바꾸어 xx 로 표시된 영역에 차례로 배치하게되면 ucs -> utf-8 변환은 끝이 납니다. 한글은 UTF-8 로 표현하게 될 경우 한 글자 당 3 바이트 씩을 차지하게 됩니다.

    그리고 이 유니코드에서 한글이 차지하는 영역은 아래와 같습니다.

    1. U+1100: 조합형 영역

      첫가끝 코드라는 이름으로도 불리고 있으며 초성(첫), 중성(가운데), 종성(끝)이 각기 다른 영역에 배치되어 있다. 이 영역에 있는 글자들을 이용하면 한글 고어까지도 표현이 가능해진다.

      한글 한 글자를 표현하는데 많은 저장공간이 필요하다는 점과, iconv 에서 첫가끝 영역 -> Euc-KR, iso2022-kr, UHC 로의 변환이 불가능한 점 등이 약간의 문제라고 생각됨.

    2. U+3130: 한글 자모 영역

      ㄱ,ㄴ,ㄷ,ㄹ, … , ㅏ,ㅑ,ㅓ,ㅕ, … 등의 자음과 모음이 배치되어 있는 영역

    3. U+AC00: 완성형 영역

      가각… 같이 이미 완성되어 있는 한글 케릭터가 11172 자 배치되어 있다.

    # by choiwonwoo | 2007/07/26 12:40 | Dev Web | 트랙백(64) | 덧글(0)
    Network Byte Ordering

    unix도 아주 별의 별 종류대로 struct를 막 쏘아대니, 정신을 못 차리고 있다가...

    아래 블로그 덕분에 골치아픈 문제를 잘 해결했습니다.

    (저만 보기 아까운 좋은 글이라 김기태님의 블로그에서 가져왔습니다. 감사합니다.)

     

     

     

    Byte Order

    오늘은 바이트 오더에 대해서 정리를 해보자. 책을 찾아보면 이해가 되었다가 한참후에 생각해보면 항상 햇갈리는 부분이라서 따로 정리를 해본다.

    바이트 오더에는 리틀엔디안과 빅엔디안 두가지가 있다. PC에서 일반적으로 사용하는 Intel, Alpha 같은 CISC 계열 CPU는 리틀엔디안을 사용하고 SPARC, 모토로라 프로세서 같은 RISC 계열 CPU는 빅엔디안을 사용한다.

    그럼 두가지 엔디안의 차이는 무엇일까? 차이점은 2바이트 이상의 데이터(정수형뿐만 아니라 일반대상체도 포함됨)를 메모리에 저장할때 어느 바이트부터 저장을 하는지이다. 리틀엔디안은 높은 번지(Most Significant Byte)에서 낮은 번지(Least Siginificant Byte)로 기록을 하고, 빅엔디안은 낮은 번지(LSB)에서 높은 번지(MSB)로 기록을 한다.

    컴퓨터는 2진수를 사용해서 데이터를 메모리에 저장한다. C언어에서 사용하는 정수형(int)은 4바이트를 사용하는데 정수형 134480385 값은 아래와 같이 표현된다. 오른쪽 끝이 2^0 부분이고 왼쪽으로 갈수록 증가해서 왼쪽 끝이 2^31 이다. (2진수 값을 보기 편하게 하기위해 볼드 처리를 하고 134480385 같은 이상한 숫자를 사용했다)
    00001000 00000100 00000010 00000001

    위의 표현이 빅엔디안 시스템에서 메모리에 저장될때는 낮은 번지(LSB)에서부터 높은 번지(MSB)로 기록을 하기 때문에 아래와 같이 변경없이 그대로 저장이 된다.
    LSB <-- 00001000 00000100 00000010 00000001  --> MSB

    하지만 리틀엔디안 시스템은 높은 번지(MSB)에서부터 낮은 번지(LSB)로 저장을 하기 때문에 아래와 같이 각 바이트의 순서가 뒤집어져서 저장이 된다. 오른쪽에서부터 왼쪽으로 데이터를 저장한다고 생각하면 이해하기 쉬울것이다.
    LSB <--  00000001 00000010 00000100 00001000  --> MSB


    그럼 두 엔디안의 차이에서 발생하는 문제가 무엇일까?

    위에서 보여준 리틀 엔디안으로 저장된 134480385의 2진수 표현을 빅엔디안 방식으로 해석해보자. 빅엔디안은 낮은 번지부터 시작한다고 했으니 왼쪽에서 오른쪽으로 읽어나가면 되겠다. 그럼 1로 셋팅된 값이 각각 2^24, 2^17, 2^10, 2^3 자리에 있으니 10진수로 변환하면 16909320이 된다. 졸지에 134480385가 16909320로 변했다!!


    두가지 방법에는 나름대로 장단점이 있다.

    빅엔디안의 경우에는 사림이 보기에 매우 직관적이라는 장점이 있지만, 데이터 타입이 변경되어 4바이트에서 8바이트로 확장될때 메모리에서 전체 4바이트 값을 오른쪽으로 이동시켜야한다.
    LSB <-- 00001000 00000100 00000010 00000001 --> MSB

    LSB <-- 00000000 00000000 00000000 00000000 00001000 00000100 00000010 00000001 --> MSB

    리틀엔디안은 사람이 보기에는 별로 직관적이지 않지만 데이터 타입 변경으로 메모리가 확장될때 단지 오른쪽에 새로운 바이트를 추가하기만 하면 된다.
    LSB <-- 00000001 00000010 00000100 00001000 --> MSB

    LSB <-- 00000001 00000010 00000100 00001000 00000000 00000000 00000000 00000000 --> MSB


    그럼 이제 언제 엔디안의 차이가 문제를 발생시키는지 알아보자. 빅엔디안이던 리틀엔디안이던간에 그 컴퓨터에서 뭔짓을 하더라도 아무런 문제도 생기지 않는다. 하지만 요즘 세상에 혼자만 노는 컴퓨터가 있던가? 다들 다른 컴퓨터와 네트웍으로 연결되어서 통신을 한다. 바로 이때 문제가 발생한다. 리틀엔디안 컴퓨터가 512라는 숫자를 전송했는데 받는 컴퓨터는 빅엔디안이다. 그럼 빅엔디안 컴퓨터는 그 값을 131072로 해석하겠지.

    이런 문제를 해결하기 위한 방법으로 네트웍 오더라는 개념이 있다. 모든 컴퓨터는 네트웍으로 정수형을 전달하기 전에 네트웍 오더로 변환 후에 전송해야 한다. 그리고 받는쪽은 네트웍 오더를 자신이 사용하는 바이트 오더로 변환 후에 그 값을 사용해야만 한다. C에서는 htons, htonl, ntohs, ntohl 같은 함수를 사용해서 변환을 한다. 참고로 네트웍 오더는 빅 엔디안이다. 그래서  솔라리스 스팍 버전에서 htons, htonl 함수는 비어있는 메크로이다.

    바이트오더 문제를 해결하는 또 다른 방법은 숫자를 문자열로 전송하는 방법이다. 512라는 값을 전송할때 정수형 512로 전송하는게 아니라 문자열 512로 전송한다. 그리고 받는 쪽에서 문자열 512를 정수형으로 변환해서 사용하면 된다. 이 방법은 사용하기 편하다는 장점이 있지만 숫자를 표현하는데 정수형보다 더 많은 바이트를 사용해야하고 숫자 표현에 몇 바이트를 사용할지 송수신자 사이에 약속이 있어야 한다. 몇 바이트를 사용할지 고정하지 않는 경우에는 구분자를 사용해서 어디까지가 숫자를 표현하는 문자열인지 표시해야 한다.
    # by choiwonwoo | 2007/07/26 12:40 | Dev Network | 트랙백 | 덧글(0)
    기본 개념

    ■ 자바(JAVA)란?

    ·선마이크로시스템사가 만든 객체 지향적 프로그래밍 언어이다. 원래 자바는 다양한 가전제품의 활용을 염두에 두고 만들어졌다. 그래서 하드웨어 및 소프트웨어 플랫폼에 독립적이다.

    ① 자바의 주요 특징

    ·하드웨어 및 소프트웨어의 플랫폼에 독립적이므로 클라이언트 서버의 분산 환경에 적합하다.

    ·객체(Object)를 활용하는 객체 지향적 언어이므로 C, C++ 등에 비해 상대적으로 단순하고 쉽다.

    ·프로그래밍 언어 차원에서 멀티쓰레드가 지원되며 메모리 관리가 수월하고 보안 기능이 강하다.

    ·컴파일도 하고 인터프리터도 하는 언어이다.

    ·장점이 매우 많지만 중요한 단점은 프로그램 실행 속도가 느린 편이라는 것이다.

    ② 자바와 C++의 비교

     

    Java

    C++

    포인터가 없다.

    포인터가 있다.

    플랫폼에 독립적이다.

    플랫폼에 종속적이다.

    순수 객체 지향 프로그래밍이다.

    C 언어에 기반을 둔 객체 지향 프로그래밍이다.

    표준 데이터 타입을 사용한다.

    OS 및 하드웨어에 따른 데이터 타입을 사용한다.

    배열 범위를 검사한다.

    검사하지 않는다.

    언어 차원의 멀티쓰레드를 지원한다.

    하드웨어와 OS에 의존하는 멀티태스킹을 지원한다.

    메모리를 overwrite할 수 없다.

    메모리를 overwrite할 수 있다.

    재 컴파일 없이 클래스, 메소드 및 변수에 접근이 가능하다.

    재 컴파일이 필요하다.


    ■ 자바로 만들어진 프로그램의 유형

    ① 자바 애플릿(Java Applet)

    ·웹 브라우저가 구동하여 클라이언트에서 실행되는 일반적으로 소형 프로그램으로서 사용자가 요청하여 서버로부터 다운로드하여 사용한다.

    ② 자바 애플리케이션(Java Application)

    ·일반적인 응용프로그램으로서 로컬의 기억장치에서 프로그램을 로딩하여 구동한다. 서버와 관계없이 자신의 시스템에서 실행되는 것이다.

    ③ 자바 서블릿(Java Servlet)

    ·애플릿과 유사하나 애플릿과는 달리 서버에서 실행되며 CGI 프로그램처럼 POST나 GET 방식으로 사용자의 입력 처리가 가능한 소형 프로그램이다.

    ④ 자바 빈스(Java Beans)

    ·자바의 재사용이 가능한 소프트웨어 객체를 만드는 기술의 결과로 만들어진 컴포넌트로서 각종 다양한 목적을 위한 소형 모듈이다.

    # by choiwonwoo | 2007/05/21 10:07 | JAVA | 트랙백 | 덧글(0)
    [1] Java Bean 이란 멀까?
    ============================================================================================
    내 기억속에 Bean과 Beans는 차이가 있다는 내용이 어렴 풋이 남아 있다.
    그래서 그 차이점을 명확하게 하기 위해서 자료를 찾아 봤으나, 명확한 구분을 하여주는 글을 찾기란 ...
    그래서 이 내용에 대해서 추적을 시작한다.
    ============================================================================================

    http://k.daum.net/qna/view.html?boardid=QCD003&qid=00iuS&q=%C0%DA%B9%D9+%BA%F3+%C0%DA%B9%D9+%BA%F3%C1%EE

    자바빈즈(JavaBeans)란 자바로 소프트웨어 컴포넌트(부품)을 만들기 위한 기술입니다.
    빈이란 제작 표준에 따라 작성한 각각의 컴포넌트입니다.
    애초에는 표준화해서 VB처럼 쉽게 속성을 설정할 수 있는
    개발도구를 이용할 수 있도록 하기 위해 JavaBeans 규약이 만들어졌습니다.
    그러나, 이러한 의도로 만들어진 자바빈즈는 크게 호황을 누리지 못하다가
    서버쪽에서 컴포넌트를 만드는 기술로 발전했습니다.
    그래서 등장한 것이 엔터프라이즈 자바빈즈, 바로 EJB 입니다


    # by choiwonwoo | 2007/05/18 10:11 | JAVA | 트랙백 | 덧글(0)
    COM+ 컴포넌트 사용하는 간략 순서 System.EnterpriseServices 참조 추가
    http://blog.naver.com/eh07ton/80037271325

    대부분, 닷넷으로 SI 관련 프로젝트를 구축할 경우 CBD 방법론에 따라 구축합니다.
    중급으로 가는 길목에서 많이 어려워 하죠. 일단 간략하게 구축 순서를 적어봅니다.
    일반적인 순서이며 약간씩 다를 수 있습니다.
     
    *. 새프로젝트 추가 : 클래스 라이브러리 선택 (컴포넌트 경로 및 파일명 지정)
     
    *. 참조추가 : System.EnterpriseServices
     
    *. 강력한 이름 (SN) 파일 생성 : 명령프롬프트에서 sn.exe 을 쳐보면 설명이 나옵니다.
       - sn -k mykey.snk (여러개의 컴포넌트를 사용하는 경우 경로를 지정하여 한쪽에 몰아 놓는 것이 좋습니다.)
     
    *. 해당프로젝트 루트에 생성되는 AssemblyInfo.cs 파일 작업 : 아래 내용에 따라 추가 합니다.
       - using System.EnterpriseServices;
       - 강력한 이름의 키파일의 경로 지정 & 명칭 설정
          [assembly: AssemblyKeyFile("..\..\mykey.snk")]
          [assembly: AssemblyKeyName("")] //명칭은 지정하지 않아도 됩니다. 옵션
     
    *. 컴포넌트 프로그래밍... 열씨미...
     
    *. 컴파일...
     
    *. 어셈블리를 GAC로 등록 : 명령프롬프트에서gacutil.exe 파일 이용
       - gacutil /i myDll.dll
       - 또는 c:WINNTassembly 폴더에 복사해도 됨
     
    *. 어셈블리를 COM+로 등록 : 명령프롬프트에서 regsvcs.exe 파일 이용
       - regsvcs myDll.dll
     
    *. 구성요소서비스 정보수정 : 윈도우 시작 > 관리도구 > 구성요소서비스
       - COM+ 응용 프로그램 하위에 있는 해당 프로그램의 등록정보를 적절히 수정
     
    *. 컴포넌트를 사용하고자 하는 프로젝트에서 컴포넌트 참조 추가
     
    *. 컴포넌트를 사용하고자 하는 프로젝트에도 System.EnterpriseServices 참조 추가
     
    에구.. 좀 길고 복잡하네요... 하지만 이런 기본적인 흐름을 알면서 부터 컴포넌트기반의 개발을 시작하는 거죠...  
    # by choiwonwoo | 2007/05/16 17:21 | Dev Information(C#) | 트랙백 | 덧글(0)
    [HASH 기본개념] 해쉬알고리즘이란 무엇이며 해쉬함수의 특징과 종류에는 어떠한 것들이 있나요?
    [출처: http://www.kisa.or.kr/kisa/kcac/jsp/kcac_faq_view.jsp?id=308]

    해쉬알고리즘은 데이터 ⑦무결성 및 메시지 인증 등에서 사용할 수 있는 함수로써 임의의 길이의 비트 열을 고정된 길이의 출력값인 해쉬코드로 압축시키는 함수이며, 암호학적 응용에 사용되는 대부분의 해쉬함수는 강한 충돌저항성을 지닐 것이 요구된다.

    해쉬알고리즘은 크게 ⓐDES와 같은 블록암호알고리즘에 기초한 해쉬알고리즘과 전용 해쉬알고리즘으로 나눌 수 있으며 블록암호암고리즘에 비해 전용 해쉬암고리즘의 속도가 빠르므로 대부분의 응용에서 전용 해쉬알고리즘이 이용된다.

    해쉬함수는 일방향 함수(one-way function)으로 다양한 길이의 입력을 고정된 짧은 길이의 출력으로 변환하는 함수로 데이타의 무결성 검증, 메세지 인증에 사용한다. 해쉬함수는 다음의 성질을 만족해야 한다.

    일방향성 : 함수 f(X)에서 f(X)=Y의 경우 X로부터 Y의 계산은 쉬우나 Y로부터 X의 계산은 어려워야 한다.
    여기서 x는 가변 길이의 메시지이고, y는 해쉬함수 h를 통하여 생성되어지는 고정의 길이의 해쉬값(hash code)이다. 해쉬함수를 거쳐 나온 값 Y를 메시지 다이제스트(Message Digest)라고 정의한다.

    해쉬함수의 특징

      - 다양한 가변 길이의 입력에 적용될 수 있어야 한다.
      - 고정된 길이의 출력을 만든다.
      - 주어진 입력값을 해쉬하는 것은 쉽다.
      - 해쉬 결과값으로 입력값을 계산하는 것은 불가능 하다.
      - 동일한 해쉬값을 가지는 서로 다른 메시지 쌍이 없다.

    전자서명을 할 때 해쉬함수로 메시지를 압축한 데이터에 서명함으로써 효율성을 높일 수 있다. RSA와 같이 전자서명에 사용되는 알고리즘은 메시지 자체를 암호화 하는 경우 해쉬함수 보다 처리속도가 느린데, 서명을 메시지 해쉬함수로 축약(Digest)함으로써 전자서명 알고리즘의 계산량을 줄일 수가 있다.

    해쉬함수의 종류

    현재 사용되고 있는 대표적인 해쉬함수는, 1990년에 R.C. Merkle에 의해 제안된 SNEFRU, 1989년에 일본 NTT의 미야구치 등이 발표한 N-HASH, 1990년과 1992년에 Ron Rivest에 의해 개발된 MD4와 ⓒMD5, 1993년에 미국 NIST에 의해 개발되었고 가장 많이 사용되고 있는 ⓔSHA(Secure Hash Algorithm)등이 있다.



    [출처:http://www.securitytechnet.com/resource/research/techreport/std-summary/node2.html]


    해쉬 알고리즘

    해쉬함수($ H$혹은 Hash로 표기)는 임의의 길이의 입력 메세지를 고정된 길이의 출력값으로 압축시키는 함수이다. 데이타의 무결성 검증, 메세지 인증에 사용한다. 해쉬함수는 다음의 성질을 만족해야 한다.

    • 일방향성 : 주어진 해쉬값 $ h$에 대해서 $ H(x)=h$를 만족하는 $ x$를 찾는것이 계산적으로 불가능

    • 강한 충돌 회피성 : 주어진 $ x$에 대해 $ H(x)=H(y)$를 만족하는 임의의 입력 메세지 $ y( \ne x)$를 찾는 것이 계산적으로 불가능

    일반적으로 널리 쓰이는 해쉬함수로는 MD5, SHA1, RMD160, TIGER 등이 있다.


    표 4: 해쉬 알고리즘
    알고리즘 출력길이 블럭의 크기 라운드 수 Endianness
    MD5 128 512 64 Little
    SHA1 160 512 80 Big
    SHA256 256 512 64 Big
    SHA384 384 1024 80 Big
    SHA512 512 1024 80 Big
    RMD128 128 512 128 Little
    RMD160 160 512 160 Little
    RMD256 256 512 128 Little
    RMD320 320 512 160 Little
    HAS160 160 512 80 Little
    TIGER 192 512 56 Little


    • MD5는 널리 사용된 해쉬 알고리즘이지만, 충돌 회피성에서 문제점이 있다는 분석이 있으므로 기존의 응용과의 호환으로만 사용하고 더 이상 사용하지 않도록 하고 있다.

    • SHA1은 DSA에서 사용하도록 되어 있으며 많은 인터넷 응용에서 default 해쉬 알고리즘으로 사용된다.

    • SHA256, SHA384, SHA512는 AES의 키 길이인 128, 192, 256 비트에 대응하도록 출력길이를 늘인 해쉬알고리즘이다.

    • RMD128, RMD160는 RIPE 프로젝트의 RIPEMD나 MD4, MD5를 대신하기 위하여 디자인된 해쉬 알고리즘이다. 128 비트의 출력을 내는 RMD128은 역시 충돌 회피성에서 문제점이 있다. RMD160은 효율성은 떨어지지만 안전성을 높인 것으로 많은 인터넷 표준들에서 널리 채택되고 있다.

    • RMD256과 RMD320은 각각 RMD128과 RMD160을 확장한 것이다.

    • HAS160은 국내 표준 서명 알고리즘 KCDSA를 위하여 개발된 해쉬 함수이다. MD5와 SHA1의 장점을 취하여 디자인 되었다. 현재 TTA 표준으로 제정중에 있다.

    • TIGER는 64 비트 프로세서에 최적화되어서 64 비트 프로세서에서는 매우 빠르다.
    # by choiwonwoo | 2007/05/14 16:43 | Dev Security | 트랙백 | 덧글(0)
    MD5, SHA-1 암호화 깨지다.

    [출처:http://dual.inxzone.net/blog/entry/MD5-SHA-1-%EC%95%94%ED%98%B8%ED%99%94-%EA%B9%A8%EC%A7%80%EB%8B%A4]

    세계 암호영역의 양대 보루가 모두 중국 산둥대학 정보연구소의 여성 과학자  40세의 왕샤오윈(王小雲)소장이 이끄는 연구팀에 의해 격파되었다.

    세상에 알려지지 않았던 왕 소장은 하루 만에 세계 명인이 되었고, 암호연구 영역에 알려지지도 않았던 산둥대학 정보연구소는 급기야 세계 암호연구영역에서 가장 주목을 받는 연구소로 되었으며, 국제 암호연구계는 충격에 휩싸여있다. 

    미국에서는 미국의 암호영역이 중국 전문가에 의해 격파되었음을 시인하고 미국의 정보안전이 위험에 처했다고 했다.
    국제 전문가들은 정보안전에 대해 다시 연구하고, 암호계산법을 새로이 만들어야 할 일이 긴박한 시점에 와있음을 분분히 주장했다.

    예고없이 발생된 강진

    ▲금년에 40세에 나는 왕샤오윈(王小雲) 산둥대학 정보연구소 소장. 그는 자기의 연구팀을 이끌어 세계 암호영역의 2대 보루인 MD5와 SHA-1 암호표준을 격파했다.     ©자료사진
    지난해 8월전만 해도 왕샤오윈은 국제 암호영역에서 이름이 없는 사람이었다. 바로 지난해 8월,  미국 캘리포니아에서 개최된 국제암호학술회의에서 원래 발언명단에 없었던 왕 소장은 집행위원회를 찾아가 자기가 소장으로 있는 산둥대학 정보연구소의 4편의 연구결과를 들고 자기에게 발언권을 줄 것을 요청했다. 그의 요청에 따라 집행위원회에서는 왕 소장에게 발언권을 주었다.

    세상에 이름이 알려지지 않은 왕소장이 발언대에 올라갈 때까지만 해도 회의참가자들은 별로 주목을 하지 않았지만, 왕소장이 산둥대학 정보연구소의 세번째 성과를 발표했을 때, 왕 소장은 회의장에서 울리는 박수소리 때문에 몇 번이나 발언을 중단할 수 밖에 없었다. 그가 4개의 연구성과를 모두 발표했을 때, 회의장에는 장시간 박수가 끊기지 않았다.

    이번 암호학술연구회에서 왕 소장은 자기들의 연구성과, 즉 세계 암호계의 주류인 MD5、HAVAL-128、MD4와 RIPEMD를 모두 격파했다.

    이번 회의가 끝 난후 이번 회의 총결보고에는 "우리는 어떻게 해야 할 것인가? MD5는 중상을 입어 장차 응용영역에서 물러나게 될 것이다. SHA-1이 아직까지 살아있다고는 하지만, 그 기간도 얼마 남지 않았다. 지금부터 SHA-1을 갱신해야 할 것이다."라고 결론을 내렸다.

    ▲암호표준 격파 설명서.     ©인터넷자료

    이번 회의에서 왕소장의 연구결과 발표로 세계 양대 암호보루인 MD5는 무너지고 말았다.

    MD5가 왕 소장에 의해 격파된 다음에도 세계 암호연구영역에서는 여전히 SHA-1은 안전한 것으로, 아직까지 그것이 격파될 충분한 이유가 없으며 2010년 전까지 그보다 더 안전한 SHA-256, SHA-512연산법으로 전환할 것을 주장했으며, 이런 내용은 2월 7일에 발표된 미국국가표준연구원에서 발표한 성명서에 적혀있었다.

    그러나 미국 국가표준연구원에서 이런 성명을 발표한 불과 한주일 만에 왕 소장 연구팀은 SHA-1 암호시스템도 그들에 의해 격파되었음을 증명했고, 세상에 공포했다.

    왕소장의 SHA-1격파소식은 세계 암호영역에 엄청난 충격을 안겨주었다. SHA-1은 미국을 비롯한 나라들에서 많이 사용하는 것으로 국제사회는 놀랐다. 왕 소장의 연구는 전자 사인을 위조할 수 있음을 증명했다.

    ▲산둥(山東)대학은 중국 기초과학인재배양기지(수학)이기도 하다.     ©안터넷사진
    최근 국제암호전문가 Lenstra는 왕 소장이 제공한 MD5충격이론에 따라 X.509에 부합되는 수학증서를 위조해냈다. 이는 왕 소장의 연구는 이론에서 실제 응용에로 들어갈 수 있으며, MD5의 응용영역 퇴출은 눈 앞에 대두되었음을 말해준다. 따라서 왕 소장은 SHA-1도 이미 격파했기에 그의 응용영역에서의 퇴출도 시간문제라고 했다.

    왕샤오윈 소장

    금년 40세인 왕 소장은 책에만 붙박혀 있는 사람이라는 뜻에서 '시체여성'이라는 별명이 있다고 그의 동료들은 말했다.1990년부터 왕 소장은 중국 과학원 원사이며 중국 수학계의 거두인 판청둥(番承洞)과 딩쓔웬(丁秀源)교수의 제자로 가르침을 받으면서 1990년대 말부터 Hash함수의 연구, 즉 암호영역의 연구에 몰두했다.

    ▲산둥대학 총장이며, 왕 소장의 스승이었던 판 교수. 중국 수학연구영역의 거물급 인물이기도 하다.     © 인터넷사진
    판 교수는 중국 수학연구 영역의 권위자로 중국 과학원 학부위원이며, 산둥대학의 총장을 지냈다. 판 교수는 골드바하 추측에 대한 연구 영역에서 큰 성과를 올린 거물급 인물로, 골드바하추측 연구에서 재래식의 연구방식에서 벗어나 {1,5}과 {1,4}의 성립을 증명, 뒤의 명제인 {1,3}과 {1,2}의 증명을 위해 기초를 닦아 놓았다.

    딩 교수 역시 중국 수학계의 유명 인물로, 4차에 걸쳐 중국 국가 자연과학기금회에서 지원하는 프로젝트를 주최한 바 있으며, "암호과학기술진보상"을 받은 적이 있는 중국 암호연구영역의 거물급 인물이다.

    이들로부터 가르침을 받은 왕 소장은 3명의 여성연구원들을 이끌고 국제 암호영역의 2대보루를 격파했던 것이다.

    왕 교수가 암호 2대보루를 격파하기 전에 국제 암호영역에서는 MD5와 SHA-1암호방식은 금성철벽으로 인정했었다. 그러나 왕 소장은 자기의 연구팀을 이끌고 불과 2개월 같의 연구를 거쳐 이 금성철벽으로 인정받은 SHA-1를 격파했던 것이다.
     
    ▲왕 소장의 스승인 딩슈웬(丁秀源)교수. "암호과학기술진보상" 수상자이기도 하다.     © 자료사진

    따라서 왕 소장은 하루밤 새에 명인으로 되었다. 원래 이름이 별로 알려지지 않았던 왕 소장의 이름이 구글에서는 수 천개 항목에 올라와 있고, 중국의 가장 큰 검색엔진에 오른 왕 소장의 이름은 무려 9천개에 가깝다.

    국제암호연구영역의 반응

    MD5、SHA-1 암호표준은 국제적으로 광범위하게 응용되는 암호표준이기도 하다. MD5는 국제저명한 암호학자이면서 듀링상의 수상자이자 공공키암호연산법인 RSA의 창시자인 Rivest가 설계한 것이고, SHA-1은 미국에서 전문암호연산법을 제정하는 전문기구인 미국국가표준기술연구원(NIST)과 미국 국가안전국(NSA)에서 설계한 것이다.

    이 두 암호표준은 전자서명과 기타 암호응용영역이 널리 쓰이는 관건기술로, 금융, 증권과 전자비즈니스에서 광범위하게 응용되고 있다.

    왕 소장의 소개에 따르면 세계적으로 지문이 같은 사람이 없기에 지문은 가장 안전한 신분표시로 되고 있다. 네트웍 안전협의에서는 Hash함수로 전자사인을 처리하여 이론적으로는 중복되지 않는 "지문"을 생성하여 "디지털손도장"을 만든다. 이상적인 안전요구에 따르면 Hash함수로 생성되는 만큼, 원시 정보가 한자리 수만 변해도 확연히 다른 "지문"이 생성된다. Hash의 함수가 충돌되는 방법을 연구해낸다면 같지 않은 데이타가 동일한 "지문"을 생성할 수 있게 되는 것이다. 이렇게 되면 자연 전자사인을 "위조"할 수 있는 것이다.

    ▲학생들을 지도하는 판교수(이미 작고했음)     ©자료사진
    왕 소장이 자기의 연구팀을 이끌어 MD5와 SHA-1 암호표준을 격파함으로 국제암호영역에는 강진이 발생했다.  

    국제 암호영역의 정상급 학자 Shamir는 “이는 최근년간 암호영역에서 거둔 가장 아름다운 과실인바, 나는 이는 장차 큰 파동을 일으키게 될 것이며 새로운 Hash함수 연산법을 연구하는 것은 극히 중요할 일이라고 본다"고 했으며, MD5의 설계자 Rivest는 “SHA-1이 격파되었다니 참으로 놀랍다", "디지털사인의 안전성은 내려가고 있는 바 연산법을 교체할 것을 제시하고 있다"라고 했다.

    미국 국가표준기술연구원과 유명 글로벌회사들에서도 적극적인 반응을 보이고 있는 바 Seagate Technology사의 안전문제연구총감 Mark Willet는 "지금은 미국 국가표준기술연구원에서 암호를 갱신하는 날짜를 앞당겨야 할 시점이다"라고 했다.

    이외 MS사, SUN과 Atmel 등 글로벌 사들 역시 자기들의 대응책을 내놓았으며 미국 변호사협회의 한 고문은 "중국의 이 몇몇 연구원들은 아주 미쳐버렸나바"라고 감탄했다.

    최근 몇 년간, 중국은 기초과학 영역과 응용과학 영역에서 괄목할만한  발전을 가져 오고 있는 바, 그 발전은 빠르다고 하기보다는 비약하고 있다고 해야 할 것이다. 나노과학 연구의 실제 응용에서 이미 커다란 성과를 거두어 나노재료를 항공기연구제작에 쓸 것으로 전망되고 있으며, 2006년 연말에는 달 탐사선을 발사한다고 중국 관련당국에서는 선포한 적도 있다.

    개혁개방의 심화와 실무적인 새로운 국가지도부의 출범으로 중국은 지금 놀라운 속도로 발전하고 있다.

    # by choiwonwoo | 2007/05/14 16:34 | Dev Security | 트랙백 | 덧글(1)
    [os] RWLock vs IOCP

    I'm thinking what 's the important point,when server side applications are deveploped.

    # by choiwonwoo | 2007/05/12 12:52 | ServerDevResource | 트랙백(54) | 덧글(0)
    < 이전페이지 다음페이지 >


    이글루링크 추가하기
    ()을(를)
    이글루링크로 추가하시겠습니까? 추가하시려면 그룹선택을 하세요.
    (그룹선택 하지 않는 경우, 최상단 목록에 추가됩니다.)
    그룹선택 :
    이글루링크 취소