Download as pdf or txt
Download as pdf or txt
You are on page 1of 14

이런 함수로는 exec(), eval()과 exefile() 등이 있다.

CGI 프로그 * 위험 요소 제거하기


user = re.sub(r” ,“”
\W” “user”
, form[ ].value)
램 중간에 다음과 같은 코드를 넣게 된다고 가정해 보자.

“finger %s”% form[


os.popen( “user”
].value)

일단 유닉스에서 권한이 없는 사용자가 setuid, setgid 등을 이용


만약 사용자가 넣는 값이 다음과 같다면 어떤 일이 벌어지게 하는 프로그램을 사용하게 될 때‘user’모듈을 임포트(import)
될까? 할 수 없게 해야 한다. user 모듈은 특정 모듈을 실행시키게 되는
데, 신뢰할 수 없는 사용자가 특정 모듈에 악의적인 코드를 삽입
; cat /etc/passwd
하게 된다면 user 모듈을 임포트하는 스크립트는 잠재적인 위험
으니 한번쯤 살펴보기 바란다. 이 자료는 기본적인 시스템에서 요소가 될 수밖에 없다.
부터 네트워크, 무선 네트워크까지 망라하는 방대한 영역을 포 유닉스 암호를 shadow화하지 않은 경우 모든 암호를 고스란히 파이썬은 컴파일시 검사를 거의 하지 않는다. 정확하게는 본질
함하고 있으므로, 필요한 부분의 경우에는 그때그때 확인하는 인터넷의 어떤 사용자에게 전송하게 되는 상황을 만들게 된다. 이 적으로 컴파일시 어떠한 타입 정보도 갖지 않으며 건네지는 매개
것이 좋다. 런 문제는 일반적인 스크립트나 외부 프로그램을 수행하는 모든 변수의 수가 주어진 함수 또는 메쏘드에 대해 적합한 것인지를 전
중요한 몇 가지 보안 원칙은 다음 세 가지 정도로 정리할 수 프로그램에서 발생할 수 있는 잠재적인 문제이다. 실제로 필자도 혀 검사하지 않는다. 이는 잠재적인 많은 버그를 야기한다. 오랫
있다. 근무하던 몇몇 회사에서 이런 식으로 동작가능한 프로그램을 볼 동안 정적 타이핑 및 타입 검사에 관련되어 논의가 진행되었지만
수 있었다. 스크립트의 경우 대부분 필요에 의해 그때그때 만들어 이에 대한 구현은 아직 완벽하지는 않다(이것에 대한 논의는
� 기밀성(confidentiality, 또한 secrecy) : 컴퓨팅 시스템 자원은 단지 인가된 사 지면서 특별히 주의를 기울이지 않는 경우가 많다. 그렇기 때문에 http://www.python.org/sigs/types-sig/를 참조한다). 현재 부
용자들에 의해서만 접근된다. 이러한 문제가 발생할 확률이 커지게 된다. 이런 일은 몇 가지 작 분적인 해결 방법은 파이썬 소스 코드 내의 일반적인 버그를 검사
� 무결성(integrity) : 시스템 자원은 오직 인가된 사용자들에 의해 인가된 방식
업을 함으로써 어느 정도 해결할 수 있다. 하는 lint 같은 프로그램인 PyChecker를 이용하는 것이며,
으로만 변경될 수 있다.
http://pychecker.sourceforge.net에서 얻을 수 있다.
� 가용성(availability) : 인가된 사용자들은(시스템 사양에 의해 결정되는) 빠른 * Quote화하기
속도로 자산에 접근할 수 있다. 이 목적을 충족시키지 못하는 것을 서비스 거부 “user”
user = pipes.quote(form[ ].value)
(Denial of Service)라고 부른다.
* 특정 문자열인 경우 서비스 거부 pickle(혹은 cPickle)은 파이썬에서 객체를 직렬화하는 모듈이다.
if not re.match(r”
^\w+$”
, user): ...error...
속담에‘열 사람이 한 도둑 못 막는다’
고 했다. 그런 만큼 무엇
인가를 지키고 보호한다는 것은 지극히 어려운 일이다. 수많은 물론 이것은 시스템 보안에 관련된 원리이긴 하지만 똑같이 프
외부 요소에 대해 모든 요소에 대응을 한다는 것은 거의 불가능 로그래밍에도 적용된다. 프로그램에서 시스템 자원을 사용하는
하기 때문이다. 그렇다고 뻔히 보이는 구멍을 막지 않을 수도 경우는 매우 비일비재하기 때문에 앞의 세 가지 원칙을 잊고 중요
Forth라는 언어에서 전해지는 말로 이런 것이 있다. 그램을 효율적이면서 안정적으로 만들 수 있기 때문이다.
없다. 한 시스템 자원에 접근하는 프로그램을 만들게 된다면 거의 재앙 근래에 많은 프로그래머들이 언어에 대한 지식은 상당히 많이 가지고 있
파이썬 같은 스크립트 언어는 시스템(적어도 유닉스 계열 OS 에 달하는 끔찍한 사고가 벌이지게 된다. “훌륭한 프로그래머는 작품을 만들지만 미숙한 프로그래머는 재앙을 만든다” 지만, 정작 시스템에 대해서는 별다른 관심을 기울이지 않는 경향이 눈에
에서는)에서 상당히 많이 사용된다. 사용하기 쉽기 때문에 많은 띄게 늘어나고 있다. 스크립트 언어를 사용하거나 자동화 도구를 이용하기
사람들이 이용하고 있다. 이런 식으로 사용되는 부분에서는 필연 사용하기 편리하다는 것은 반대로 자기도 모르는 사이에 어떤 일이 벌어 때문에 시스템에 관련되어 뚜렷한 영향을 주고받는 일이 적어질 수는 있겠

적으로 많은 수의 보안 문제가 발생할 수밖에 없다. 이번 호에서 질 수 있다는 것을 의미한다. 기능이 풍부하다는 것은 달리 말한다면 복잡 지만, 근본적인 프로그래머의 입장에서는 바람직하지 않다고 본다.
하다는 것을 말할 수 있으며, 복잡하다는 것은 문제가 발생할 확률이 그만 어떠한 프로그램이라도 시스템과 상호작용은 피할 수 없다. 따라서 프로
는 기본적인 보안 원리와 파이썬에서 생길 수 있는 몇 가지 보안 파이썬과 같은 스크립트 언어는 어떠한 사용자가 코드를 사용할
큼 커질 수 있다는 것을 의미할 수 있다. 그램 상의 약간의 실수가 전체적인 시스템에는 큰 문제를 만들 수 있다. 더
문제를 살펴보는 한편, 코드를 검사해주는 패키지 PyChecker를 지 명확히 구분되지 않는다. 그렇기 때문에 신뢰할 수 없는 사용
기본적으로 시스템을 구축할 때 가장 중요한 것은 최대한의 기능을 최소 욱이 현재의 웹 서비스 같은 불특정 다수에게 열려 있는 서비스에서는 조금
살펴보도록 한다. 자가 입력에 영향을 미칠 수 없도록 데이터가 프로그램의 한 부분
한의 복잡성으로 구성하는 데 있다. 라이브러리나 모듈, 컴포넌트라고 불리 의 실수가 상상할 수 없는 최악의 상황으로 전개될 수도 있다.
으로 실행되도록 하는 모든 함수들에 대해 각별히 유의해야 한다.
는 수많은 환경은 이러한 법칙을 충실히 이행하려는 하나의 노력이다. 툴을 이용하는 것은 편리함을 추구하는 이유가 크지만, 한편으로는 절약
훌륭한 프로그래머란 자신이 하는 작업이 발생할 수 있는 문제를 미연에 되는 시간과 노력을 다른 곳에 재투자할 수 있기 때문이다. 따라서 편리한
시스템 관리자뿐 아니라 프로그래머가 반드시 잘 알고 있어야 파악해 그에 대한 대비책을 충실히 세우거나, 아니면 처음부터 그런 문제를 작업만큼이나 그 뒤에 있을 상황을 철저히 대비할 수 있는 노력과 투자를
하는 일반적인 원리는 분명히 있다. 이런 정보를 얻을 수 있는 피할 수 있는 설계를 할 수 있는 사람을 말한다. 이를 위해서는 시스템에 대 게을리 하지 않는다면 훌륭한 프로그래머로의 길에 조금은 더 근접해 간다
곳으로 IATF(Information Assurance Technical Frame 해 어느 정도 지식을 갖추고 있을수록 유리한데, 그것은 자신이 만든 프로 고 볼 수 있지 않을까?

work, http://www.iatf.net/)가 있다. 상당히 많은 정보가 있


이를 이용하면 특정 객체를 텍스트 파일 등으로 덤프한 후 다른 import resource # 최대 5 CPU sec를 사용 별다른 어려움 없이 사용할 수 있는 것을 볼 수 있다. 이와 같
resource.setrlimit(resource.RLIMIT_CPU, (5, 5))
파일에서 로드하는 방식으로 객체를 전달할 수 있다. 기본적으로 모든 파이썬 코드는 파이썬 라이브러리와 언어에서 이 특정 조건에 만족하는 환경을 구성해야 할 때는 rexec를 계승
여기서 가장 근본적인 문제는 직렬화한 객체를 원래대로 환원 지원하는 모든 기능을 사용할 수 있다. 그렇지만 우리는 이미 앞 # 코드를 실행한다. 받아 적절한 메쏘드를 재정의함으로써 필요한 환경을 구성할 수
guard = Guard()
하는 데서 발생한다. 기본적으로 객체를 직렬화하는 데서는 큰 문 서 os.system 등을 통한 작업이 내포한 위험성에 대해 알아봤다. 있다.
guard.r_exec(input)
제가 생기지 않는다. 이것은 직렬화하는 단계에서 프로그래머가 하지만 특정한 상황이라면 인터넷을 통한 코드 자체를 실행해야
그 객체에 대해 충분히 검토할 수 있으며, 직렬화를 거친 경우 결 하는 경우가 필요할 수도 있다. 이를 위해서는 제한된 환경에서
과 값 역시 단순한 문자열 값이기 때문이다. 실행하는 작업이 필요하다. 이제 해당 코드를 실행해 보자. C에서 소스 코드의 문제점을 확인하기 위해서 사용하는 lint와 비
하지만 이것을 다시 원래대로 환원할 때는 상당한 주의가 필요 모듈 중에서 rexec 클래스는‘제한된 실행(restricted 슷한 작업을 수행하는 프로그램이다. 현재 PyChecker가 제공하
siabard@ns:~$ python rexec_test.py en
하다. 환원시에 전혀 의도하지 않았던 객체가 나올 수 있으며, 이 execution)’
을 지원한다. rexec는 원래 파이썬 애플릿 Grail에 사 는 기능은 다음과 같다.
Input (ctrl+z=end) => x =5
들 객체가 무엇인가 의심스러운 동작을 할 수 있기 때문이다. 이 용하기 위해 만들어졌다. 그렇지만 코드가 외부에서 제공되지 않 Input (ctrl+z=end) => print x (여기서 유닉스의 경우는 <ctrl+d>를
런 상황은 소켓 통신을 통해 외부에서 객체를 받아오는 작업에서 을 때에도 프로그램 내의 권한을 제한하기 위해 사용될 수 있다. 누른다. 윈도우는 <ctrl+z>) ◆ 임포트 없이 사용하는 모듈을 체크한다.
Input (ctrl+z=end) =>
흔히 발생되는데, 이런 경우 출처를 알 수 없는 곳에서의 전송에 기본적으로 제한된 실행 환경은 파일 읽기(쓰기가 아닌)를 허용 ◆ 함수/메쏘드/생성자에 전달되는 인수의 수가 틀린 경우를 검사한다.
5
◆ 내장 함수/메쏘드에 전달되는 인수의 수가 틀린 경우를 검사한다.
대해서는 특별한 주의를 기울여야 한다. 하지만 네트워크 접근 또는 GUI 인터페이스를 위한 기능을 제공 siabard@ns:~$ python rexec_test.py
Input (ctrl+z=end) => x = 5 ◆ 포맷 문자열과 인수의 수가 틀린 경우를 검사한다.
이와 같은 문제를 해결하는 몇 가지 방법 중 하나가 pickle이나 하지 않는다. rexec를 쓰기 위해서는 이를 계승하는 클래스를 생
Input (ctrl+z=end) => for i in range(x): print‘hello%d’% i, ◆ 존재하지 않는 클래스 메쏘드와 속성을 검사한다.
cPickle 등을 재정의하는 것이다. 그렇지만 이런 경우 파이썬에서 성하고, 프로그램 코드를 해당 클래스에서 실행해야 한다. Input (ctrl+z=end) =>
◆ 메쏘드를 오버라이딩할 때 서명이 변경되는 것을 검사한다.
hello0 hello1 hello2 hello3 hello4
제공하는 모듈 중 pickle이나 cPickle은 상당히 다른 방식을 사용 ◆ 함수/클래스/메쏘드가 동일한 블럭 내에서 재정의되는 것을 검사한다.
#!/usr/bin/env python
하기 때문에 자신이 사용하는 모듈이 무엇인지를 확인하고 작업 ◆ 변수 값이 정의되기 전에 사용되는 상황을 검사한다.
import rexec, sys
을 해야 한다. isWeb = 0 실제의 파이썬 코드가 실행되는 것과 거의 동일하다. 이제 파일 ◆ self가 메쏘드를 정의할 때 첫 번째 파라미터가 아닌 경우를 검사한다.
두 개의 모듈을 재정의할 때 거의 공통적으로 사용하는 것은 if sys.platform[:3] ==‘win’
: 을 열어보자. ◆ 사용되지 않는 전역, 지역 모듈이나 메쏘드를 검사한다.
safeDir = r’c:\temp’
__safe_for_unpickling__ 같은 속성을 구현하는 것이다. 실행시킬 ◆ 사용되지 않는 함수/메쏘드 인수를 검사한다(self의 경우는 무시될 수 있다).
else:
siabard@ns:~$ python rexec_test.py ◆ 모듈, 클래스, 함수, 메쏘드에서 doc 문자열이 없는 경우를 검사한다.
수 있는 객체를 이용할 때 기본적으로 환원 메커니즘에서는 safeDir =‘/tmp’
Input (ctrl+z=end) => open(‘/home/siabard/rexec_test.py’,
copy_reg 모듈을 통해 해당하는 객체가 정확히 등록되어 있는지, ‘r’).read()
def commandLine(prompt=’Input (ctrl+z=end) =>‘):
혹은 __safe_for_unpickling__을 참으로 설정한 것인지 확인할 수 input =‘’ Input (ctrl+z=end) => 그렇지만 파이썬이 가지는 특징적인 요소 때문에 불필요한 경
while 1: Traceback (most recent call last):
있으며, 이런 경우 후속 작업을 계속하면 된다. File“rexec_test.py” , line 41, in ? 고가 많이 발생할 수 있으니 사용에 주의한다.
try:
이 방식을 통하면 임의의 파일에 대해 os.unlink()을 수행하는 input = input + raw_input(prompt) +‘\n’ guard.r_exec(input)
except EOFError: File“/usr/lib/python2.1/rexec.py” , line 264, in r_exec
것 같은 위험한 작업을 동반하는 부분에 대해 어느 정도 방어를
break exec code in m.__dict__
할 수 있다. 기본적으로 시스템 관련 작업을 하는 모듈 등의 경우 print # 화면 정리용 File“<string>”, line 1, in ? PyChecker는 파이썬 1.5.2에서 2.2까지 지원하고 있으며,
File“rexec_test.py” , line 30, in r_open
__safe_for_unpickling__ 같은 속성이 참으로 설정되지 않는 것이 return input http://pychecker.sourceforge.net에서 최신판을 다운받을 수 있
raise SystemError,‘files outside %s prohibited’% safeDir
많기 때문에 위의 제한을 통과하는 객체들은 비교적 안전하다고 SystemError: files outside /tmp prohibited 다. PyChecker는 다음과 같이 설치한다.
if isWeb:
가정할 수 있다. import cgi # 웹에서 실행한다면 cgi 코드에서 동작시킨다.
form = cgi.FieldStorage() python pycheker/checker.py
클래스 인스턴스를 안전하게 환원하기 위해서는 어떤 클래스를
input = form[‘input’ ].value
생성하는지 정확하게 제어해야 한다. 즉, 클래스의 생성자가 수행 else: 주어진 디렉토리(/tmp나 c:\temp) 이외의 곳의 데이터를 액세
되는지를(__getinitargs__() 등을 찾는지) 확인하고, 메모리 정리 input = commandLine() # 셸에서 실행한다면 일반적인 커맨드 라인에서 실행한다. 스할 때 에러가 나는 것을 볼 수 있다. 이제 안전한 디렉토리에서 모듈이 설치되고 나면 바로 사용할 수 있다. PyChecker를 셸
시에 클래스의 파괴자가 실행하는지를(__del()__ 등의 메쏘드가 직접 액세스하는 것을 살펴보자. 에서 사용하는 방법은 간단하다.
# rexec를 통해 제한된 실행 환경을 구성한다.
수행되는지) 확인해야 한다. class Guard(rexec.RExec):
def r_open(self, name, mode=’ r’, bufsz=-1): siabard@ns:~$ python rexec_test.py $ pychecker file1.py file2.py ...
문제는 클래스의 경우, 파일 삭제와 같은 위험한 작업을 하는
if name[:len(safeDir)] != safeDir: Input (ctrl+z=end) => open(‘ /tmp/rexec_test.txt’, (윈도우에서는 pychecker.bat를 사용하면 된다)
메쏘드를 숨기는 것이 그다지 어렵지 않다는 점에 있다. 이런 것 raise SystemError,‘files outside %s prohibited’% safeDir ‘w’ “Hello rexec\n”
).write( )
을 제어하기 위해 사용되는 pickle과 cPickle은 서로 다른 방식을 else: Input (ctrl+z=end) =>
return open(name, mode, bufsz) siabard@ns:~$ python rexec_test.py
사용한다. 이들 방식은 거의 해킹에 가까운 수준까지 필요하므로 ‘/tmp/rexec_test.txt’
Input (ctrl+z=end) => print open( ,‘r’
).read() PyChecker를 사용하는 다른 방법은 임포트를 사용해 코드 상
여기서는 자세히 설명하지는 않는다. 필요하다면 파이썬 문서를 # 시스템 리소스를 제한한다(윈도우에서는 지원하지 않는다) Input (ctrl+z=end) => 에서 사용하는 것이다. 이 부분은 조금 후에 기술하도록 한다.
if sys.platform[:3] !=‘win’
: Hello rexec
참고하기 바란다. 소스 파일에서 임포트시 의존하는 파일이 있는 경우(임포트하
는 모듈이 다른 모듈을 임포트하는 경우) 셸에서 가장 먼저 이들 이 방법은 다음과 똑같은 효과를 낸다.
파일을 써야 한다. 그렇지 않은 경우는 에러를 발생하거나 상당히 일반적인 보안의 정의는 네트워크 환경 하의 시스템 보안과 네트
PYCHECKER_DISABLED=1 /path/to/your/program
많은 양의 경고 메시지가 뜨게 된다. 워크 보안으로 나눌 수 있다. 먼저 시스템 보안은 호스트나 컴퓨
PyChecker에 몇 가지 옵션을 주고 싶다면 커맨드 라인에서 옵 터 단말기와 같은 개체에 존재하는 보안 위협요소를 제거하고 항
션을 주거나 .pycheckrc 파일에 몇 가지 옵션을 넣는 것으로 가능 상 가용한 상태를 유지하기 위한 기술로 정의할 수 있다. 네트워
하다. pycheckrc의 옵션을 보고 싶다면 다음과 같이 하면 된다. 지금까지 대략적인 보안 요소들과 이를 이용하는 방법에 대해 알 크 보안은 네트워크 환경이 발전해감에 따라 점점 발전하고 있는
아봤다. 언어에서의 보안은 전체적인 시스템의 보안만큼이나 중 분야인데, 네트워크 상에서 정보의 유출이나 변조 등에 따른 보안
pychecker -h
요하고 까다로운 요소로 동작한다. 또한 언어를 통해 만들어진 프 위협을 방지하기 위한 기술에 대한 것으로 표준단체에 의해 표준
로그램은 언어가 가지는 보안상 문제점을 그대로 이어받는다는 화가 이뤄지고 있다.
pychecker에서는 간단한 GUI는 지원하지만 그렇게 효과적으 점에서 더욱 섬세한 작업이 필요하다. 따라서 설계나 실제 코딩 네트워크 보안의 경우 ISO 7498-2, 보안 구조에서는 보안 서
로 지원하지는 않는다. 몇 가지 옵션에 관한 설정 등은 다음과 같 시에는 필요한 작업 이상의 자원을 사용하거나 불필요한 요소가 비스를 신분 확인(entry authentication security services), 접근
이 실행시키면 된다. 발생하는지를 살펴 효과적인 코드를 구성해야 한다. 통제(access control security services), 비밀보장(data
confidentiality security services), 데이터 무결성(data integrity
python pychecker/options.py
security services), 부인방지(non-repudiation security
services)로 정의하고 있는데, 이러한 보안 서비스들은 보통 여러
� IATF : http://www.iatf.net/
� Secure Programming for Linux and Unix HOWTO : http://kldp.org/ 인터넷이라는 가상 공간은 모든 사람들이 쉽고 편리하게 데이터 가지 메커니즘을 통해 복합적으로 제공되고 있다.
PyChecker를 파이썬 코드에서 사용하는 방법은 단순히 임포트하 HOWTO/html/Secure-Programs-HOWTO/ 공유를 가능케 하지만, 그 편리함 만큼이나 인터넷이 가지는 개방 예를 들면, 부인방지 서비스 제공을 위해 사용되는 디지털 서명
� PyChecker 공식 페이지 : http://pychecker.sourceforge.net
면 된다. 성과 익명성은 많은 위험 요소들을 가지고 있음을 명심해야 한다. 의 경우 RSA나 Rabin, ElGamal과 같은 공개키 암호화 방식과
하루에도 수십 통씩 주고받는 메일이나 쇼핑몰에서 물건 구매를 대칭키 암호 방식, 그리고 SHA(Secure Hash Algorithm)와 같
import pychecker.checker
위해 입력한 신용카드 번호가 알지 못하는 사이에 타인에 의해 도 은 해시 함수를 복합적으로 사용하고 있다.
용당할 수도 있다. 하지만 현재의 인터넷이 그렇게 위험한 공간만
이렇게 하면 PyChecker 다음으로 임포트되는 모든 모듈에 대 은 아니다. 인터넷에 구축된 대부분의 시스템들은 내부적으로 보
해 검사가 시작된다. 주의할 점은 PyChecker 이전에 임포트되는 안 루틴들이 적용되어 있어 중요한 데이터가 타인에 의해 도용된 윈도우 NT 시스템은 다른 윈도우 시스템에 비해 보안에 대한 개
모듈에 한해서는 검사 기능이 이뤄지지 않는다는 점이다. 경고 다든지 하는 위험에서 안전하게 보호되고 있다. 그렇다고 100% 념이 잡혀 있는 시스템이다. 이러한 것은 NT 응용 프로그램 구성
사항은 표준 출력(stdout)을 통해 출력된다. 이런 경우 커맨드 라 보호되고 안전하다고 확신해서는 안 된다. 시에 사용되는 파일, 파이프, 쓰레드, 동기화 객체, 공유 메모리
인 파라미터를 전달할 수 없는데 이때는 다음과 같은 방법을 사 네트워크가 발달되지 않았을 때 보안은 시스템 구축시 크게 중 등의 시스템 자원을 보면 알 수 있다. NT 시스템 자원을 생성할
용한다. 요시되지 않았다. 물리적으로 외부에 공개되어 있지 않기 때문에, 때, 일반적으로 사용되지 않지만 보안 설정을 위해 SECURITY
내부 관리만 잘 되면 데이터가 유출되는 경우는 발생할 수 없었기 _ATTRIBUTES 구조체가 인자로 사용된다. 이 구조체는 NT 보
‘PYCHECKER’
os.environ[ ] =‘커맨드 라인 옵션’
때문이다. 설령 외부 시스템과의 통신이 필요하더라도 인터넷 망 안 체계의 최상위 레벨의 엔트리 포인트로 자원에 대한 상속성과
이 아니라 사설망을 통한 전용회선을 사용했기 때문에 시스템 침 접근성을 결정한다. 다음은 SECURITY_ATTRI BUTES 구조체
이 방법은 셸 환경변수 PYCHECKER를 등록하는 것과 동일 입의 경로가 제한적이었고, 보안을 위해 소모되는 관리 비용도 그 의 내용이다.
하다. 리 많지 않았다. 하지만 요즘처럼 대부분의 시스템이 인터넷에 연
typedef struct _SECURITY_ATTRIBUTES {
결되어 있는 상황에서는 시스템 침입에 대비한 다양한 장치를 마
DWORD nLength;
PYCHECKER=’
no-namedargs maxreturns=0’/path/to/your/program
련해 두지 않으면 시스템은 물론 데이터에 막대한 손실을 초래할 LPVOID lpSecurityDescriptor;
수 있다. BOOL bInheritHandle;
} SECURITY_ATTRIBUTES;
예를 들어, PyChecker에서 주어지는 경고가 귀찮다면 다음과 이렇듯 보안은 시간이 지날수록 점점 중요한 위치를 차지해 가
같은 방법으로 설정할 수 있다. microsoftware 는 분야가 되어 가고 있다. 이번 호에서는 보안에 대한 간단한 정
의와 실제 시스템 개발시 도움이 될 수 있는 Win32 환경에서의
‘PYCHECKER_DISABLED’
os.environ[ ] = 1
보안 관련 정보 및 C/C++ 언어 기반의 암호화 관련 라이브러리
import pychecker.checker
를 살펴보겠다.
nLength에는 SECURITY_ATTRIBUTES 구조체의 크기가 전 베이스로부터 구하고, 사용자 접근 토큰에 위치시킨다. 시스템은 <리스트 1> 파일 접근 권한 정보 출력 예제 lpTemp += sizeof(ACCESS_MASK);

달되고, lpSecurityDescriptor에는 SECURITY_DESCRIP TOR의 사용자가 행한 동작에서 윈도우 보안 관련 정보가 필요할 때마다 pSID = (PSID) lpTemp;
VOID RunTests(LPTSTR lpName, SECURITY_INFORMATION *pSecurityInfo)
switch(pACEHeader->AceType)
포인터가 전달된다. bInheritHandle가 TRUE이면 자식 프로세스 이 값을 사용한다. {
{
는 부모 프로세스가 생성한 객체를 상속받게 된다. <표 1>은 NT 보안 체계에서는 SID와 함께 ACL(Access Control List) BYTE bySDBuffer[8192];
case ACCESS_ALLOWED_ACE_TYPE : lpVerb =“granted to”
;
PSECURITY_DESCRIPTOR lpSecurityDescriptor = (PSECURITY_DESCRIPTOR)bySDBuffer;
SECURITY_ATTRIBUTES 구조체를 인자로 받는 함수 목록이다. 이라는 자료형을 사용한다. ACL은 어떤 객체에 대해 누가 사용 break;
DWORD dwSDSize;
case ACCESS_DENIED_ACE_TYPE : lpVerb =“denied to”
;
그렇다고 <표 1>에 나열되지 않은 함수들이 보안 특성을 가지 가능한지 불가능한지를 결정하는 데 사용된다. ACL은 0개 이상 dwSDSize = sizeof(bySDBuffer);
break;
지 않는 것은 아니다. 예를 들어 CreateWindow 함수는 SECU 의 ACE(Access Control Entry)를 가질 수 있는데, ACE는 트러 // 파일의 Security Descriptor 정보를 구한다.
case SYSTEM_AUDIT_ACE_TYPE : lpVerb =“being audited for”
;
if (!GetFileSecurity(lpName, *pSecurityInfo, lpSecurityDescriptor, dwSDSize, &dwSDSize))
RITY_ATTRIBUTE 인자를 받지 않지만, NT에서는 screen 기 스티에 의해 지정된 객체에 대한 접근을 제어하고 감시한다. break;
return;
case SYSTEM_ALARM_ACE_TYPE : lpVerb =“being audited for”
;
반 객체들과 같은 보안 레벨을 유지한다. 즉, CreateWindow 함 SID 값은 내부적으로 매우 복잡한 이진화된 숫자인데, 개발 레 DumpDACL(lpName, lpSecurityDescriptor);
break;
수에서 생성된 HWND 핸들은 사용자가 로그인한 후 생성한 윈 벨에서는 SID를 읽을 수 있는 문자로 표현해야 할 경우도 있다. }
}
// ACL 정보 출력
도우 스테이션(window station)과 쓰레드 데스크톱의 보안 설정 NT에서는 이를 위해 SID로 이름을 구할 수 있는 Lookup if(DumpSID(pSID, szSIDName, szNameType))
VOID DumpDACL(LPTSTR lpName, PSECURITY_DESCRIPTOR pSD)
printf(“\n Access rights %08X %s %s on %s”, dwAccessMask, lpVerb, szSIDName, lpName);
을 그대로 상속받게 된다. AccountSid() 함수와 Everyone과 같은 이름으로 SID를 구할 수 {
}
SECURITY_ATTRIBUTE에 포함된 SECURITY_DESCRIP 있는 LookupAccountName() 함수를 제공한다. 다음은 각 함수 PACL pACL = NULL;
}
BOOL bDACLPresent;
TOR의 형태에 대한 정보는 공개되어 있지 않은데, SECURITY_ 에 대한 원형이다.
BOOL bDACLDefaulted;
BOOL DumpSID(PSID pSID, LPTSTR lpSIDName, LPTSTR lpNameType)
DESCRIPTOR에는 다음과 같은 정보가 들어 있다.
{
BOOL LookupAccountName( if(!GetSecurityDescriptorDacl(pSD, &bDACLPresent, &pACL, &bDACLDefaulted))
TCHAR szAccount[256];
LPCTSTR lpSystemName, // system name
return;
◆ 객체의 소유자. 이것은 SID(Security Identifier)로 표현된다. LPCTSTR lpAccountName, // account name DWORD dwAccountSize = sizeof(szAccount);

◆ 소유자가 속한 1차 그룹에 대한 정보. 이 그룹 정보는 NT 사용자 계정이 생성 PSID Sid, // security identifier TCHAR szDomain[256];
if(pACL != NULL) DumpACEs(pACL, lpName);
LPDWORD cbSid, // size of security identifier DWORD dwDomainSize = sizeof(szDomain);
될 때 지정된다. else “\n%d 파일은 NULL DACL입니다.\n”
printf( , lpName);
LPTSTR DomainName, // domain name SID_NAME_USE SidNameUse;
◆ DACL(Discretionary Access Control List) : 객체에 누가 어떤 제어를 할 수
LPDWORD cbDomainName, // size of domain name
있는지를 결정한다. PSID_NAME_USE peUse // SID-type indicator “\n”
printf( );
if(!LookupAccountSid(NULL, pSID, szAccount, &dwAccountSize, szDomain,
); }
◆ SACL(System Access Control List) : 어떻게 객체의 사용을 감시할 수 있는 &dwDomainSize, &SidNameUse))
// ACE 정보 출력
지를 지정한다. return FALSE;
BOOL LookupAccountSid( VOID DumpACEs(PACL pACL, LPTSTR lpName)
sprintf(lpSIDName, szAccount);
LPCTSTR lpSystemName, // name of local or remote computer {
if(lpNameType != NULL)
PSID Sid, // security identifier BYTE byBuffer[1024];
sprintf(lpNameType,“%s”
, SidNames[SidNameUse]);
객체의 소유자를 관리하기 위해 GetSecurityDescriptorOwner LPTSTR Name, // account name buffer ACL_SIZE_INFORMATION *pACLSize = (ACL_SIZE_INFORMATION *)byBuffer;
LPDWORD cbName, // size of account name buffer LPVOID pACE;
() 함수와 SetSecurityDescriptorOwner() 함수가 제공되는데, LPTSTR DomainName, // domain name
return TRUE;
ACE_HEADER *pACEHeader;
}
이 함수는 객체 소유자의 SID를 요구한다. SID는 윈도우 NT 보 LPDWORD cbDomainName, // size of domain name buffer LPBYTE lpTemp;
PSID_NAME_USE peUse // SID type
안 데이터베이스에 존재하는 유일한 값으로 트러스티(trustee), TCHAR szSIDName[256];
void main(int argc, char* argv[])
);
TCHAR szNameType[256];
즉 사용자 계정, 그룹 계정, 연결 세션(login session)을 구분하는 {
DWORD dwAccessMask;
HANDLE hFile;
정보이다. SID는 보통 윈도우 도메인 컨트롤러와 같은 권한이 있 PSID pSID;
SECURITY_INFORMATION SecurityInformatin = DACL_SECURITY_INFORMATION;
는 시스템에 의해 발행되고 보안 데이터베이스에 저장된다. 만약 LookupAccountSid() 함수와 LookupAccountName() 함수를 LPTSTR lpVerb;

사용자가 시스템에 로그인하면 시스템은 사용자의 SID를 데이터 보면 SID 유형이 나오는데 SID는 크게 사용자, 그룹, 도메인, 별 // SECURITY_ATTRIBUTE가 NULL로 임시 파일을 연다.
if(pACL==NULL) return;
hFile = CreateFile(argv[1], GENERIC_ALL, 0, NULL, // SECURITY_ATTRIBUTE is NULL
명(alias), 잘 알려진 그룹, 삭제된 계정으로 구분된다.
CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL);
<표 1> SECURITY_ATTRIBUTES 구조체를 인자로 받는 함수 목록 <리스트 1>은 NTFS 시스템에서 임의의 파일을 생성한 후 해당 if(!GetAclInformation(pACL, byBuffer, sizeof(byBuffer), AclSizeInformation))
if(hFile==INVALID_HANDLE_VALUE)
return;
CreateFile CreateMailslot 파일의 보안 설정 정보를 출력해 주는 예이다. <리스트 1>에서는 {
CreateProcess CreateProcessAsUser “\n파일을 생성할 수 없습니다. GetLastError() = %d\n”
printf( , GetLastError());
파일명을 인자로 받아서 해당 파일의 GetFileSecurity() 함수로 for(DWORD i=0; i<pACLSize->AceCount; i++)
CreateConsoleScreenBuffer CreateDesktop ExitProcess(1);

CreateDirectory(Ex) CreateEvent SECUTIRY_DESCRIPTOT를 구하고, GetSecurityDescriptor {


}
if(!GetAce(pACL, i, &pACE)) continue;
CreateFileMapping CreateMutex Dacl() 함수로 DACL 정보, GetAclInformation() 함수로 ACE CloseHandle(hFile);
pACEHeader = (ACE_HEADER *)pACE;
CreateNamedPipe CreatePipe RunTests(argv[1], &SecurityInformatin);
정보를 구해 그 정보를 화면에 출력해 준다. ACE 정보에는 SID lpTemp = (LPBYTE)pACE;
CreateRemoteThread CreateSemaphore ExitProcess(0);
정보가 들어 있고 LookupAccountSid() 함수로 해당 사용자에 대 lpTemp += sizeof(ACE_HEADER);
}
CreateThread CreateWindowStation
dwAccessMask = *(ACCESS_MASK *) lpTemp;
RegCreateKeyEx RegSaveKey 한 정보를 구한 후 화면에 출력한다.
살펴보자. <리스트 2> 파일 암호화 예제 ..........................

마이크로소프트는 응용 프로그램 개발자가 윈도우에서 암호화 기 <리스트 2>는 파일을 암호화하는 예제이다. <리스트 2>는 사용 }
// 본 소스는 MSDN에 제공하는 Example C Program: Encrypting a File 중 일부이다. else
능과 디지털 서명 기능을 사용할 수 있도록 CryptoAPI를 제공하 자로부터 파일명과 암호를 입력받아 세션 키를 생성한 뒤, 그 키 #define MY_ENCODING_TYPE (PKCS_7_ASN_ENCODING | X509_ASN_ENCODING) {
#define KEYLENGTH 0x00800000 // 암호가 존재하면 패스워드로부터 생성된 세션 키로 암호화한다.
고 있다. CryptoAPI는 인터넷 익스플로러(이하 IE) 3.0 이상이 로 파일을 암호화한다. 이때 세션 키의 생성을 위해 사용자가 암
#define ENCRYPT_ALGORITHM CALG_RC4 // 해시 객체 생성 : MD5 알고리즘 사용
설치된 시스템에는 모두 설치되어 있기 때문에 윈도우 환경에서 호를 입력하지 않았으면 CryptGenKey() 함수와 CryptGet #define ENCRYPT_BLOCK_SIZE 8 if(CryptCreateHash(hCryptProv, CALG_MD5, 0, 0, &hHash))

쉽게 사용할 수 있는 암호화 라이브러리라고 할 수 있다. IE의 도 UserKey() 함수를 이용해 세션 키를 생성하고, 암호가 존재하면 ..........................
// szSource : 입력 파일명
움말을 보면 암호화 수준이 출력되는데, 이것이 CryptoAPI에 의 해당 암호를 MD5 알고리즘을 적용시키고 이 값으로 세션 키를 // szDestination : 출력 파일명 // 패스워드를 MD5 알고리즘을 적용시킨다.
// szPassword : 암호 if(CryptHashData(hHash, (BYTE *)szPassword, strlen(szPassword), 0))
해 출력되는 것이다. 생성한다. 소스를 보면 세션 키는 RC4 알고리즘에 맞게 생성되
static BOOL EncryptFile(PCHAR szSource, PCHAR szDestination, PCHAR szPassword) ..........................
CryptoAPI의 특징은 다양한 암호화 알고리즘은 단일한 인터페 고, 이 키 값으로 CryptEncrypt() 함수에서는 암호화 작업을 수 {
FILE *hSource; // 해시 객체로부터 키를 생성한다.
이스로 사용가능하도록 CSP(Cryptographic Service Provider) 행한다.
FILE *hDestination; if(CryptDeriveKey(hCryptProv, ENCRYPT_ALGORITHM, hHash, KEYLENGTH, &hKey))
라는 확장 모듈 형식을 제공한다는 점이다. CSP 형식으로 구성된 .................... ..........................
....................
암호화 알고리즘 모듈은 CryptoAPI 형식으로 사용할 수 있게 한
// Hash 객체 제거
다. 마이크로소프트는 기본 CSP로 RSA, DSA(Digital Crypto++ 라이브러리는 인터넷에서 쉽게 구할 수 있는 공개된 // 입력 파일 오픈 CryptDestroyHash(hHash);
if(!(hSource = fopen(szSource,”
rb”
))) hHash = 0;
Signature Algorithm), NIST(National Institute of Standards C++용 암호화 라이브러리다. 이것은 RSA, ECC, DSA, SHA-
return FALSE; }
and Technology) 등을 제공하고 있다. CSP를 PROV_FSA_ 1, RC6, Twofish 등 현존하는 대부분의 암호화 알고리즘을 사용 // 한 번에 암호화할 수 있는 블럭 크기를 구한다.
// 출력 파일 오픈 // 블럭 크기는 ENCRYPT_BLOCK_SIZE의 배수이어야 한다.
FULL로 해서 선택할 경우 RSA 암호화를 위해서는 RC2와 RC4 할 수 있을 뿐만 아니라 Win32 환경은 물론 유닉스, DOS,
if(!(hDestination = fopen(szDestination,”
wb”
))) dwBlockLen = 1000 - 1000 % ENCRYPT_BLOCK_SIZE;
방식을, 해싱을 위해서는 MD5와 SHA 방식을 사용할 수 있다. BeOS, Mac OS 등 다양한 플랫폼을 지원하고 있어 암호화 적용 return FALSE; if(ENCRYPT_BLOCK_SIZE > 1)

CryptoAPI를 사용하기 위해서는 우선 어떤 CSP를 사용할 것 이 필요한 시스템에 쉽게 적용할 수 있다. 이 라이브러리에 대한 dwBufferLen = dwBlockLen + ENCRYPT_BLOCK_SIZE;
// 기본 CSP인 PROV_RSA_FULL을 사용 else
인지를 선택해야 한다. CryptAcquireContext()를 호출해 핸들을 설명은 지면 관계상 소개하는 정도에서 마칠까 한다. Crypto++ if(CryptAcquireContext( &hCryptProv, NULL, MS_ENHANCED_PROV, PROV_RSA_FULL, 0)) dwBufferLen = dwBlockLen;
......................
구한 후 사용이 끝나면 CryptReleaseContext() 함수를 호출해 라이브러리의 홈페이지인 http://www.cryptopp.com에 방문하
// 메모리 할당
핸들을 제거한다. 면, 최신 4.2 버전의 소스 파일과 예제, 도움말 등을 볼 수 있으므 // 세션 키 생성 if(pbBuffer = (BYTE *)malloc(dwBufferLen))
if(!szPassword ) // 패스워드가 없으면 키를 생성한다. ......................
로 참조하기 바란다. 소스의 경우 비주얼 C++에서 바로 불러들
{ do
BOOL WINAPI CryptAcquireContext(
일 수 있게 프로젝트 파일이 생성되어 있으므로 Win32 환경에서 if(CryptGenKey(hCryptProv, ENCRYPT_ALGORITHM, KEYLENGTH | CRYPT_EXPORTABLE, &hKey)) {
HCRYPTPROV *phProv, // CSP 핸들을 돌려받기 위한 포인터
...................... // 버퍼 크기만큼 파일에서 읽기
LPCTSTR pszContainer, // key container의 이름을 지정한다. 쉽게 테스트할 수 있을 것이다. 최근에는 닷넷 플랫폼에 적용할
dwCount = fread(pbBuffer, 1, dwBlockLen, hSource);
LPCTSTR pszProvider, // 사용할 CSP의 이름을 지정한다. NULL 가능 수 있는 정보가 추가됐다. // 공개 키를 구한다. if(ferror(hSource)) // 파일 읽기에서 오류
DWORD dwProvType, // provider 종류 지정
if(CryptGetUserKey(hCryptProv, AT_KEYEXCHANGE, &hXchgKey)) ...........................
DWORD dwFlags // flag .......................
); // 암호화
// 키 저장을 위해 키 저장 공간 크기를 구하고 해당 메모리를 할당한다. if(!CryptEncrypt(hKey, 0, feof(hSource), 0, pbBuffer, &dwCount, dwBufferLen))
앞서 설명한 CryptoAPI를 이용해 해시 값을 구할 수도 있지만,
BOOL WINAPI CryptReleaseContext( if(CryptExportKey(hKey, hXchgKey, SIMPLEBLOB, 0, NULL, &dwKeyBlobLen)) ............................
HCRYPTPROV hProv, // CryptAcquireContext 함수 호출로 구한 CSP 핸들 해시 루틴은 많이 사용되므로 특정 라이브러리에 종속적이지 않 ........................
DWORD dwFlags // 암호화된 결과를 파일에 저장
게 함수를 보유하고 있어도 나쁘지 않을 것이다. 우선 MD5 알고
); if(pbKeyBlob =(BYTE *)malloc(dwKeyBlobLen)) fwrite(pbBuffer, 1, dwCount, hDestination);
리즘에 대해 살펴보자. MD5 알고리즘은 RSA에서 제시한 알고 ........................ if(ferror(hDestination)) // 파일 쓰기 오류 발생

리즘으로 RFC 1321에 그 방법이 명시되어 있다. MD5, 정확히 ...........................


// 세션 키를 암호화해 pbKeyBlob에 저장한다. } while(!feof(hSource));
암호화 방식에 쓰는 키는 CryptGetKey() 함수나 CryptDerive 명시하면 MD5 message-digest 알고리즘이다. MD5 알고리즘은 if(CryptExportKey(hKey, hXchgKey, SIMPLEBLOB, 0, pbKeyBlob, &dwKeyBlobLen)) // 비초기화 작업 : 생성된 핸들 제거
........................ if(hSource) fclose(hSource);
Key() 함수를 사용해 만들거나 CryptImportKey 함수를 써서 기 임의의 길이의 메시지를 128비트의 데이터로 변환해 준다. MD5
if(hDestination) fclose(hDestination);
존의 키를 불러올 수도 있다. CryptoAPI와 관련된 모든 키는 알고리즘은 서로 다른 메시지가 같은 결과 값을 가지는 경우가 발 // 핸들 해제
CryptDestroyKey(hXchgKey); if(pbBuffer) free(pbBuffer);
CSP 내에 보관되며 CSP는 키의 생성 및 제거와 관련된 작업의 생할 수 없는 알고리즘으로 디지털 서명에 응용되고 있다. 그 사
hXchgKey = 0; if(hKey) CryptDestroyKey(hKey);
수행을 책임진다. 이렇게 만들어진 키 값 자체에 대해 알고 싶다 용 방법은 다음과 같다. if(hXchgKey) CryptDestroyKey(hXchgKey);
// 키 길이를 목적 파일에 저장한다. if(hHash) CryptDestroyHash(hHash);
면 CryptoExportKey() 함수를 이용하면 된다. 이 함수를 이용해
fwrite(&dwKeyBlobLen, sizeof(DWORD), 1, hDestination);
CSP 내부에 생성된 키 값은 BLOB 형식으로 되어 있기 때문에 ........................ if(hCryptProv) CryptReleaseContext(hCryptProv, 0);
// 키를 저장한다. return(TRUE);
키 크기를 우선 구한 후 그 값을 구해야 한다. CryptoAPI에는 이 우선 메시지는 그 길이가 448 modulo 512가 되도록 확장된다.
fwrite(pbKeyBlob, 1, dwKeyBlobLen, hDestination); } // End of Encryptfile
외에 암호화를 위한 다양한 함수를 제공한다. 실제 예를 보면서 즉, 그 길이가 512비트(16워드)의 배수에서 64비트(2워드)가 모
자라도록 확장된다는 것이다. 이러한 패딩(padding)은 반드시 행 시지를 M[0…N-1]로 표현하자. M[0], M[1] 등은 워드이고 N [ABCD 5 5 21] [DABC 10 9 22] [CDAB 15 14 23] [BCDA 4 20 24]
[ABCD 9 5 25] [DABC 14 9 26] [CDAB 3 14 27] [BCDA 8 20 28]
해져야 한다. 즉, 원래 메시지의 길이가 이미 448 modulo 512라 메시지 길이 b의 64비트 표현을 스텝 1의 결과에 추가한다. 만약 은 16의 배수이다. [ABCD 13 5 29] [DABC 2 9 30] [CDAB 7 14 31] [BCDA 12 20 32]
하더라도 패딩(이 경우 512비트를 더한다)을 해야 한다. 패딩은 메시지의 길이가 2^64를 넘어간다면, b의 하위 64비트를 추가한 /* Round 3. */
/* Let [abcd k s t] denote the operation
다음과 같이 수행된다. 다. 이 시점에서 메시지는 512비트(16워드)의 배수가 되는 길이
a = b + ((a + H(b,c,d) + X[k] + T[i]) <<< s). */
를 갖게 된다. 즉 이 메시지를 워드 단위로 쪼갤 경우 그 블럭의 네 개의 워드 버퍼 A, B, C, D가 message-digest 연산에 사용된 /* Do the following 16 operations. */
◆ 하나의‘1’
비트가 일단 메시지에 더해진다. [ABCD 5 4 33] [DABC 8 11 34] [CDAB 11 16 35] [BCDA 14 23 36]
개수는 정확히 16의 배수가 된다는 뜻이다. 여기까지의 결과 메 다. 각 버퍼는 32비트 레지스터이며 이들 레지스터는 다음의 값
[ABCD 1 4 37] [DABC 4 11 38] [CDAB 7 16 39] [BCDA 10 23 40]
◆ 그 다음 메시지 길이가 448 modulo 512가 될 때까지‘0’비트들이 더해진다. 으로 초기화된다(16진수, low-order bytes first). [ABCD 13 4 41] [DABC 0 11 42] [CDAB 3 16 43] [BCDA 6 23 44]
[ABCD 9 4 45] [DABC 12 11 46] [CDAB 15 16 47] [BCDA 2 23 48]
<리스트 3> MD 5 알고리즘 구현 소스 예 memset(m_Count, 0, 2 * sizeof(uint4));
Word A : 01 23 45 67 /* Round 4. */
memset(m_State, 0, 4 * sizeof(uint4));
Word B : 89 ab cd ef /* Let [abcd k s t] denote the operation
// szString에 MD5 알고리즘을 적용한 값을 구한다. memset(m_Buffer,0, 64 * sizeof(uchar));
char* MD5String(char* szString) Word C : fe dc ba 98 a = b + ((a + I(b,c,d) + X[k] + T[i]) <<< s). */
}
{ Word D : 76 54 32 10 /* Do the following 16 operations. */
int nLen = strlen(szString); void md5::Transform (uchar* block)
[ABCD 0 6 49] [DABC 7 10 50] [CDAB 14 15 51] [BCDA 5 21 52]
md5 alg; { [ABCD 12 6 53] [DABC 3 10 54] [CDAB 10 15 55] [BCDA 1 21 56]
alg.Update((unsigned char*)szString, (unsigned int)nLen); uint4 a = m_State[0], b = m_State[1], c = m_State[2], d = m_State[3], x[16]; [ABCD 8 6 57] [DABC 15 10 58] [CDAB 6 15 59] [BCDA 13 21 60]
alg.Finalize(); [ABCD 4 6 61] [DABC 11 10 62] [CDAB 2 15 63] [BCDA 9 21 64]
return PrintMD5(alg.Digest()); Decode (x, block, 64);
32비트 워드를 입력으로 받아 32비트 워드를 출력하는 다음의 네 /* Then perform the following additions. (That is increment each
} // Round 1 개 함수를 우선 정의하자. of the four registers by the value it had before this block
void md5::Init() FF (a, b, c, d, x[ 0], S11, 0xd76aa478); was started.) */
{ .................. // 생략 A = A + AA
memset(m_Count, 0, 2 * sizeof(uint4)); F(X,Y,Z) = XY v not(X) Z G(X,Y,Z) = XZ v Y not(Z)
// Round 2 B = B + BB
m_State[0] = 0x67452301; GG (a, b, c, d, x[ 1], S21, 0xf61e2562);
H(X,Y,Z) = X xor Y xor Z I(X,Y,Z) = Y xor (X v not(Z))
C = C + CC
m_State[1] = 0xefcdab89; .................. // 생략 D = D + DD
m_State[2] = 0x98badcfe; // Round 3 end /* of loop on i */
m_State[3] = 0x10325476; HH (a, b, c, d, x[ 5], S31, 0xfffa3942);
}
그리고 sine 함수로부터 구성된 64개의 엘리먼트 테이블
................... // 생략
void md5::Update(uchar* chInput, uint4 nInputLen) //Round 4 T[1..64]를 정의하자. T[i]는 테이블의 i번째 원소로서
{ II (a, b, c, d, x[ 0], S41, 0xf4292244);
uint4 i, index, partLen;
4294967296 * abs(sin(i))의 정수부만 취한다. 그 후에 다음과
................... // 생략
index = (unsigned int)((m_Count[0] >> 3) & 0x3F); m_State[0] += a; m_State[1] += b; 같이 한다. 최종적인 message-digest 결과 값은 A, B, C, D의 값이다(A의
if ((m_Count[0] += (nInputLen << 3)) < (nInputLen << 3)) m_State[2] += c; m_State[3] += d;
low order byte에서부터 D의 high-order byte까지). 길이는 4워
m_Count[1]++; memset(x, 0, sizeof(x));
/* Process each 16-word block. */
m_Count[1] += (nInputLen >> 29); } 드, 즉 128비트이다.
For i = 0 to N/16-1 do
partLen = 64 - index; void md5::Encode(uchar* dest, uint4* src, uint4 nLength)
/* Copy block i into X. */ MD5 알고리즘을 구현해 놓은 소스가 <리스트 3>으로 CODE
if (nInputLen >= partLen) {
{ uint4 i, j;
For j = 0 to 15 do GURU 웹 사이트(www.codeguru.com)에 Garu McNickle의 소
memcpy( &m_Buffer[index], chInput, partLen ); Set X[j] to M[i*16+j].
end /* of loop on j */ 스를 일부 발췌한 것이다. 이 소스는 RFC 1321에 있는 소스를
Transform(m_Buffer); // 16워드 블럭 메시지 처리 부분 assert(nLength % 4 == 0);
for (i = partLen; i + 63 < nInputLen; i += 64) for (i = 0, j = 0; j < nLength; i++, j += 4) /* Save A as AA, B as BB, C as CC, and D as DD. */ C++용 클래스로 옮겨 놓은 것인데, 자세한 소스는 RFC 1321
Transform(&chInput[i]); { AA = A
또는 CODEGURU를 참조하기 바란다.
index = 0; dest[j] = (uchar)(src[i] & 0xff); BB = B
}else dest[j+1] = (uchar)((src[i] >> 8) & 0xff); CC = C
i = 0; dest[j+2] = (uchar)((src[i] >> 16) & 0xff); DD = D
// Buffer remaining input dest[j+3] = (uchar)((src[i] >> 24) & 0xff); /* Round 1. */
fileaccess.zip http://www.sbmedia.co.kr/maso
memcpy( &m_Buffer[index], &chInput[i], nInputLen-i ); } /* Let [abcd k s i] denote the operation
} } a = b + ((a + F(b,c,d) + X[k] + T[i]) <<< s). */
void md5::Finalize() void md5::Decode(uint4* dest, uchar* src, uint4 nLength) /* Do the following 16 operations. */
{ { [ABCD 0 7 1] [DABC 1 12 2] [CDAB 2 17 3] [BCDA 3 22 4]
uchar bits[8]; uint4 i, j; [ABCD 4 7 5] [DABC 5 12 6] [CDAB 6 17 7] [BCDA 7 22 8] � 마이크로소프트 MSDN : http://msdn.microsoft.com
uint4 index, padLen; assert(nLength % 4 == 0);
[ABCD 8 7 9] [DABC 9 12 10] [CDAB 10 17 11] [BCDA 11 22 12] � 코드구루 : http://www.codeguru.com
Encode (bits, m_Count, 8); for (i = 0, j = 0; j < nLength; i++, j += 4)
[ABCD 12 7 13] [DABC 13 12 14] [CDAB 14 17 15] [BCDA 15 22 16] � Crytp++ : http://www.cryptopp.com
index = (unsigned int)((m_Count[0] >> 3) & 0x3f); {
/* Round 2. */ � Win32 네트워크 프로그래밍, Ralph Davis 저, Addison Wesley
padLen = (index < 56) ? (56 - index) : (120 - index); dest[i] = ((uint4)src[j]) | (((uint4)src[j+1])<<8) |
/* Let [abcd k s i] denote the operation Developers Press
Update(PADDING, padLen); (((uint4)src[j+2])<<16) | (((uint4)src[j+3])<<24);
a = b + ((a + G(b,c,d) + X[k] + T[i]) <<< s). */
Update (bits, 8); }
/* Do the following 16 operations. */
Encode (m_Digest, m_State, 16); }
[ABCD 1 5 17] [DABC 6 9 18] [CDAB 11 14 19] [BCDA 0 20 20]
입력해야 했으므로 유지보수가 귀찮고 까다로웠다. 즉 보안에 대 <authentication mode=”
Forms”>
<forms name=”diky”loginUrl=”
Login.aspx”
></forms>
한 설정이 바뀔 때마다 해당 페이지의 코드를 변경해야 했다. 윈 여기서는 웹 프로그램에서 가장 많이 쓰이는 Form 방식으로 보 </authentication>
도우 계정을 사용하는 방식은 모든 사용자의 계정을 Active 안 처리하는 예제를 다룬다. Form 방식으로 보안 처리를 하면,
Directory에 저장하고 그 정보를 사용하는 방식이기 때문에 다수 사용자의 로그인 정보가 쿠키 형태로 컴퓨터에 남겨진다(쿠키
의 사용자를 가지고 있는 웹 애플리케이션에서 사용하기엔 무리 설정에 따라 사용자의 컴퓨터에 쿠키를 남길 수도, 삭제할 수도
가 많았다. 있다). <authorization> 태그 안에 allow 혹은 deny 태그를 첨가해 사용자
ASP.NET에서는 web.config이라는 설정 파일을 이용해 각 파 Form 방식을 사용하면 일단 IIS의 보안 설정은 Anonymous 별로 이 서버의 자원에 접근하거나 접근 제한을 지정할 수 있다.
일, 디렉토리의 보안 관계를 설정하고 관리할 수 있게 하고 있다. 방식을 사용하게 된다. 즉 웹 서버에서 보안 처리를 하는 부분은
<authorization>
Web.config 파일의 내용을 보면 인증(authentication)과 권한부 없으며, 모든 것을 ASP.NET의 프로세스에서 처리하도록 위임하
<deny users=”?”/>
여(authorization) 두 영역이 있는데, 처음에는 두 가지 영역의 는 것이다. 설정 방법은 다음과 같이 아주 간단하다. </authorization>
어감이 비슷해서 다소 혼동될 수도 있다. 전자는 애플리케이션 전 web.config 파일을 보면 <system.web> 태그 아래에
체의 보안을 어떤 방식으로 처리할 것인지를 지정하는 영역이고, <authentication>이라는 부분이 있다. 바로 여기에서 인증 관련
후자는 각 페이지별로 할당이 가능한데, 그 페이지를 어떤 사용자 처리를 다음과 같이 지정한다. 앞의 예제는 anonymous 사용자의 경우는 현재 디렉토리에 접
가 이용하게 할 것인지를 지정한다. 근할 수 없도록 지정한 것이다. VS.NET에서 모든 웹 프로젝트는
설정값”
<authentication mode=” >
하나의 가상 디렉토리로 관리되므로 웹 프로젝트에 있는
</authentication>
web.config 파일은 웹 프로젝트 전체에 영향을 미치게 된다.
ASP.NET에서는 다음과 같이 다양한 인증 방법을 제공하고 사용자를 지정하는‘?’
는 anonymous 사용자를 뜻하며,‘*’

보안이 실제로 일반인들에게 관심을 끌게 된 것은 그리 오랜 역사 있다. 자신이 사용할 인증 방법에 따라 설정 값을 앞서 설명했던 모든 사용자를 뜻한다. 권한을 지정하는 부분에서 deny라고 지정
를 가지고 있지는 않다. 특히 웹에서 보안이 화제가 된 것은 웹이 Windows/Passport/Forms/None 네 가지 중 하나를 지정한다. 하면 모두 거부한다는 것이며, allow는 모두 허용하는 것으로 지
라는 환경이 우리와 친숙해진지 오래 되지 않았기 때문에 더욱 생 ◆ Windows : 현재 쓰이고 있는 윈도우 계정에 권한을 부여하고, 로그인한 사용 그러면 웹 애플리케이션 전체에 그 인증 방식을 사용하는 것으로 정된다. <deny users=
“?”
> 부분을 <allow users=
“*”
>로 바꾸면
소한 얘기라고 할 수도 있을 것이다. 자의 역할에 따라 다양한 권한을 제어하는 방식이다. 사용자의 수가 적은 경우 지정된다. 모든 사용자에 대해 접근할 수 있도록 설정된다.
에 편리하게 사용할 수 있으며, 별도의 코딩 없이 윈도우 계정을 바로 사용하는
웹에서의 보안이라고 하면 일반적으로 웹 사이트를 방문하 다음의 소스와 같이 설정 값을 지정하면 Forms을 이용한 쿠키 만약 특정 파일에 대해 따로 인증을 제어하고 싶을 때는 <리스
방식이다. 하지만 ASP.NET으로 만든 웹 프로그램과는 별도의 윈도우 계정 관
는 사용자를 인증하고 권한을 부여하는 것이 일반적이며, 사이 방식의 인증을 사용하는 것으로 간주하며, 로그온 정보가 사용자 트 1>과 같이 web.config 파일의 기본 태그 </system.web> 밖에
리가 필요하며, 여러 사용자를 관리하기 위해서는 ADSI에 대한 프로그램을 사
트를 설계할 때 보안 처리에 대한 것은 중요한 부분을 차지하 에게 전달될 때 필요한 쿠키 이름을 지정하고 있다(쿠키 이름은 <location> 태그를 따로 지정한다. <리스트 1>은 EditAccount.
용해야 하므로 좀더 많은 노력이 필요한 단점이 있다. 사이트 관리를 위한 관리
게 된다. 그리고 닷넷 환경에서 모바일 코드는 웹을 통해 코드 자 페이지에서 사용하는 경우도 있으나 일반적인 웹 프로그램에서는 잘 사용되
사용자의 웹 브라우저에 저장될 때 그 값을 식별하기 위해 사용하 aspx 파일에 대해 Anonymous 사용자의 접근을 막기 위한 값이다.
를 배포하는 방법을 제공하고 있다. 닷넷의 모바일 코드도 안 지 않는 방식이다. 므로 일반적으로는 자신의 사이트 주소로 지정하면 된다. 물론 적
전을 위해 배포되는 위치를 통해 각각의 보안 처리를 할 필요 ◆ Passport : MS의 패스포트 제품을 이용한 인증 방식으로 간단하게 인증 부분 당한 이름으로 적당한 값을 지정해도 상관없다). 만일 인증받지 <리스트 2> Location 항목의 지정 위치
가 있다. 을 처리할 수 있는 장점이 있으나, 제품을 구입해서 설치해야 하므로 규모가 작 않은 사용자가 인증이 필요한 특정 폴더(보안이 필요한 특정 폴더
<?xml version=”
1.0”encoding=”
utf-8”?>
은 웹 사이트에서는 잘 사용되지 않는다. 이 책에서는 더 이상 자세한 내용을 는 아래의 권한부여 항목에서 지정하는 폴더를 의미한다)의 페이 <configuration>
다루지 않는다. 지를 보려고 하면 인증 페이지를 login.aspx 페이지로 바로 이동
◆ Forms : 사용자가 직접 인증 페이지를 만들고, 값을 비교해 인증 정보를 쿠키 <system.web>
웹 애플리케이션을 만드는 데 있어서 보안 처리는 아주 중요하다. 시키고, login.aspx 페이지에서 인증을 마치면 원래 요청했던 페
에 저장해 사용하는 방식으로 웹 프로그램에서 일반적으로 가장 많이 사용되는 ...여러 가지 설정값이 잔뜩 들어 있다(생략).
웹은 그 특성상 현재 누가 접속해서 정보를 원하는지 알기 어려운 이지로 자동으로 돌아간다(뒤에 나올 인증에 쓰이는 메쏘드에 따 </system.web>
방식이다. 이전 웹 프로그램에서는 따로 쿠키를 사용하는 부분을 작성해야 했
환경이므로, 중요한 정보를 다루고 있을수록 보안에 대한 대비를 라 조금 다를 수도 있지만 가장 일반적인 형태이다).
지만 닷넷에서는 인증 처리에 대한 클래스를 기본으로 제공한다.
잘 해야 한다. 특히 현재 정보를 요구하는 사용자의 권한을 정확 <!- 여기에 서브 폴더, 파일에 대한 권한 지정을 한다.>
◆ None : 아무런 인증도 하지 않는 설정. 누구나 자유롭게 사이트의 각 페이지에
<location path=”
EditAccount.aspx”
>
하게 파악하고, 웹 페이지를 동작하도록 지정하는 것이 중요하다. <리스트 1> 특정 페이지의 권한 지정
접근해 내용을 볼 수 있다. <system.web>
이전에 ASP에서 보안 처리를 하기 위해서는 IIS의 보안 설정 <location path=”
EditAccount.aspx”
> <authorization>

을 변경해 접속한 사용자의 IP에 따라 필터링을 해주거나, 윈도 <system.web> <deny users=”


?”/>

<authorization> </authorization>
우 계정을 이용해 직접 사용자에게 권한을 부여하는 방식을 사용
<deny users=”
?”/> </system.web>
했다. 또한 각 페이지마다 사용자의 정보를 확인하는 코드를 삽 </authorization> </location>
입해 각 페이지가 호출될 때마다 인증하는 방식을 사용했다. 그 </system.web>
</location> </configuration>
러나 이런 방식은 보안이 필요한 페이지마다 일정한 코드 블럭을
<리스트 2>는 <Location> 설정 값이 web.config 파일의 어디에 <화면 1> Login.aspx 페이지 디자인 ‘true’
를 반환하고 아니면‘false’
를 반환한다. 필자는 ID와 패스 을 저장해 그 권한을 읽어와 사용하는 방식이다. Authorization
들어가야 하는지 헷갈릴 독자를 위해 설정한 web.config 파일을 워드를 프로그램 안에 넣고 두 가지를 비교하는 것으로 간단하게 항목에 다음과 같이 역할에 대한 권한을 지정하는 것으로 모든 설
보여준다. 맨 마지막 부분에 추가한 서브 폴더에 권한 설정을 하 테스트했지만, 실제로 프로그램을 구현할 때는 사용자 테이블을 정은 끝난다(다음 항목은‘Manager’역할을 가진 사용자에 대해
는 부분을 주의깊게 보기 바란다. 만들어 두고, 데이터베이스와 연동해 사용자에 대한 정보를 읽어 권한을 부여했다).
와 사용자 ID와 패스워드를 비교하면 될 것이다.
“NeedLogin.aspx”
<location path= >
FormsAuthentication.RedirectFromLoginPage(txtUserID.
<system.web>
여기서는 간단하게 Forms 인증 방식을 사용해 로그인 처리를 하 NeedLogin.aspx 페이지는 Anonymous 사용자가 볼 수 없도 Text, false);은 사용자 ID를 이용해 쿠키 값에 로그인한 사실을 <authorization>
는 예제를 보여준다. 그리고 web.config 파일을 이용해 각 서브 록 지정한 것이다. 여기서는 location path에 특정 파일을 지정했 저장하는 부분이다. 이 페이지에서 인증을 마치고 나면 자동으로 “Manager”/>
<allow roles=
“*”/>
<deny users=
폴더의 권한을 부여하는 방법까지 함께 보여주고 있으므로 이번 지만 폴더를 지정하고 싶다면 폴더 이름을 직접 적어주면 된다. 처음에 호출했던 페이지로 돌아가게 된다(메쏘드의 이름은 Login </authorization>
예제에서 웹의 인증에 관한 부분을 마스터하자. 그리고 다른 파일이나 폴더에 대한 지정을 추가하고 싶다면 Page에서 원래 호출했던 페이지로 리다이렉트한다는 의미다). 두 </system.web>
</location>
</location> 태그 다음에 다음과 같이 다른 <location> 태그를 추가 번째 인자값을 true로 하면 영구적인 쿠키 값이 만들어지므로 주
� VS.NET에서 새로운 웹 프로젝트를 하나 생성한다. 웹 프로젝트의 이름은 하면 된다. 의해야 한다. 즉 웹 브라우저를 닫더라도 계속 로그인한 정보를
LoginTest로 하자. 가지게 된다. 이런 경우라면 당연히 생성된 쿠키의 유지시간을 지 각 권한에 대해 처리하고 싶으면 어디에서 그 과정을 처리해야
� WebForm1.aspx 파일의 이름을 Default.aspx로 변경한다. 링크 버튼을 하 “NeedLogin.aspx”
<location path= >
정해주는 것이 필요하다. 여기서는 false로 지정했으므로 사용자 할까? 이 때 사용하는 것이 Global.asax 파일이다. 이 파일은 모
나 추가해 NeedLogin.aspx 파일로 링크를 건다. <system.web>
<authorization> 가 웹 브라우저를 닫으면 로그인한 정보는 사라진다. 데이터베이 든 파일에 대한 작업이 수행될 때마다 사용된다. 보안에 대한 것
� web.config 파일을 열어 authentication 항목을 다음과 같이 변경한다.
“?”/>
<deny users= 스와 연동해 정보를 가져오는 부분은 지난번 ADO.NET에 대한 도 마찬가지다. Global.asax 파일의 코드 창을 열어 그 내용을 보
</authorization>
“Forms”
<authentication mode= > 기사를 참고해 작성하기 바란다. 면 다음과 같은 이벤트 처리 부분을 볼 수 있을 것이다.
</system.web>
“log”loginUrl=
<forms name= “Login.aspx”
></forms>
</location>
</authentication>
“권한 설정할 서브 폴더 이름 혹은 파일 이름”
<location path= > protected void Application_AuthenticateRequest(Object sender,
� 만들어진 프로그램을 테스트해보자. <F5> 키를 눌러서 웹 프로그램을 실행시키
<system.web> EventArgs e)
고, 링크를 눌러 인증이 필요한 페이지인 NeedLogin.aspx로 접근한다. 아까
<authorization>
“?”/>
<deny users= 만들었던 로그인 페이지(login.aspx)로 자동으로 이동해 사용자에게 ID와 패
이렇게 변경하면 사용자가 직접 로그인 페이지를 만들어서 로
</authorization> 스워드를 묻는다. 일부러 잘못된 값을 넣어보자. 그럼 입력한 값이 잘못되었다
그인 처리를 하고, 인증 정보는 쿠키 형식으로 저장된다. 예전 </system.web>
는 에러 메시지를 보여준다. 이제 제대로 된 값(ID=dazzani, Password <리스트 3> 로그 처리를 위한 코드
ASP에서는 프로그래머가 직접 코드를 작성해 각 페이지마다 현 </location>
=1234)을 입력하고 확인 버튼을 누른다. 처음에 독자가 선택했던
재 사용자가 로그인했는지 검사하고 일일이 인증 처리를 해주는 NeedLogin.aspx 페이지로 바로 이동한다.
private void btnChkID_Click(object sender, System.EventArgs e)
{
부분을 만들어야 했지만, ASP.NET에서는 System.Web.Security. � 솔루션 탐색기에서 새로운 파일을 추가해 파일 이름을 NeedLogin.aspx로 변
// 아래에 만들어 놓은 Login() 함수를 이용해 입력 값과 비교한다.
FormsAuthentication 클래스에 의해 자동으로 사용자 인증 처리 경한다. 이 페이지는 앞서 설정한 것처럼 로그인한 사람만이 볼 수 있는 페이지
bool chkID = Login(txtUserID.Text, txtPassword.Text);
가 될 것이다.
가 이뤄진다. 따라서 프로그래머는 각 사용자 정보를 어디에 저장 if (chkID)
� 솔루션 탐색기에서 새로운 파일을 추가해 파일 이름을 Login.aspx 파일로 변 {
하고 어떻게 불러와서 인증 처리를 할 것인지만 고민하면 된다. 사이트를 제작하는 경우 사용자에 따라 각기 다른 권한을 부여하
경한 뒤 <화면 1>과 같이 디자인한다. FormsAuthentication.RedirectFromLoginPage(txtUserID.Text, false);
이 설정에 따라 로그인 페이지는‘Login.aspx’
로 지정됐다. 즉 고, 다른 작업을 할 수 있는 CUG 형태의 사이트를 만들어야 하는 }
보안이 필요한 페이지를 호출하면 자동으로 로그인 페이지가 호 경우가 있다. 가장 일반적으로 사용되던 방법은 보안 처리를 하는 else

출되도록 지정한 것이다(로그인하고 나면 처음에 호출했던 페이 디자인을 마쳤다면 오른쪽에 있는 소스 보기 버튼을 눌러서 소 코드를 각 페이지의 앞에 붙여두고, 사용자에 대해 인증할 때 사 {
lblMsg.Text =“패스워드가 잘못되었습니다.”
;
지로 자동으로 움직인다). 스를 연다. 맨 위쪽 namespace에 다음 항목을 추가한다. 용자 정보를 함께 처리하는 형태였다. 그러나 이 방법은 각 페이
}
지마다 보안 처리에 대한 코드를 삽입하고 관리해야 하는 불편함 }
� </system.web> 태그 다음에 <location> 태그를 따로 지정해 다음의 문장을 using System.Web.Security;
이 존재했다. 따라서 사용자를 분리해 각각의 역할(role)을 지정
추가한다. public bool Login(string strUserID, string strPassword)
하고 그에 따라 다른 권한을 주는 것이 필요하다.
{
<location path=”NeedLogin.aspx”
> 디자인 창으로 돌아와서 아까 만들었던 로그인 버튼을 더블 클 보안 처리를 할 때 역할을 지정하는 것은 별도 프로그램으로 처 // 메일 주소와 패스워드를 비교해 맞다면 True를 반환한다.
<system.web> 릭하면 이전에 없었던 btnChkID_Click 이벤트가 생겨 있을 것이 리할 수도 있지만 닷넷에서는 기본으로 역할에 의한 권한 지정 방 // 이 부분이 실제 프로그램에서는 DB와 연결해 사용자 정보와 비교하는 부분이 된다.
<authorization> if (strUserID ==“dazzani”&& strPassword ==“1234”
)
다. 그 이벤트 항목에 <리스트 3>에 보이는 것과 같이 코드를 입력 법을 제공하고 있다. 물론 윈도우 계정을 사용할 수도 있지만 새
<deny users=”?”/> return true
</authorization> 하고, 아래에 Login() 함수를 하나 더 만든다. Login 함수가 하는 로운 사용자를 추가하거나 사용자에 대한 정보 관리가 쉽지 않다. else
</system.web>
일은 로그인 페이지에서 사용자 ID와 패스워드를 읽어와 데이터 다음은 Web.config의 권한부여 항목에 역할에 따른 권한을 제 return false
</location>
베이스에 있는 사용자 정보와 대조해 만약 사용자가 맞다면 공하고, 프로그램 내에서 데이터베이스 사용자 정보와 함께 역할 }
이벤트는 각 페이지에서 보안에 관련된 요청이 있을 때마다 일 코드의 출처가 어디인지에 따라 다른 권한을 부여할 수 있도록 하 <화면 2> 보안 에러 할 것이다. 혹은 인터넷을 통해 배포된 코드라 할지라도 우리와
어난다. <리스트 4>에 보이는 코드는 이벤트가 일어났을 때 사용 고 있다. 협력 관계에 있는 회사의 것이라면? 이에 대해서도 적절한 권한
자 인증서에 대한 값을 지정하는 것으로 사용자 역할을 지정하는 닷넷에 있어서 각 코드의 출처를 밝히는 것은 아주 중요하다. 을 주는 것이 필요하다. 한마디로 시스템을 관리하는 관리자의 일
과정이 아주 간단하게 처리된다. 지금 실행하려고 하는 코드가 급여 명세표를 작성하기 위해 여러 이 많이 늘었다고 할 수도 있을 것이다. 그러나 한 번 권한을 설정
보안 처리를 할 때 원칙을 지정하는 것으로 현재 사용자에게 매 분의 본사에서 배포한 코드인지, 아니면 여러분의 컴퓨터 자료를 해 두면 설정 과정을 되풀이할 필요 없이 설정 파일만을 배포하는
니저(manager)라는 권한이 따로 부여되고, 웹에서 권한을 사용 복사하기 위한 목적으로 배포된 월급 명세서를 작성하는 코드를 것도 가능하다. 각각의 코드에 대해 권한을 부여하고, 설정 파일
할 수 있게 된다. 가장한 스파이 웨어인지에 따라 실제 여러분이 겪게 될 상황은 아 을 배포하는 과정을 좀더 자세하게 알아보자.
주 무궁무진하다.
황을 바라봐야 한다. 사용자가 인식하지 못하는 순간에도 코드는
이제 모바일 코드와 관련된 보안을 살펴보자. 지금까지 웹의 기능 실행될 수 있으며, 이 코드의 유해성을 검증할 수 있는 메커니즘 닷넷에서는 세 가지 영역에서 이런 문제점을 다루고 있다. 첫 번
을 확장하기 위해 많이 사용된 것은 액티브X 컨트롤이었다. 물론 모바일 코드에 대한 예제를 살펴보자. <화면 2>를 보면 윈도우 프 이 필요한 것이다. 째로 네트워크 상의 보안 처리를 단일 사용자에게 맡기지 않는
현재의 닷넷 환경에서도 예전에 쓰이던 액티브X 컨트롤을 쓰는 로그램이 하나 있다. 이 프로그램은 사용자의 컴퓨터에서 텍스트 은행 홈페이지에서 홈뱅킹을 할 때 액티브X 컨트롤에 대한 여 다. 사용자가 따로 코드에 대한 권한을 인정했다고 하더라도, 코
것이 가능하지만, 윈도우 프로그램을 만들어 웹 폼에서 불러 사용 파일을 읽고, 그 결과를 메시지 박스로 뿌리는 예제다(
‘이달의 디 러 개의 인증 페이지가 나타나는 경우가 자주 있다. 일반 사용자 드를 각각의 범주에 맞춰 권한을 제한할 수 있는 도구를 가지고
하는 것도 가능하다. 스켓’
에 MoCode.exe라는 실행 파일이 있다). 먼저 제대로 실행 는 아무런 생각 없이‘확인’버튼을 누르고, 원래 하고자 했던 계 있다. 그리고 권한 범위를 사용자, 컴퓨터, 엔터프라이즈로 나누
되는 지를 확인하고, 그 실행 파일을 다시 웹 서버의 루트에 위치 좌 이체나 잔액 조회를 수행할 것이다. 하지만 이런 무의식적인 고 있다.
시키고 웹 페이지에 http://localhost/MoCode.exe라고 입력한 습관 속에 문제가 숨어 있다. 사용자가 경고 메시지를 무심하게 관리자는 이름을 통해 코드 그룹을 구별하고, 적절한 범위를 지
닷넷에서 보안을 다루는 관점은 조금 특이하다. 지금까지의 보안 후 실행한다. 그러면 <화면 2>와 같이 보안 관련 에러가 발생하는 바라보면서 확인 버튼을 누름과 동시에 결국 문제는 발생하게 된 정해 각각에 필요한 권한을 부여하는 형태로 코드를 관리한다. 윈
처리에 대한 부분, 특히 사용자 권한에 대한 부분을 다룰 때 그 대 것을 볼 수 있다. 다. 앞서 말했듯 액티브X로 만들어진 코드는 한 번의 인증으로 사 도우 폼 컨트롤은 일정한 이름(공개키, 이름, 버전), 영역(인터넷
상은 현재 로그인한 사용자가 누구인가에 초점이 맞춰졌다. 그러 이 에러는 모바일 코드가 메시지를 띄우기 위해 사용자 컴퓨터 용자 컴퓨터에 대한 모든 접근 권한을 가지게 되므로, 마음만 먹 영역 혹은 인트라넷 영역) 그리고 다른 속성에 의해 구별된다. 그
나 모바일 코드에서의 관점은 조금 다르다. 주체가 되는 것이 현 의 하드 디스크에 들어 있는 파일을 읽으려고 접근을 시도하는 과 는다면 사용자 하드 디스크를 포맷하는 코드를 넣어서 전달하는 래서 일반 사용자의 보안에 관한 철저한 방어가 가능하고, 더 이
재 사용자가 아니라 실행될 코드가 주체가 된다. 즉 현재 실행할 정에서 그 코드가 하드 디스크에 읽기 권한을 가지고 있지 않기 것도 가능하다. 이러한 바탕에서 나온 것이 한동안 맹위를 떨쳤던 상 인정되지 않은 바이러스 코드가 실행되는 것을 막아줘 사용자
때문에 발생했다. 만약 독자가 이전에 액티브X를 가지고 무언가 ILOVEYOU 바이러스이다. 의 시스템을 보호해준다.
<리스트 4> 사용자 역할 지정
를 작성해 본 경험이 있다면, 닷넷에서 보여 주는 이런 보안상의 그래서 닷넷에서는 좀더 강력한 보안 체제를 갖추게 되었다. 웹
protected void Application_AuthenticateRequest(Object sender, EventArgs e) 에러는 처음에는 다소 당황스럽게 보일지도 모르겠다. 을 통해 전달된 모바일 코드의 실제 동작에 따라 권한을 따로 부
{
액티브X 기술을 이용한 코드의 경우는 그 코드가 아무런 보안 여하고, 코드를 실행할 때 그 작업에 따라 권한이 적용되는 방식 닷넷 프레임워크를 설치하고 나면, 제어판 관리도구에 Microsoft
// 보안 처리가 필요한 경우 호출되는 메쏘드
HttpApplication app = (HttpApplication) sender;
관련 서명을 가지고 있지 않다고 하더라도 사용자에 대해 코드를 이다. 예를 들어 간단한 메시지를 보여주는 것이라면 사용자 시스 .NET Framework Wizard와 Microsoft .NET Framework
실행할 것인지를 물어보는 확인창을 보여준다. 만약 사용자가 그 템을 건드릴 필요가 없으므로 별다른 보안 사항이 필요하지는 않 Configure(MS Configure로 표시한다) 두 가지 툴이 생긴다. 이
if(app.Request.IsAuthenticated)
코드를 실행시키기로 결심하고 확인 버튼을 누른다면, 액티브X 지만, 파일 내용을 읽는다는 것은 시스템 파일에 대한 직접적인 툴을 사용하면 실행되는 전체 모바일 코드에 대한 인증 처리가 가
{
FormsIdentity identity = (FormsIdentity) app.User.Identity;
컨트롤은 사용자 권한에 걸맞는 권한을 가지고 코드를 실행하고 읽기 권한이 필요하다는 것을 의미한다. 그리하여 모든 작업의 위 능하다. 이 도구를 사용해 각각의 처리 과정을 살펴보자.
string role = GetUserRole(identity.Name); 사용자 컴퓨터의 자원에 접근하는 것이 가능하다. 한 번의 인증을 험 관계와 신뢰할 수 있는 사이트에서 제공된 프로그램 코드인지 먼저 모바일 코드의 권한 인증 관계를 설정하기 위한 도구인
if (role != null) 통해 쉽게 권한을 부여할 수 있고, 사용자의 입장에서는 권한에 를 검증해 코드 인증에 따라 각각의 권한을 부여하는 방식을 사용 MS Configure를 사용하는 방법에 대해 알아보자. 관리도구 아래
{
대해 따로 관리해야 하는 부분이 없기 때문에 개발자와 사용자 모 한다. 에 있는 Microsoft .NET Framework Configure를 실행시킨다.
app.Context.User
= new GenericPrincipal(identity, new string[] {role}); 두에게 참 편리한 기능이다. 하지만 이 기능을 악용해 바이러스를 이때 필요한 것이 코드에 대한 인증이다. 이 인증을 통해 모바 내 컴퓨터 아래에 어셈블리 캐시 등 여러 가지 아이템이 보일 테지
} 만드는 개발자들이 생기기도 했다. 이미 많은 악명을 떨치고 있는 일 코드가 가지고 있는 기능이 서버의 자원을 건드려도 아무런 이 만, 여기서 설명하려고 하는 것은 실행시 권한 문제를 다루는‘런
}
바이러스들이 이런 기능을 이용해서 만들어진 것이다. 상이 없다는 정보를 제공한다. 그래서 바이러스 메일과 같은 인증 타임 보안 정책’항목이다. 앞에 있는 + 기호를 클릭해 런타임 보
}
받지 않은 프로그램이 사용자의 시스템을 파괴하는 것을 미연에 안 정책의 하부에는 어떤 요소들이 자리잡고 있는지 살펴보자.
// 사용자의 역할을 가져온다. 방지할 수 있다. 좀전에 설명했던 것과 같이 사용자, 컴퓨터(Machine), 엔터프
string GetUserRole (string name)
이러한 코드의 실행 권한 부여는 현재 로그인한 사용자 권한을 중 예전에는 이런 인증 과정이 개인 사용자의 재량에 맡겨졌다면, 라이즈 세 가지 요소가 자리를 잡고 있는 모습을 볼 수 있다. 또한
{
// 입력받은 사용자 이름으로 DB에서 사용자 역할을 가져오는 코드를 작성한다.
요시하는 지금까지의 프로그램 구조와 밀접한 관계를 가지고 있 지금은 관리자가 사용할 모바일 코드에 대한 권한과 인증 처리를 그 아래로 확장하면 세 가지 요소 모두 코드 그룹, 권한 집합, 정
return“Manager” 다. 즉 현재 사용자는 항상 옳다는 전제하에 모든 일이 일어난다. 해야 하는 구조다. 예를 들어 현재 인트라넷을 통해 배포된 모바 책 어셈블리라고 하는 세 분류를 똑같이 가지고 있는 것을 볼 수
}
그러나 웹을 통해 코드가 배포되는 경우는 다른 관점에서 이런 상 일 코드라면? 당연히 모든 시스템에 접근할 수 있는 권한을 줘야 있다. 그 중에서도 컴퓨터 항목에 들어 있는 요소들이 기본적인
<화면 3> 등록 정보 설정 우 Read와 같은 식으로 따로 권한을 설정하는 것이 귀찮기 때문 <화면 4> 설정 배포 파일 만들기

에 따로 여러 가지 기본적인 권한들을 셋트로 묶어 놓은 곳이다.


필요하다면 자신만의 권한 관계를 만들어 코드 그룹에서 지정해
사용하면 된다.

m
현재 권한이 부여되어 자유롭게 사용할 수 있는 어셈블리 집합을
나타내는 부분이다(정책 어셈블리; Policy Assemblies). 따로 어

as
떤 기능을 주는 것이 아니라 전체 영역에 대해 어셈블리의 기능이 들기 항목을 선택해 설정 파일을 만든다.
필요하다고 판단되면, 그 영역의 어셈블리를 지정해 사용자가 자 이렇게 하고 나면 권한 설정에 대한 값을 가지고 있는 msi 확장

권한 관련 설정 값을 가지고 있으므로 여기에 지금 설정되어 있는


기본 값을 변경하면서 어떤 역할을 하는지 알아보자.
유롭게 기능을 사용할 수 있도록 한다.

권한 집합 아래에 보면 여러 가지 권한 집합이 보이는데,‘권한 집


합’탭에서 오른쪽 버튼을 클릭해 새로 만들기를 선택한다. 그러
자를 가진 파일이 만들어지는데, 이것을 사용자에게 배포하고 실
행 파일을 잠시 실행시키는 것으로 모든 설정 과정이 완료된다.
이 파일을 관리자가 공통적으로 사용하는 웹 서버에 올려두고 각
사용자는 링크를 눌러 설치하면 아주 편리하게 전체적으로 동일
한 권한 설정을 갖게 된다.
o
면 권한 집합 이름을 입력하는 창이 나온다. 권한 집합을 구별하
어떤 코드에 대해 권한을 설정할 것인지 범위를 지정하는 부분이 기 위한 이름을 부여하고‘다음’버튼을 눌러 각각의 필요한 권한
다(코드 그룹; code groups). 예를 들어 URL로 항목을 설정하고 들을 택한다. 지금까지 웹의 보안 처리와 모바일 코드 보안 처리를 하는 과정에
www.dazzani.com 사이트를 지정한 다음 그 내부 아래에 있는 권한 종류에 따라 몇 가지 다르게 설정해야 하는데, 파일을 다 대해 살펴봤다. 웹 사이트에 대한 보안 처리는 기존 웹 프로그램
권한 집합 가운에 하나인 Full Trusts를 지정했다고 하자. 그러면 루는 경우라면 읽고 쓰는 것에 대한 권한을 주기 위한 대화 상자 에 비해 중앙에서 XML 파일인 Web.config 파일을 수정하는 것
이것은 사이트에서 배포되는 코드에 대해서는 모든 권한을 인정 가, 실행에 대한 것은 단순하게 어떤 권한을 줄 것인지 지정하는 으로 모든 설정을 마칠 수 있으므로 아주 간편하게 보안 처리를
해 마음대로 컴퓨터 자원에 접근할 수 있다는 뜻이 된다. 대화 상자가 나타난다. 오른쪽에 보이는 여러 가지 권한들 가운데 할 수 있는 것이 특징이다. 모바일 코드에 대한 것은 닷넷 어셈블
여기서 아까 에러를 발생시켰던 모바일 코드를 실행하기 위한 버튼을 이용해 오른쪽으로 옮기고, 그 각각의 권한 관련 사항들을 리에 대한 내용을 지면관계상 좀더 얘기하지 못한 것이 조금 아쉽
보안 설정을 해보자. 코드 그룹의 All_Code 항목 아래에 있는 지정하는 것으로 권한 집합을 지정하는 것은 끝난다. 이제 코드 다. 보안에 대해 관심있는 독자라면 닷넷 어셈블리에 대한 내용을
LocalIntranet_Zone 항목에서 오른쪽 클릭을 해서 새로 만들기 그룹의 대화상자에 가서 자신이 만든 권한 집합을 다시 적용해 코 좀더 공부하는 것으로 모바일 코드의 보안 체계에 대한 지식들을
를 선택하고, 단계적으로 값을 지정한다(필자만의 문제인지는 모 드를 실행해 봄으로써 자신이 부여한 권한이 제대로 적용되고 있 얻을 수 있을 것이다. 이번 달부터 필자가 활동하는 NetSharp 동
르겠지만, 내부의 항목들을 All_Code 항목을 선택해 빈 그룹을 만 는지 확인한다. 호회가 웹 사이트를 www.knug.or.kr로 이전하고 좀더 활발한
들고 수정을 통해 필요한 값을 지정해야 한다). 활동을 준비하고 있다. 기사에 대한 문의사항은 이 사이트에 있는
Kwon_Site라는 이름의 항목을 새로 만들고 속성창을 열어 <화 Q/A 게시판에 올려주길 바라며, 독자 여러분들의 많은 관심을 기
면 3>과 같이 설정 값을 지정한다. 이때 여러 가지 항목을 지정할 모든 권한 사항에 대한 설정은 컴퓨터 각각에 대해 부여되는 것이 대해 본다. 그럼 다음호까지 Nothing But .NET!!!
수 있지만, 코드의 배포 위치를 http://localhost/*로 지정하면 므로 각 사용자마다 따로 지정하는 과정을 거쳐야 한다. 한 대의
localhost에서 배포하는 모든 모바일 코드에 대해 권한을 부여하 컴퓨터에 대해 권한을 설정하는 것은 그다지 문제가 되지 않을 수
게 된다. 다음 탭에 나오는 권한 집합에서 FullTrust를 지정하면, 도 있다. 하지만 문제가 생겨서 운영체제를 새로 설치하거나 여러 sec_code.zip http://www.sbmedia.co.kr/maso

localhost에서 배포되는 모든 코드에 모든 권한을 가지게 된다. 이 대의 컴퓨터에 대해 동일한 권한을 부여해야 하는 경우라면, 이들
제 모바일 프로그램을 실행시키면 아무 이상 없이 실행되는 것을 권한을 일일이 따로 제어하는 것은 아주 성가신 일이다. 따라서
확인할 수 있을 것이다. 이런 권한 설정에 대한 것을 사용자가 알아서 하도록 하는 교육이
필요하다.
닷넷에서는 이렇게 만들어진 권한 사항에 대해 따로 설치 파일
항목을 살펴보면 금방 눈치를 챌 수 있겠지만 각종 권한을 하나의 을 만들어서 배포하는 기능을 가지고 있다. Microsoft .NET
마소 편집부 3430-6710, maso@sbmedia.co.kr, www.sbmedia.co.kr/maso
셋트로 묶어놓은 곳이다(권한 집합; Permission Sets). 예를 들 Framework Configure를 이용해 필요한 권한 설정을 모두 마쳤
서울시 강남구 삼성동 165-2 성도벤처타워 3층 소프트뱅크미디어 마소 편집팀
어 모든 권한을 설정할 경우 Full Trust, 읽기 권한만 설정할 경 다면, <화면 4>와 같이 런타임 보안 정책 항목에서 배포 패키지 만
에 대해 다양한 패키지를 통해 여러 가지 국제 표준을 제공하고 for (int i=0, len=digest.length; ;i++) 다. 반면, 애서메트릭 사이퍼는 공개키 혹은 비대칭키, 공개키 방
{
있다. 이들 패키지를 사용하기 위해서는 보안에 관한 몇 가지 기 System.out.print(digest[i]); 식이라고도 부르는데 암호화와 복호화에 필요한 키가 서로 다른
본 지식을 알고 있어야 한다. if (i<len-1) 키로 운용되는 방식이다. 이 중에서 공개키 방식은 키를 공개키와
{
개인키로 나눈다. 이 둘을 묶어 키 페어(key pair)라고 부르는데
“,“);
System.out.print(
continue; 이들 키는 서로간의 연관성이 있어서 이들을 만들 때 동시에 만들
} else
먼저 해시 함수에 대해 알아보자. 일반적으로 말하는 해시 함수는 게 되며 서로가 반대의 역할을 수행하도록 되어 있다. 즉 공개키
{
단방향 해시 함수(one way hash functions)가 정식 이름인데, 하 break; 로 암호화한 문서는 개인키로 풀 수 있으며, 개인키로 암호화한
나의 문서에 대해 특정한 데이터를 산출해 내는 함수이다. 원 문 } 문서는 역시 공개키로 풀 수 있다.
}
서를 입력으로 받으면 함수 종류에 따라 지정된 길이의 특정 데이 }
그런데 여기에는 문제가 하나 있다. A라는 사람이 개인키를 이
터를 산출하기 때문에 위변조 여부를 손쉽게 파악할 수 있다. } 용해서 암호화된 문서를 만들었다고 해도 A라는 사람에 대한 정
해시 함수는 특정 데이터를 산출하는 특징 외에도 단방향이기 체는 아무도 알 수 없다는 점이다. 그래서 A의 공개키를 얻기가
때문에 해시 데이터로 원 문서를 알아내는 것이 거의 불가능하다 자바는 MessageDigest라는 메시지 다이제스트 클래스를 제공 매우 곤란할 수 있으며, 공개키를 얻는다 해도 다른 사람이 혹시
는 특징이 있다. 원 문서에서 단 하나의 문자만 달라져도 그 결과 하는데, 이 클래스로 MD5와 SHA-1로 해시를 할 수 있다. 다음 A를 사칭하는 것은 아닌지 혹은 A라는 사람을 어디까지 신뢰해
값은 그 이전의 결과 값과 어떠한 유사점도 찾을 수 없다. 게다가 은 해시를 해보는 예이다. 메시지 길이에 관계없이 MD5와 SHA- 야 할지를 알 수가 없게 된다. 그래서 등장한 것이 인증기관(CA :
같은 결과 값을 내놓는 원 문서들 역시 찾기가 거의 불가능하다. 1 알고리즘에 따라 길이가 정해져 있으며 그 결과가 천차만별이 Certificate Authority)과 인증서(certificate)이다.
그래서 해시 함수의 결과 값은 신뢰성을 가진다. 라 각 결과만으로 원 메시지를 유추해낼 수 없음을 알 수 있다
문서에 대해 해시 함수를 수행하는 것을 메시지 다이제스트 (SHA-2가 새로 개발될 예정이기 때문에 SHA-1이라고 쓰는 것
(message digest)라고 부른다. 자바가 지원하는 해시 함수의 종 이 맞지만, 아직까지는 그냥 SHA라고 하는 경우도 많다. 자바에 인증기관은 공개키를 가지는 사람에 대한 일종의 인감증명서를
자바는 네트워크 언어이다. 단순히 네트워크를 잘 쓸 수 있다는 류로는 SHA-1(Secure Hash Algorithm-1)과 MD5(Message 서 SHA는 SHA-1과 동일하게 취급된다). 발행한다. 동사무소에서 인감증명서를 발급신청하면 그 사람의
의미가 아니라 네트워크를 통해 그때그때 실행중에 새로운 실행 Digest number 5) 등이 있는데, 전자는 160비트(20바이트)의 주민등록에 인감을 등록하고 그 인감에 대한 증명서를 발급하게
[c:\myJava\book] java MessageDigestTest MD5 java
코드를 다운받아 쓸 수 있다는 의미다. 이것은 다른 언어가 쉽게 해시값을 내놓으며 후자는 128비트(16바이트)의 해시 값을 내놓 되는데, 이는 그 사람의 신원이 확실하며 그 사람이 계약이나 매
MD5로 다이제스트한 결과 : -109, -9, 37, -96, 116, 35, -2, 28, -120,
가지지 못하는 자바만의 특성으로 이런 높은 성능을 받쳐줄 안정 는다. 다음은 String을 해시하는 예제이다. -97, 68, -117, 51, -46, 31, 70 매 등의 행위를 했음을 확실히 보증하는 수단이 된다.
성을 제공하기 위해 자바는 많은 보안 관련 기능들을 제공하며 가 [c:\myJava\book] java MessageDigestTest MD5 java2 마찬가지로 A라는 사람의 공개키에 대한 인감증명서가 있다면,
import java.security.*; MD5로 다이제스트한 결과 : 21, 127, -51, 120, 8, -93, 66, -78, -20,
장 보안 능력이 높은 언어라는 평가를 받고 있기도 하다. 116, 76, -26, 38, -17, 74, 45 그 사람의 신원이 보증됨은 물론 그 사람이 어떤 행위를 했는지
보안은 안정성과 성능이라는 두 가지 가치를 조율하는 기준점 public class MessageDigestTest [c:\myJava\book] java MessageDigestTest SHA-1 java 그 공개키로 검사해 봄으로써 행위에 대한 증거를 만들 수 있는
{ SHA-1로 다이제스트한 결과 : 35, 82, 75, -23, -37, -95, 75, -62, -15,
이 된다. 보안이 강력하면 안정성은 높아지지만 성능은 떨어지기 수단이 된다(인증기관을 국가가 공인했다면 이는 공인 인증기관
public static void main(String[] args) throws Exception -105, 91, 55, -7, 92, 51, -127, 119, 21, -107, -56
마련이며, 보안을 느슨하게 하면 성능은 좋아지지만 그만큼 안정 { [c:\myJava\book] java MessageDigestTest SHA-1 java2 이 된다). 이때 행위에 대한 증거를 만들기 위해 전자사인이라는
SHA-1로 다이제스트한 결과 : -83, 114, 69, 92, -23, 17, -115, -59,
성은 떨어진다. 또한 보안은 호환성이라는 가치와 대비되는 경향 if (args.length<2) 기술을 활용한다. 전자사인은 개인키와 앞서 설명한 해시 함수를
{ -81, 49, -36, -7,-116, -68, -61, 106, -25, -9, -55, -52
이 있다. 호환이 잘 되려면 보안이 뒤쳐질 수 있으며, 보안이 강조 활용한다.
“사용법 : MessageDigest <알고리즘> <문자열>”
System.out.println( );
되면 호환이 안 될 수도 있기 때문이다. 이처럼 보안에 관련된 여 System.out.println( “\t알고리즘 : SHA, MD5” ); 이렇게 만들어진 전자인증서에는 A의 공개키가 담기게 되고,
System.exit(1);
러 기본 개념들을 알아보면서 자바가 제공하는 보안 관련 기술에 A의 개인키를 이용해서 만들어진 모든 암호화된 문서에 대해 A
}
는 어떤 것들이 있는지 살펴본다. 열쇠라는 것은 제한된 자원에 접근하기 위한 권한을 의미한다. 금 의 신원이 확실해지는 것이다. 그리고 A에게 암호화된 문서를 보
MessageDigest md=MessageDigest.getInstance(args[0]); 고 열쇠가 있으면 금고를 열어서 중요한 물건을 보관하거나 꺼낼 내고자 할 때도 공인인증기관에서 A의 공개키를 제공받아서 사용
byte[] data=args[1].getBytes();
byte[] digest=md.digest(data);
수 있다. 보안에서‘키(key)’
가 의미하는 바도 이와 같다. 어떤 문 하면 A는 자신이 가지고 있는 개인키로 이 문서를 복호화해서 볼
보안은 IT에서 가장 오래됐으면서도 민감한 화두이다. 보통 보안 서를 특정 알고리즘으로 암호화했을 때, 어떠한 키를 이용해 암호 수 있다. 이런 과정은 요즘 많이 활성화된 인터넷 뱅킹의 예를 들
System.out.print(args[0]+ 로 Disest한 결과 : ”
);
이라고 말하면 암호화와 침입 방지 정도를 생각할 수 있는데, 자 화했다면 이를 다시 원문서로 복원시키는 복호화 때도 키가 필요 면 확실하게 구체화된다.
바 역시 이러한 기능을 잘 제공하고 있다. 컴퓨터에서 보안이라는 하게 된다. PKI(Public Key Infrastructure)는 뒤에서 설명할 전자사인된
것은 여러 가지 개념을 내포하고 있기 때문에 매우 광범위한 정의 키를 관리하는 방식에는 크게 시메트릭 사이퍼(symmetric 애플릿을 이해하기 위해 필요한 개념이다. 여기에는 PKI에 대해
가 필요하다. 그러나 기본적으로 보안은 기밀성(confidentiality), ciphers)와 애서메트릭 사이퍼(asymmetric ciphers)가 있다. 시 기본 개념만을 소개했는데 더 구체적인 내용을 알고 싶은 독자는
무결성(integrity), 인증(authentication), 부인 봉쇄(non- 메트릭 사이퍼는 비밀키 혹은 대칭키 방식이라고도 부르는데 암 마소에 실렸던 많은 보안 관련 기사나 서적 혹은 http://simrsa.
repudiation)의 특성을 제공해야만 한다. 자바에서는 이들 특성 호화와 복호화에 필요한 키를 하나의 같은 키로 운용하는 방식이 netian.com을 참조하기 바란다.
이를 설치하면 자동으로 같이 설치되는 자바 플러그인을 사용했 SHA1withDSA 도록 하겠다). 참고로 키툴이 관여하는 것은 키 페어와 인증서 및
SHA1withRSA
자바는 네트워크 언어이다 보니 네트워크에서 실행 코드를 다운 다. 그러므로 여기에서 설명하는 내용을 실행해 보려면 JDK 1.4 MD2withRSA
이들을 관리하는 keystore인데, 키툴은 키 페어를‘키 엔트리
받는 것이 가능하다. 그러나 기본적으로 네트워크에서 다운받은 를 반드시 설치해야만 한다는 점을 미리 밝혀둔다. MD5withRSA (key entry)’
로, 인증서를‘Trusted Certification Entry’
로 부른
실행 코드는 위험한 코드로 간주하게 된다. 그래서 이런 코드들은 앞서 말한 대로 애플릿이 샌드 박스를 벗어나려면 전자사인을 다. 다음과 같이 타이핑하면 키 엔트리를 만들기 위해 키툴이 필
활동에 많은 제약을 받는다. 대표적인 것이 애플릿으로 이는 웹 해줘야 하는데, 전자사인을 하려면 인증서가 필요하다. 인증서는 이중 기본 값은 SHA1withDSA이다. dname은 키를 만들고자 요한 내용을 직접 입력받게 될 것이다. 설명의 편의상 전자사인
브라우저의 자바 가상머신에서 몇몇 허락된 영역 이외에는 접근 앞서 설명한 PKI에서 설명된 대로 공개키에 대한 인감증명서이 하는 사용자에 대한 여러 신상명세를 한 줄로 적어서 처리하게끔 알고리즘은 SHA-1에 RSA를 쓰겠다.
하지 못하게 되는데, 이런 제약을 샌드 박스(sand box) 보안 모델 다. 이것을 자바에서 만들려면 키툴(keytool)이라는 JDK의 도구 해준다(이는 DN이라고도 불리는데, 구별되는 이름이라는 뜻이며
[C:\myJava\book] keytool -genkey -alias testkey -keyalg RSA -
이라고 한다(샌드 박스는 유아를 눕히는 것으로 창살로 사방을 막 를 써야 한다. 키툴은 공개키나 대칭키를 만들고 공개키에 대한 자세한 것은 뒤에서 JNDI를 다룰 때 설명한다). dname 옵션을
sigalg SHA1withRSA
아서 아이가 밖으로 나가지 못하도록 보호한다. 여기에 옛날에는 인증서를 내보내거나 다른 인증서를 가져오기 위한 도구로 키들 생략하면 신상명세에 대한 내용을 키툴이 하나씩 물어오게 된다. keystore 암호를 입력하십시오: teststore
모래가 깔려 있었다고 해서 샌드 박스라고 불린다). 과 인증서들이 저장 파일에 저장된다. 이 저장 파일은 키들과 인 그 형식은 다음과 같다. 이름과 성을 입력하십시오.
[Unknown]: 하동욱
이런 제한은 자바 런타임 환경 1.1에 이르러 인증서 개념을 도 증서들을 저장하는 비밀금고라고 생각하면 된다. 조직 단위 이름을 입력하십시오.
keytool -genkey -dname“CN=Dongwook Ha, ST=Seoul, C=KR”-alias
입함으로써 풀렸다. 인증서를 첨부한 애플릿을 전자사인되었다고 따라서 접근을 위해서는 암호가 필요하다. 이 저장 파일의 이름 [Unknown]: 개발부
testkey 조직 이름을 입력하십시오.
표현하는데, 전자사인된 애플릿은 작성자를 알 수 있고 중간에 위 은 별도의 파일 이름을 정해주지 않았다면 자신의 홈디렉토리에
[Unknown]: 회사
변조되지 않았음을 확인할 수 있기 때문에 사용자의 판단 하에 샌 ‘.keystore’
라는 파일 이름을 가지게 된다(홈디렉토리는 운영체제 구/군/시 이름을 입력하십시오?
◆ validity : 유효일 값이다. 이 키가 얼마동안 유효하게 할 지를 지정해 준다. 생 [Unknown]: 테헤란로
드 박스 밖의 영역에 접근하는 것을 특별히 허용하게 됐다. 이것 별로 다르고 운영체제의 버전별로도 다양한데, user.home라는 시
시/도 이름을 입력하십시오.
이 자바 2에 이르러 분화된(fine-grained) 영역별로 보안 정책을 스템 프로퍼티로 확인할 수 있다. 일반적으로 윈도우 XP의 경우 략하면 기본 값은 1년이다.
[Unknown]: 서울
◆ keypass : 키에 대한 암호로 이를 생략하면 나중에 키툴이 물어본다. 이 조직의 두 자리 국가 코드를 입력하십시오.
달리 줄 수 있게 되는 것으로 발전했다. 는 c:\Documents and Settings\[자기 아이디], 유닉스는
◆ keystore : 키를 저장하는 파일의 이름으로 생략하면 기본 값으로 홈디렉토리 [Unknown]: KR
그리고 JDK 1.4에서는 GSS-API를 지원하는데 이는 프로토콜 /home/[자기 아이디]가 된다). 지금 콘솔을 열어서‘keytool’
이라 CN=하동욱, OU=개발부, O=회사, L=테헤란로, ST=서울, C=KR이(가) 맞습니까?
에 .keysotre 파일이 쓰이며, 파일이 없다면 새로 만든다.
에 추상화된 보안 모델로 이를 통해 미국 MIT에서 개발한 커베로 고 타이핑하면 다양한 옵션들에 대한 설명이 나오는 것을 볼 수 있 [아니오]: 예
◆ storepass : 키를 저장하는 파일에 접근하기 위한 암호를 지정하기 위해 쓰인다.
스(Kerberos)에 접근할 수 있다(GSS-API는 커베로스에 접근하 다. 그 중에서 많이 쓰이고 꼭 필요한 옵션들을 중심으로 설명을 ◆ storetype : 키 페어와 인증서를 저장하는 방식에 대한 것으로 앞서 말한 키와 <testkey>에 대한 키 암호를 입력하십시오
기 위한 표준 API중 하나로 RSA에서 만든 RFC-2743에 프로그 할텐데 그 과정에서 전자사인된 애플릿도 만들어보게 될 것이다. 인증서의 비밀금고에 대한 방식이다. storetype의 기본 값은 jre/lib/security/ (keystore 암호와 같은 경우 RETURN을 누르십시오): testkey
래밍 언어 독립적인 스펙이 기술돼 있으며, 썬 마이크로시스템즈 java.security 파일의 keystore.type 항목에 지정된 값이다. 그 값으로는 JKS
(이하 썬)에서 자바를 위한 스펙으로 RFC-2853을 만들었다. 이 와 JCEKS가 있는데 JCEKS 방식이 좀더 강력하다. JKS 방식이 대칭키만 저
는 JCP에서 JSR-72로 구현됐다. JDK 1.4에서 커베로스를 쓰기 먼저 genkey라는 옵션을 살펴보자. 이 옵션을 사용하면 키를 만 장할 수 있는 반면, JCEKS는 비대칭키까지 저장할 수 있다(JKS는‘Java keystore의 암호와 키의 암호의 경우 테스트 목적이라면 앞의
가 수월하지 않았는데, 이는 조만간 출시될 JDK 1.4.1에서 kinit 들 수 있다. 다음과 같이 콘솔에서 keytool이라 타이핑하면 다음 Key Store’
의 줄임말이며, JCEKS는‘Java Cryptography Extensions 예와 같이 아무렇게나 해도 되지만, 중요한 개발에 쓰이는 것이라
Key Store’
의 줄임말인데, JCE는 과거 JDK에 포함되지 못했던 보안 관련 패
과 klist, ktab이라는 도구를 통해 쉽게 구현될 것이다). 과 같이 genkey에 대한 옵션이 굉장히 많은 것을 볼 수 있다. 기 면 아무도 모르게 잘 조합해서 써야 한다. 모든 입력이 맞으면
키지를 말한다. 물론 JDK 1.4에는 기본 포함돼 있다). JDK의 설치 기본 값은
그리고 표준 확장 라이브러리였던 JCE(Java Cryptography 본적인 옵션을 하나씩 살펴보자.
JKS인데 JKS는 대칭키를 저장할 수 없으므로, 대칭키를 쓰고자 한다면
Extension)과 JSSE(Java Secure Socket Extension),
java.security 파일을 고쳐서 JCEKS를 지정해 주거나 키툴 옵션에서 이를 지
-genkey [-v] [-alias <별명>] [-keyalg <키 알고리즘>]
JAAS(Java Authentication and Authorization Service)를 자 정해야 한다. 이 밖에 PKCS12 방식도 쓸 수 있다. 이는 다른 보안 관련 프로
[-keysize <키 크기>] [-sigalg <서명 알고리즘>]
체 내에 포함시켰다. JCE는 문서 암호화에 쓰이며, JSSE는 PKCS는 Public Key Cryptography Standards의 줄임말로 RSA
[-dname <대상 이름>] [-validity <유효일>] 그램과 최소한의 호환성을 유지할 수 있도록 제한적인 지원만 가능한데, 다른
[-keypass <키 암호>] [-keystore <keystore>] 라는 표준을 만든 RSA 시큐리티라는 회사가 주축이 되어 만든 표준
SSL/TLS를 구현하는 데 쓰이고, JAAS는 싱글 사인온을 구현하 프로그램이 만든 PKCS12로 된 keystore 파일을 읽는 것만 가능하며,
[-storepass <암호 입력>] [-storetype <입력 유형>] 이다. 여기에는 썬, 마이크로소프트(이하 MS), 애플 등의 회사가 함
는 데 쓰일 수 있다(GSS-API는 하나의 토큰을 전송하고 수신하 [-provider <공급자 클래스 이름>] ...
keystore 파일을 만들어서 키를 만들어 넣거나 내용을 수정하는 것은 지원되
께 참여했다. PKCS는 공개키를 운용하기 위한 몇 개의 세부 표준들
는 것에 관한 것이기 때문에 기본적으로 TCP를 쓰든 UDP를 쓰 지 않는다(PKCS12는 Java Secure Socket Extension 패키지를 통해 제공
로 이뤄져 있는데, 앞서 언급한 PKCS12는 PKCS#12로도 표기되
든 혹은 하부에 독자적인 프로토콜을 쓰든 아무 상관이 없다. 하 된다).
며, 이는 PKCS의 여러 세부 표준 중에서 12번째 표준이라는 뜻이
◆ provider : 자바의 Java Cryptography Architecture를 나름대로 구현해서
지만 JSSE는 HTTP를 안전하게 송수신하기 위한 것으로 SSL과 ◆ alias : 키에 대한 이름이다. 생략되면 기본값인 mykey가 쓰여진다.
다. PKCS#12는 개인키나 인증서 등을 어떻게 다른 개인이나 프로
제공되는 것이 있다면 원래의 자바의 것을 대신해서 사용하는 옵션으로 보통은
TLS에 국한된다). 또한 인증서의 경로를 탐색할 수 있는 ◆ keyalg : 키에 대한 알고리즘으로 RSA와 DSA가 쓰일 수 있는데, 생략하면
세스와 교환할 것인지에 대한 내용을 담고 있다. PKCS의 다른 세부
필요하지 않다.
DSA가 쓰인다.
Certification Path API도 있어서 인증서에 대한 또 다른 인증서 표준에 대해서 알고자 한다면 www.rsasecurity.com/solutions
◆ keysize : 키의 크기로 RSA는 512이상 8의 배수이고 DSA는 512에서 1024
의 경로를 처리하는 것도 가능하다. /developers/whitepapers/IntroToPKCSstandards.pdf의 PDF
사이의 64의 배수이다.
문서를 참조하기 바란다. 현재 JCP에서 PKCS 중 1, 5, 7, 8, 9,
◆ sigalg : 서명 알고리즘으로 RSA 혹은 DSA가 MD5나 SHA-1 등과 같이 쓰
10, 12 에 대한 내용을 자바로 접근할 수 있도록 하는 JSR-74가 진
인다. 그래서 sigalg에 대한 옵션으로는 다음과 같은 것들이 쓰일 수 있다
이제 독자 여러분이 직접 자신만의 키 페어를 만들어 보도록 하자
행중이다.
애플릿에 전자사인하는 예를 들기 위해 여기에서는 JDK 1.4와 (DSA는 SHA-1만 쓸 수 있다). (여기서는 편의상 JKS 방식의 keystore에 공개키 방식만을 다루
‘예’혹은‘y’
를 입력하고 방금 만든 키 엔트리에 대한 암호를 설 [-storetype <type>] - keystore의 형식을 지정한다. jre/lib/ 추가된 manifest 서 파일 내용을 공개키로 풀어보면 MANIFEST.MF의 내용과
security/java.security 파일의 keystore.type 값에 적힌 값이 기본 값 추가 중: FileWriteApplet.class(내부 = 777) (외부= 512)(34%가 감소
정하고서 잠시 복잡한 연산을 수행한 다음 만들어진 키 엔트리를 이다. 됐습니다.)
동일한 내용이 나온다. 동일한 내용이 나온다는 것은 데이터를 만
홈디렉토리의 keystore 파일에 저장한다. 이렇게 만들어진 키 엔 [-keypass <password>] - 개인키에 대한 암호를 지정한다. storepass와 든 사람에 대한 신원이 확실해짐과 동시에 데이터가 중간에 변형
같으면 지정하지 않아도 된다.
트리를 확인하기 위해 다음과 같이 타이핑해보자. 되지 않았다는 증거도 된다. 만약 두 파일 중 어느 하나가 변형된
[-sigfile <file>] - 사인 파일의 기본 이름을 지정한다. mysign이라고 지
정했을 경우, mysign.sf 파일과 mysign.rsa(DSA를 썼다면 mysign.dsa) 다음과 같이 write.html이라는 이름의 HTML 파일도 만들자. 다면 그 즉시 변형 여부를 알아차릴 수 있다.
[c:\myJava\book] keytool -list 파일이 jar 파일 안에 만들어진다.
자바 플러그인은 자신이 다운받은 애플릿을 로컬 하드 디스크
keystore 암호를 입력하십시오: teststore [-signedjar <file>] - 사인된 jar 파일의 이름을 지정해 준다. 지정하지
<applet code=”
FileWriteApplet” archive=”
write.jar” width=200
않으면 원본 jar 파일을 덮어쓰게 된다. 에 저장하는데 사용자가 전자사인된 애플릿을 실행할 때 전자사
height=100>
Keystore 유형: jks [-verify] - 사인된 jar 파일을 점검한다. 인에 쓰인 인증서를 영구적으로 승인한다는 의사를 표시하는 경
</applet>
Keystore 공급자: SUN [-verbose] - 출력 내용을 본다.
[-certs] - verbose나 verifying 때 인증서를 출력해 본다.
우는 그 인증서를 로컬 하드 디스크에 저장하고서 그 인증서로 풀
Keystore에는 1 항목이 포함되어 있습니다. 수 있는 전자사인된 애플릿인 경우는 별도의 인증절차 없이 곧바
이제 애플릿과 HTML 파일도 만들어졌으니 앞서 만든 test 로 실행시키게 된다.
testkey, 2002-05-23, keyEntry,
인증서 지문(MD5): FA:2B:71:CB:68:CF:34:E1:C2:EF:C8:52:B9:EE:34:ED key 키를 가지고 전자사인을 해보는 일만 남았다. 다음과 같이 실
자, 이제 실제 애플릿을 만들어볼 차례인데 다음 예제 애플릿을 행하면 jar 파일에 전자사인을 하게 된다(keystore의 암호가
보도록 하자. 이 애플릿은 사용자 컴퓨터의 홈디렉토리에 test.txt teststore이고 keypass는 testkey이므로 이들도 옵션으로 넣어주 J2ME는 CLDC(Connected Limited Device Configuration)와
JKS 방식의 keystore가 새로 만들어졌으며, 이 keystore에 파일을 만든다. 원래 전자사인되지 않은 애플릿은 로컬 디스크에 거나, 프롬프트가 뜰 때 타이핑하는 것을 잊지 말자). CDC(Connected Device Configuration)라는 환경으로 나뉜다.
testkey라는 이름의 키 엔트리가 생겼음을 확인할 수 있다. 이제 파일을 만들 수 없으므로 이 애플릿을 실행한다면 에러가 발생할 CDC에서 쓰이는 CVM은 J2SE의 JVM에 기반하고 있기 때문에
[c:\myJava\book] jarsigner write.jar testkey
이 키를 이용해서 애플릿 프로그램을 사인해 보겠다. 애플릿 프로 것이다. 자바 2의 보안 기능을 거의 다 쓸 수 있다(JDK 1.4에 추가된 보
그램을 인터넷에서 다운로드해 웹 브라우저에서 실행하려면 그 코 안 기능은 지원 범위에 해당되지 않는다). 반면 CLDC는 CDC에
import java.io.*;
드에 대한 신뢰가 절대적이다. 무슨 코드인지 어떻게 알고 아무 애 testkey라는 키를 이용해 전자사인을 했다면 write.jar 파일에 비해 워낙 제한된 디바이스 환경이라 초창기에는 CLDC 구현에
import java.awt.*;
플릿이나 실행시키겠는가. 혹시라도 하드 디스크를 포맷하거나 중 import java.applet.*; 무언가 변화가 있을 것이다. 다음 명령을 실행해서 write.jar 파일 필요한 보안말고는 거의 고려되지 않았다. 하지만 일부 성능이 괜
요한 파일을 네트워크를 통해 몰래 빼내갈 수도 있을 것이다. 그것 을 살펴보자.
public class FileWriteApplet extends Applet
을 방지하기 위해 인증서를 가진 개발자가 애플릿에 인증서를 포 {
[c:\myJava\book] jar xf write.jar
함한 다음 개인키로 사인하고 이를 배포하면 프로그램 사용자는 public void init()
{
인증서를 통해서 개발자(혹은 개발회사)에 대한 신원을 확인하고
“user.home”
String home=System.getProperty( ); 인터넷 뱅킹을 신청하면 신청자 명의로 개인키와 공인 인증서에 담
믿을지 말지를 결정하게 된다. 만약 제시된 인증서가 공인 CA로 File file=new File(home,“test.txt”); 압축을 풀면 META-INF라는 디렉토리가 보인다(
‘meta
긴 공개키를 받게 된다. 이들 키 페어를 담는 keystore가 어떤 형식
부터 받은 것이라면 더 확실하게 믿을 수 있을 것이다. information’
이라는 뜻이다). 이 디렉토리에 보면 다음의 세 파일
try 으로 되어 있느냐는 인터넷 뱅킹 클라이언트 모듈을 만든 업체의 자
애플릿에 사인하기 위한 도구로 jarsigner 도구가 사용된다. { 이 보일 것이다. 유이지만, 표준 규격인 PKCS#12 형식으로 저장할 수 있는 경우라
jarsigner는 keystore로부터 인증서를 가져와 애플릿이 담겨 있는 file.createNewFile();
면 자바에서 이를 이용해서 애플릿을 전자사인하는 데 쓸 수 있다.
} catch(IOException ioe) MANIFEST.MF
Jar 파일에 담고 이를 또 다시 개인키를 이용해 전자사인하게 된 {
물론 이 경우는 인터넷 뱅킹용 공인 인증서의 원래 용도와는 다른
TESTKEY.RSA
다. 다음은 jarsigner의 사용법이다. ioe.printStackTrace(); TESTKEY.SF 것이고, 루트 CA에 대한 인증서가 자바 실행환경에 설치돼야 한다는
} 점 때문에 큰 의미는 없을 수 있다. 하지만 그렇게만 된다면 시중 은
}
jarsigner [options] jar-file alias 행이 공인하는 사용자가 되므로 공인 인증서의 역할만은 확실하다고
jarsigner -verify [options] jar-file 말할 수 있겠다. 게다가 아직까지는 인터넷 뱅킹용 공인 인증서에 대
public void paint(Graphics g) MANIFEST.MF 파일은 jar 파일 안에 포함된 각 파일에 대해
{ 한 발급 수수료가 없기 때문에 부담없이 이용하기에는 더없이 좋다.
“test.txt 파일을 썼습니다.”
g.drawString( , 30, 40); SHA-1 해시 함수를 실행한 메시지 다이제스트 값을 가지고 있
자세한 내용은 생략하겠으나 키툴의 import 옵션을 이용해서 키
jar 파일 이름을 적고 keystore의 alias 이름을 적어주면 해당하 } 다. 이 값은 각 파일의 고유한 해시 값으로 파일이 중간에 변형되
페어를 읽어들일 줄 알고, PKCK#12 형식의 keystore라는 점만 염
}
는 키 엔트리의 인증서를 포함시켜 주고 애플릿 전체를 개인키로 지 않았는지를 판단하는 근거가 된다(앞서 인터넷 뱅킹을 얘기할 두에 둔다면 큰 문제는 없을 것이다. 필자가 테스트한 것은 국민은행
사인해 준다. 다음은 jarsigner의 주요 옵션이다. 때 계좌간 이체나 이체액 등에 관한 내용에 대해 메시지 다이제스 에서 발급받은 YesSign 공인 인증서 및 키 페어와 한미은행에서 발
이를 컴파일해서 jar 파일로 만들자. 트한다는 내용과 동일한 것이다). 하지만 이 파일 역시 변형될 수 급받은 사설 인증서 및 키 페어였다. 국민은행용 키 관리 프로그램에
[-keystore <url>] - keystore의 위치를 지정한다. 생략하면, 홈페이지의 서는 PKCS12 파일을 얻을 수 없기 때문에, 이를 받기 위해서 한미
있으므로 MANIFEST.MF 파일에 대해 전자사인을 해야 한다.
.keystore 파일이 사용된다.
[c:\myJava\book] javac FileWriteApplet.java 은행에서 인증서 관리 메뉴를 선택한 다음 한미은행 사설 인증서와
[-storepass <password>] - keystore에 접근하기 위한 암호를 지정한다. TESTKEY.SF 파일은 전자사인 파일로서 이 파일에는
생략하면 물어본다. 국민은행에서 받은 YesSign 공인 인증서를 저장시켜서 테스트했다.
[c:\myJava\book] jar cvf write.jar FileWriteApplet.class MANIFEST.MF 파일 내용에 대한 전자사인이 담겨 있다. 그래
찮은 핸드폰이나 PDA를 중심으로 모바일 커머스 서비스를 위한 J2ME도 PKI를 본격적으로 도입하고 있다(사실 MIDP 2.0의 최 밖에 텍스트 암호화용 라이브러리로는 Bouncy Castle(www. JSR-104와 JSR-106은 IBM이 단독으로 상정한 것들이다). 이
WPKI(Wireless Public Key Infrast ructure)를 구현하는 경우가 늘 대 관심사 중 하나는 모바일 커머스이다. 이전에 kssl이라는 라이 bouncycastle.org)의 J2ME용 Cryptography API를 쓰면 된다. 들 JSR도 XML Signature(RFC-3275)에 기반하고 있다.
고 있다. 우리나라에도 제한적인 PKI 서비스가 WAP 브라우저에 브러리를 통해 PKI를 제공 중이었으나 이는 비공식 라이브러리 이런 것들과는 별도로 J2ME에 체계적인 보안 관련 패키지들 OASIS의 표준인 SAML(Security Assertion Markup
탑재돼 쓰였으며, LG텔레콤은 케이사인, 한국정보인증과 함께 벨 였다). 먼저 J2ME에서 MIDP 2.0에 javax.microedition.pki 패 을 구현하는 것을 목표로 하는 JSR이 JCP에서 추진되고 있는데 Language)을 지원하기 위한 JSR-155도 진행 중이다. SAML은
록스소프트에서 개발한 자바를 OS로 하는 핸드폰에 공인 인증 PKI 키지가 추가됐다. 이 패키지는 단말기가 탑재하고 있는 PKI 솔루 지난 4월에 JCP에 상정된 JSR-177(Security and Trust 썬, IBM, HP, Oblix, Netegrity, Entergrity, OpenNetwork
서비스를 올리기도 했다. 그리고 SK텔레콤은 시큐어소프트와, 션에 대한 정보와 이를 쓸 수 있는 수단을 제공하기 때문에 단말 Services API for J2ME)이 그것이다. javax.microedition.se.*와 Technologies 등이 함께 진행한 것으로 주로 썬이 주도한 스펙이
KTF는 드림시큐리티과 함께 공인인증 PKI 솔루션을 탑재시켰다. 기에 PKI가 구현돼 있다면 이를 가져다가 MIDP에서 인증 관련 javax.microedition.crypto라는 패키지명을 가질 것으로 보이는 다. WS-I의 WS-Security와 함께 유력한 웹 서비스의 XML 보안
서비스 등을 구현할 수 있다(MIDP 2.0은 현재 JCP에서 퍼블릭 JSR-177은 J2ME에서 javax.microedition.pki와 함께 보안과 관련 기술이다.
리뷰를 거치고 있는 상태이고, 이 스펙을 인터넷을 통해 본 사람 암호화에 관련된 기능들을 체계적으로 구현하게 될 것이다. 출시
이렇게 모바일 디바이스에 PKI가 탑재되고 있는 추세에 따라 들의 의견을 종합 반영해 조만간 최종 스펙이 나올 예정이다). 그 시기는 2003년 중반 이후로 예정돼 있다.
그리고 정확히 J2ME에 포함되지는 않지만 자바 카드도 소형 보안만큼 뜨거운 감자도 없을 것이다. 그 시장은 참으로 무궁무진
기기의 보안에 많이 쓰이고 있다. 썬은 400만 개의 아메리칸 익스 하지만, 실패하면 그 뒷감당도 무궁무진한 비용을 요구하기 때문
프레스 블루 카드와 700만 개의 비자 인터내셔널 스마트카드를 이다. 웹 서비스에서도 보안이 뜨거운 감자이기는 마찬가지다. 보
WS-I(www.ws-i.org)는 IBM과 MS가 주도해서 만든 웹 서비스 상호협 있는 중이었는데, 다행히 얼마 전에 OASIS의 WS-Security 상정을 지지
포함해 1억 개 이상의 자바 카드 장비 사이의 보안 애플리케이션 안이 없는 웹 서비스는 의미가 없다. 하지만 자바는 보안에 있어
조 기구이며, 현재 가장 유력한 웹 서비스 관련 단체이다. 이 단체는 의제를 하고 지원하기로 결정했다(SAML은 OASIS의 표준이며, 썬은 OASIS의
과 인터페이스가 완벽하게 호환된다고 말하고 있다. 이는 스마트 서 만큼은 다른 어떤 언어보다 더 효과적인 적응을 해왔으며 이는
상정하고 표준을 제정할 수 있는 창립 멤버와 의제를 제안만 할 수 있는 기 회원사로서 이것을 지원하고 있었다. 하지만 WS-I에서 WS-Security를
카드 같은 장비에 자바가 많이 쓰이고 있고, 점점 디지털화돼 가 앞으로도 변함이 없을 것으로 확신한다. 그것은 자바가 개방적이
여 멤버의 두 가지 자격 기준을 가지고 있는데, 썬은 현재 창립 멤버로의 참 OASIS에 상정했을 때 OASIS 내에서 이를 지원하기로 다른 회원사들과
여를 희망하고 있는 상태이다. 얼마 전 IBM이 썬의 창립 멤버로의 참여 방 함께 찬성한 것이다). 이렇게 해서 SAML과 WS-Security는 서로의 장단 는 사회구조에 자바도 그 영역을 확대하고 있다는 것을 보여준다. 고 협력적인 면을 많이 갖추고 있기 때문이다.
안을 제안했었지만, MS의 반대로 뜻을 이루지 못한 일이 있었다. 점을 취해서 새로운 스펙으로 재탄생할 수 있는 기회를 얻게 됐다. 현재 많은 보안 분야에서 자바가 쓰이고 있으며, 그 경향은 보
초창기에 썬은 기여 회원으로의 참여 권유를 받기는 했지만 이는 썬의 그런데 썬이 WS-Security를 지원하게 된 것에 대해 필자는 WS-I의 창 다 더 생산성을 높이는 쪽으로 맞춰져 있다. 효과적이고 효율적으
위상으로 볼 때 웹 서비스에 대한 영향력을 영원히 박탈당할 수도 있는 일 립 멤버 가입을 위해 IBM의 노력에 힘을 실어주기 위한 제스처로 보고 있 J2EE에서의 보안 기술은 J2SE의 보안 기술을 그대로 승계한다. 로 보안 서비스를 제공하기 위해서는 기반 기술에 대한 기본적인
이기 때문에 썬이 거부했다(창립 멤버로의 합류를 위해서는 기존 창립 멤버 다. 이런 모습들은 MS에게 썬의 창립 멤버 가입을 허락하도록 압력을 행사 이는 J2EE의 기본적인 인프라를 J2SE가 제공하는 관계를 가졌 이해가 필수적이다. 대충대충 짜맞추는 프로그래밍만 해 본 독자
들이 만장일치로 찬성해야 한다. MS는 썬이 기여 멤버로 먼저 참여를 해야 하는 역할을 하게 될 것이다(실제 썬의 WS-Security 지원에 대해 MS는
기 때문이다. 여기에 추가해서 최근 웹 서비스 열풍을 타고 웹 서 라면 보안에 대해 자신만의 노하우를 쌓아보는 것도 좋으리라 생
한다고 주장하고 있지만 창립 멤버로의 참여를 바라지 않기 때문이라는 것 언론에 환영의 뜻을 밝혔다). m
비스 관련 보안 기술이 등장하고 있다. 이는 웹 서비스가 XML을 각된다. as
o
은 법원에 제출된 MS 내무 문건을 통해서 확인된 상태이다). 하지만 다른
통신 언어로 삼기 때문이다. 결국 XML은 일반 텍스트로 이뤄져
WS-I의 창립 멤버들은 썬의 창립 멤버 합류에 대해 대부분 긍정적인 시각
을 가지고 있기 때문에 결국에는 창립 멤버로의 뜻을 이룰 것으로 본다. 이 사실 웹 서비스 보안에 대해 두 가지 다른 스펙이 존재하게 된다면 이것은
있으며 매우 읽기 쉬운 포맷이라는 점과 XML 레벨에서 웹 서비
런 모습들을 어떻게 해석해야 할까? 웹 서비스의 시장 형성에 매우 큰 악영향을 끼치게 된다는 점에서 썬의 스의 모토인 통합을 이뤄내야 하기 때문에 XML의 암호화와 이를
WS-Security 지원은 바람직한 일이라고 볼 수 있다(이것은 기업 시장의 이용한 보안 정책은 웹 서비스에서 가장 중요한 선결 과제이다.
가장 보편적인 플랫폼인 자바의 웹 서비스 보안 표준과 타 플랫폼의 웹 서 XML의 암호화와 관련된 기술 스펙은 지금도 속속 등장하고 있는
WS-I에 썬이 참여하는 것은 많은 의미를 갖고 있다. IBM은 썬을 제치고 비스 보안 표준이 같게 된다는 것을 의미한다). 이제 OASIS 내에 같이 자 데 이중에는 OASIS와 W3C에 상정된 표준을 포함해서 많은
자바 시장에서의 최대 이익을 실현해 왔지만 자바와 관련된 실권을 다루는 리를 잡게 된 SAML과 WS-Security의 상호협력을 눈여겨 볼 때라고 할 � XML-Based Security Services TC : http://www.oasis-open.org/com
JSR들이 JCP에서 작업이 진행중이다. mittees/security
것에서 썬에게 많은 부분을 양보해야만 했었다. 이런 와중에 웹 서비스를 수 있겠다.
먼저 SOAP 레벨에서 암호화에 관한 JSR-183(Web Services � WSCI : http://www.ebpml.org/wsci.htm
통해 썬을 앞서나갈 수 있는 기회를 얻게 된 것이다. 하지만 WS-I의 설립 그리고 한 가지 더 첨언하자면 WS-I의 배후에서 이뤄지고 있는 치열한 � GSS-API : http://www.ietf.org/rfc/rfc2743.txt
Message Security APIs)이 있다. 이것은 IBM이 지난 4월 JCP
이후 이제 IBM으로서는 MS를 견제해야 할 필요성을 느끼게 됐을 것이다. 경쟁도 놓치기에는 아까운 장면들이다. WS-I에서 모든 업체들이 상호 협 � GSS-API Java Bindings : http://www.ietf.org/rfc/rfc2853.txt
에 상정한 것으로 W3C에 상정된 SOAP-SEC, XML-Encrypt∙ � XML-Signature Syntax and Processing : http://www.ietf.org/rfc/rfc3275.txt
웹 서비스에 관련된 규약의 상당 부분을 함께 작업해 온 IBM과 MS이지만 력하는 것처럼 비치기도 하지만, 실상은 웹 서비스에 대한 시장을 키우는
W3C∙IETF가 공동 작업한 XML Signature(RFC-3275)와 같 � JAAS Class Libraries and Methods : http://access1.sun.com/code
자바로 인해 발생되는 이익의 가장 많은 부분을 취하고 있는 IBM으로서는 것이 우선적인 목표임과 동시에 그 시장에서 자사의 최대 이익을 실현하기 samples/J2SE-JAASexample-part1.html
웹 서비스 시장에서의 자바 입지를 견고히 하기 위해서 썬의 협력이 절대적 위한 장이라고 봐도 된다. 실례로 IBM의 WSFL과 MS의 Xlang, 거기에 은 스펙들을 기반으로 하고 있다. 이것은 올해 말이나 내년 초에 � http://www.zdnet.co.kr/foreignnews/article.jsp?id=50155
으로 필요하다(IBM은“썬의 자바 소프트웨어가 웹 서비스의 기본”
이라고 추가해서 썬의 WSCI는 아직까지 통합되지 못한 웹 서비스 관련 스펙들이 가시적인 성과를 내는 것으로 계획되고 있다. � http://www.zdnet.co.kr/foreignnews/article.jsp?id=49931
� http://www.zdnet.co.kr/biztech/hwsw/biztrend/article.jsp?id=48993
공공연히 주장하고 있다). 그런 면에서 웹 서비스의 보안에 관한 WS-I의 다. 어쨌든 썬과 MS 그리고 이 두 회사 사이에서 실익을 챙기고 있는 IBM 그리고 JSR-104(XML Trust Service APIs), JSR-105(XML
� http://zdnet.com.com/2100-1104-912968.html
WS-Security에 썬이 협력하는 것은 웹 서비스의 마케팅적 성공을 위해서 까지, 이들의 행보는 큰 관심을 갖고 지켜볼만 한 가치가 있다. 웹 서비스는 Digital Signature APIs), JSR-106(XML Digital Encryption � http://www.zdnet.co.kr/biztech/hwsw/biztrend/article.jsp?id=48744
라도 필수적인 요소이다. 분열이 아닌 통합을 전제로 하는 만큼 이들 업체가 이런 전제에 충실하게 � http://www.zdnet.co.kr/biztech/hwsw/biztrend/article.jsp?id=49631
APIs)으로 진행되고 있는 XML의 암호화에 관한 JSR들은 직접
썬은 WS-Security와는 별도로 웹 서비스에서의 보안에 관련된 스펙인 일하는지 아닌지를 지켜봐야 하기 때문이다. � http://www.zdnet.co.kr/ecommerce/biztrend/article.jsp?id=47755
XML 레벨에서의 암호화와 전자사인 등에 관한 내용들을 다루고 � http://techupdate.zdnet.com/techupdate/stories/main/0,14179,
SAML(Security Assertion Markup Language, JSR-155)을 추진하고
있다(이것 역시 JSR-105만 IBM과 썬이 함께 상정했을 뿐, 2872547,00.html

You might also like