블로그 이미지
자유로운설탕

calendar

1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30 31

Notice

2018. 7. 15. 20:18 보안

  이 시간에는 보안에서는 거의 필수라고 할수 있는 몇 가지 타입의 암호화와 복호화에 대한 얘기를 해보려고 한다. 다만 RSA 나 AES 와 같은 암호화 방식에 대한 수학적 전개에 대한 얘기를 하려는 것은 아니고(해당 부분은 많은 책이나 인터넷에서 자세히 설명하고 있다. 쉽게 이해가 잘 안되서 문제긴 하지만...^^), 보안 및 IT 쪽에서 암복호화가 어떤 의미로 쓰이고 있는지와 이해가 필요한 미묘한 점에 대해서 아는 범위 내에서 얘기해 보려 한다.

 

 

[목차]

1. 보안을 바라보는 방법

2. 보안에서의 코드 읽기

3. 인젝션(Injection) 살펴보기

4. 암복호화

5. 클라이언트 코드

6. 업로드, 다운로드

7. 스크립트 문제

8. API

9. 설정, 패치, 하드닝

10. 설계 문제

11. 스캐너 vs 수동 테스트

12. 자동화 잡

13. 리버싱과 포렌식

14. 모니터링 문제

15. 악성코드

16. 보안과 데이터

 

 

1. 들어가면서

  사실 암호화 라는 것은 현실과 비교하자면 우리가 주민등록증을 가지고 다닐 때, 남들이 다 볼 수 있도록 손바닥위에 놓고 다니지 않고, 지갑에 넣은후 주머니에 넣거나 가방에 넣어 가지고 다니는 것과 비슷하다고 볼 수 있다. 보통의 사람들 한테는(뭐 초능력자나 어벤저스가 있다면 모르겠지만) 그것을 투시할 수 있는 능력이 없기 때문에  남에게 보이지 않고 안전하게 다닐 수 있게 된다. 

 

  과거의 암호들은 셜록홈즈 소설에서 나오는 그림 암호 같은 형태로 숨겨진 특정 규칙에 의해서 문자를 뒤섞거나 매칭되어 있기 때무네, 그 숨겨진 규칙이 암호화 방식 차체가 되는 방식이였지만, 현대에서는 수학적 도메인을 이용하여 관련 계산식은 모두 공개하고, 몇 몇 변수 값을 감추어 어렵게 풀어야 하는 수학적 문제로 바뀌게 되었다. 그렇게 된 이유 중의 하나는 아마도 우리가 컴퓨터에 저장한 데이터 들이 결국은 2진수의 형태로 저장되어 있기 때문일 것 같다. 해당 저장된 수를 적당히 잘라서(블록화) 뒤섞거나 암호키인 숫자와 연산하여 의미가 없어 보이는 다른 숫자의 형태로 만들 수 있게 되었기 때문이라고 생각한다(인간이 인지할 수 있는 텍스트나 실행이 되는 exe 파일들도 디스크 상의 저장된 형태를 기반으로는 무척 큰 2진수나 블록으로 잘라진 작은 2진수 묶음 들에 불과하다). 결국 그러한 숫자를 뒤섞는 수학적 로직들이 AES, DES, RSA, ECC, SHA(해시) 등의 이름으로 암호화 알고리즘 이라고 불리우게 된다(머신러닝에서 통계적 기법들이 각각 하나의 머신러닝 알고리즘을 차지하는 거랑 비슷한 듯도 싶다). 

 

 

[셜록홈즈 춤추는 인형 - Sherlock님 블로그]

https://m.blog.naver.com/thdgnstjs/50077677206

 

 

  뭐 개인적으로 나눠본다면 암호를 1세대, 2세대, 3세대, 특수 형태, 제3자 인증 형태의 5가지로 나눠보고 싶다.

 

   1세대는 위의 셜록홈즈의 그림 암호같이 다른 매칭되는 매체들(예를 들어 이미지)과 연관되서나, 문자나 비트 등을 특정한 규칙에 의해 교환하거나 뒤 섞어 만드는 방식을 얘기한다. 예를 들면 프로그래밍에서 많이 쓰이는 Base64 인코딩이나, HTML 인코딩, URL 인코딩 등이 그러한 타입이라고 볼수 있다.

 

  2세대는 엑셀이나 zip 파일에 암호를 걸때 "1234" 를 입력해 암호를 걸었다면, 해당 문서나 zip 파일을 열때 같은 암호인 "1234" 를 넣어야 되는 것과 마찬가지인 타입이다. DES 나 AES 같은 대칭키 암호화 알고리즘이 이런한 타입이라고 볼수 있다.

 

  3세대는 우리가 계약서에 날인 할때 인감 도장을 두 개의 나눠가질 계약서 사이에 찍는 간인(間印)과 비슷하다고 봐도 될듯 하다. 한 쪽 계약서에 찍힌 반쪽의 도장은 다른 한쪽의 계약서에 찍힌 도장과 매칭이 되어, 두 개의 계약서가 서로 유효하다는 것을 증명하게 된다. 보통 양쪽 당사자의 도장을 다 찍기 때문에 상호 증명이 된다. 이러한 쌍이되는 키를 수학적으로 구현한 것이 RSA 나 ECC 라고 불리우는 공개키, 개인키를 가지는 비대칭키 암호화 알고리즘이다. 아래와 같은 증표의 나눠 가지는 것도 비슷하다고 봐도 될 것 같다.

 

[메데이아와 테세우스, 배신하는 딸들의 운명 - 윤단우. 그녀의 시선 블로그]

http://blog.yes24.com/blog/blogMain.aspx?blogid=iconblue&artSeqNo=6998225

 

  특수 형태는 개인적으로 프로그래밍을 공부하다 처음 접했을때 이해하기 힘들었던 해시 함수 이다. 해시 함수는 비유 하자면 사람이 지닌 지문이나 홍채와 비슷하다. 지문 또는 홍채가 해당 개인 자체는 아니지만, 개인만의 고유한 특징을 소유하여 한 개인의 신원을 증명을 할 수 있는 것 처럼 컴퓨터에 저장된 특정한 문장, 파일, 숫자에 대해서(앞에서도 얘기했지만 내부적으로는 결국 숫자로 이루어져 있기 때문에) 수학적 연산을 통해서 일정한 길이를 가진 고유의 숫자로 함축해서 표현하게 된다. 최종적으로 만들어진 것은 우리가 발급받은 주민번호와 같아서 정말 아주 특별한 경우가 아니라면 현실적으로는 겹치지 않는다(해당 부분은 홍채나 지문도 마찬가지이다). 실제 우리가 입력한 홍채, 지문, 패스워드 등의 정보는 숫자 형태로 변환한 후(디지털화 라고 한다), 해시함수를 통해서 고유 값으로 변환하여 데이터베이스나 OS에서 관리하는 비밀 장소에 저장하게 된다.

 

  마지막으로 제3자 인증 형태는 일반적인 관점에서는 암호화의 한 종류라고는 할수 없지만, 암호화의 쓰임과 등가거나 밀접히 연결되어 있기 때문에 여기서 연관하여 같이 설명하려고 한다. 제3자 인증 형태는 신원의 증명을 위해서 외부의 기관이나, 장치, 서버 등을 신뢰하는 것을 말한다. 현실로 따지면 계약시 동사무소에서 발급 받은 인감 증명서에 의해 계약이 효력이 생기는 것 같이, 신뢰할 수 있는(물론 해당 부분은 국가와 비슷하게 내부의 구성원들이 약속이나 이익이나, 법률등에 기반해 신뢰하는 것과 마찬가지로 절대적인 것은 아니다. 다만 믿지 않으면 현실적으로 개인이 살아갈 수 없거나, 많은 사람이 동의 하는 것이기 때문에 믿는 것이라고 볼수 있다. 우리가 현실의 돈이나 게임 내의 아이템, 비트코인 등을 교환 가능한 가치로 인정하듯이 말이다).

 

  이러한 부분들은 응용적인 측면이 강하기 때문에 앞의 4가지 타입의 암호화 와도 같이 맞물려 사용된다. 공개키-개인키를 이용한 전자서명의 기반이 되는 인증서의 존재를 특정한 상위 기관이 증명한다거나 하는 일도 벌어지고, 휴대폰, ARS 인증같은 소유기반의 인증이나, OTP 와 같은 소유와 서버 인증이 동시에 이루어지는 경우도 있고, 패스워드나 토큰 기반의 인증도 마찬가지로 서버 기반의 인증이라고 볼수 있다. 꼭 서버가 아니라더라도 모바일 폰에서 특정 횟수의 패스워드의 틀림이 있을때, 폰을 잠가버리는 행위도 제3자 인증 형태가 일부 차용된 것이라고 볼수 있을 것 같다.

 

  왜 암호화에 대한 얘기에 이런 제3자 인증을 끼워넣느냐고 생각할 수도 있지만, 암호화 라는 것은 키 측면에서 보면 해당 키를 가진 사람만이 암호화된 정보에 접근할 수 있는 인증의 개념도 포함되고 있기 때문이다. 마치 바위에 박혀있는 엑스칼리버를 아서왕 만이 뽑을 수 있는 것처럼 말이다. 여러 인증에서 사용하는 서버 쪽 만이 알고 있는 특별한 검증 정보 및 인증 로직은 암호화 알고리즘과 비슷한 측면이 있다. 뭐 여튼 암호와의 응용 측면까지 포함하려 생각하다보니 해당 개념을 빼고는 너무 사전적인 설명이 될것 같아서 포함하게 되었다.

 

  다만 앞에도 얘기했듯이 이 분류는 개인적으로 글을 구성하다 보니 개념적으로 나눠보게 된 것이고, 일반적인 보안 지식이나, 자격증 지식의 측면에는 타당한 분류는 아니라는 것을 잊진 말았음 한다. 그럼 각 요소들에 대해서 조금 더 자세히 들여다 보도록 하겠다.

 

 

 

2. 1세대

  1세대 암호화는 아주 옛날에는 풀기 불가능했던 암호화일지는 모르지만, 여러가지 수학적, 과학적 툴들이나 컴퓨터 프로그래밍이 발달한 현재에는 약점을 쉽게 드러낼 가능성이 높은 방식이다. 물론 특정 물리적 개체의 특성과 연관짓는다든지 하는 특수한 내부집단에서만 공유되는 비전서 적인 방법도 있을지는 모르겠지만, 보통 키 자체 또는 암호화 로직이 엄청 복잡해 지는 경우일 것이기 때문에 엄청 비효율 적일 것이다(예를 들어 특정 책의 본문 내용과 암호화 할 대상을 1:1로 섞는다든지 하는 방식이 있을 듯 싶다. 우리가 강력한 암호를 선택할 때 책의 좋아하는 문장을 적절한 특수문자와 섞어 암호로 사용한다든지 하는 것도 비슷할 것 같고 말이다). 이 쪽에서 보안 측면에서 생각할 문제는 이러한 방식에 대해서 유효한 암호화 라고 생각하는 보안적 측면에 경험이 적은 개발자 들을 종종 볼 수 있다는 것이다. 코드 안에서 AES 암호화를 수행 해야될 위치에 베이스64 함수를 이용해 인코딩을 한다든지 하는 식으로 말이다(쿠키에 베이스64로 인코딩된 인증 쿠키를 숨겨 놓는 등의 설계를 할 수 있다).

 

 

2.1 Base64

  세상에는 수많은 인코딩이 있지만(유니코드나, 각 언어별 인코딩, 더 나아가 스스로 만든 인코딩도 있을 수 있다) 몇 가지 보안적 측면에서 많이 거론되는 인코딩을 본다면 우선 "베이스64(BASE64)"는 어떠한 문자라도 웹을 통해 전달할 수 있는 아스키 형태로 변환 하는것을 말한다. 예를 들면 그림 파일을 업로드시 바이너리의 내용(이것도 앞에서 얘기했지만 어치피 특정한 숫자의 연속이다)이 베이스64식으로 인코딩 되서 HTTP Body 에 첨부되어 날라가게 된다(아마 뒤에서 업로드 코드를 시연할 때 실제로 보게 될것 같다).

 

[베이스64 - 위키백과]

https://ko.wikipedia.org/wiki/%EB%B2%A0%EC%9D%B4%EC%8A%A464

 

  실제로 베이스64 인코딩이 되는 부분을 보기 위해서, 여러 인터넷에 있는 툴이나 페이지를 이용해도 되지만, 여기에서는 다음 클라이언트 코드 시간에 사용하게 될 피들러를 설치한 후, 내장된 유틸리티인 TextWizard를 이용해 보도록 하겠다. TextWizard는 여러 종류의 인코딩 디코딩을 하게 해주는 유틸리티 이다. 해당 부분도 파이썬 10교시 WhoIS API 글에서 설명을 했기 때문에 그쪽에 있는 피들러 설치와 설정 방법을 참조해서 세팅하기 바란다. 현재 버전은 바뀌었지만 설치과정은 거의 비슷하다. 피들러를 실행하고 상단에서 Tools > TextWizard 나 TextWizard 아이콘을 클릭하면 아래와 같은 유틸리티 창이 나오게 된다.

 

  기본적으로 Transform 부분에 "To Base64"가 선택되어 있을 것이다. 위의 입력란에 넣은 텍스트를 베이스64로 인코딩 해준다는 뜻이다. 그럼 위쪽에 "안녕하세요." 이라고 넣게 되면, 하단에 베이스64로 인코딩 된, "7JWI64WV7ZWY7IS47JqULg==" 값이 나오게 된다.

 

 

 그럼 반대로 "7JWI64WV7ZWY7IS47JqULg==" 를 복사해서 위쪽 칸에 넣고, Transform 드롭박스에서 "From Baset64" 를 선택해 본다. 베이스64로 인코딩된 문자열로부터 평문을 만든다는 뜻으로, 다시 하단에 "안녕하세요."라는 문장이 나오게 된다.

 

 

2.2 URL Encoding

  2번째로 URL 인코딩은 브라우저의 주소창에서 사용되는 부분인데, 영어가 아닌 한글 같은 문자나, 공백 문자 등을 %OO 의 형태로 바꾸어 URL에서 사용할 수 있도록 하는 것을 말한다. 서버는 저 %OO으로 변환된 URL을 받아서 원래의 문자로 바꾸어 처리하게 된다.

 

[URL - Encoding URL - Regular Motion님의 블로그]

http://regularmotion.kr/url-encoding-url/

 

  이 부분도 TextWizrd 를 통해서 실제로 보도록 하겠다. 위쪽의 베이스 64위키 링크였던  "https://ko.wikipedia.org/wiki/%EB%B2%A0%EC%9D%B4%EC%8A%A464" 를 복사해서, TextWizard 에 복사하고, Transform 드롭박스에서 "URLDecode"를 선택 한다. 그럼 URL 뒤쪽에 암호와 같이 있었던 "%EB%B2%A0%EC%9D%B4%EC%8A%A464" 부분이 "베이스64" 라는 것을 알수 있게된다. 자세히 보면 뒤의 숫자 64는 아스키 코드이기 때문에 따로 인코딩이 되지 않고 한글 부분만 인코딩이 되어있다.

 

 

2.3 HTML Encoding

  마지막으로 HTML 인코딩은 설명하려 한다. <table>, <b>, <script> 와 같은 태그들은 원래 브라우저에서 문법 문자로 해석이 되어 테이블 형태, 볼드체 표기 등의 UI적 측면을 표시하거나 자바스크립트를 실행 하게 된다. 그런데 만약 해당 태그를 HTML 인코딩을 하게 되면, 태그 그 자체의 글자로 브라우저 화면에 표시되게 한다. 이러한 원리를 이용해서, XSS 공격을 방어하기도 한다.

 

[difference between url encode and html encode - 스택오버플로]

https://stackoverflow.com/questions/1812473/difference-between-url-encode-and-html-encode

 

  이것도 실제 보기 위해서 아래의 테이블을 보여주는 HTML 파일을 보도록 하겠다.

 

  가장 간단한 구조의 테이블 예제는 아래와 같다. <table> 태그가 맨 밖에 있고, 선(border) 굵기가 1 사이즈를 가진다. <th> 태그안에 제목인 '과자'와 '초콜릿'이  들어있고, 줄을 나타내는<tr> 태그가 두개 있고, 하나에는 '파이, 카카오45%' 가, 나머지 하나에는 '머랭, 카카오100%'  가 각각 <td> 태그안에 나눠 담겨 있다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<table border=1>
  <tr> 
     <th>과자</th>    
     <th>초콜릿</th>  
  </tr>  
  <tr>    
     <td>파이</td>
     <td>카카오45%</td>
  </tr>  
  <tr>   
     <td>머랭</td>
     <td>카카오100%</td>  
  </tr>
</table>
cs

 

 

  아무 폴더에나  파일형식을 "모든 파일"로 선택하고 "table_sample1.html" 이라고 저장한다. 이후 탐색기에서 해당 파일을 더블클릭해 실행하면 브라우저가 뜨면서 아래와 같이 테이블이 표시된다.

 

 

  이제 HTML 인코딩이 되는 경우를 보기 위해서, 해당 소스를 복사해서 TextWizard에 붙여 넣습니다. 이후 Transform 드롭박스에서 "HTML Encode" 를 선택한다.

 

   위와 같이 변환된 결과가 나오면, 아래의 결과를 드래그해 복사 후, 아무 폴더에나  파일형식을 "모든 파일"로 선택하고 "table_sample2.html" 이라고 저장한다. 이후 탐색기에서 해당 파일을 더블클릭해 실행하면 브라우저가 뜨면서 아래와 같이 랜더링된 테이블이 아닌 테이블 소스 자체의 문자로 표시 된다. 저 내용 안에 <script> 태그가 있다해도 일반적인 글자로 취급되서 실행이 안되니(마치 이전 SQL Injection 에서 Prepared Statement 호출시 인자가 문법 문자로 취급되지 않는 것과 원리가 비슷합니다), XSS 공격의 방어 수단으로 사용되기도 한다(이것도 좀 인젝션의 스토어드 프로시저나, Prepared Statement 처럼 원래 만들때의 의도는 XSS 방어를 생각하고 만들어진 것은 아니였을 것 같다)

 

 

  이렇게 위의 예제 3개를 보면 인코딩 이란것은 변환 로직에 기반한 암호화 이기 때문에 중요한 문자열을 저런 타입의 인코딩으로 변화해 보호하는 것은 의미 없는 행위라는 것을 이해할 수 있다. 이 세가지 인코딩을 확실히 이해하지 못하면 보안 공부할때 헷깔리는 경우가 종종 있으니 꼭 이해하고 넘어가길 바란다.

 

 

 

3. 2세대

  2세대가 되면서 암호화에 중요한 진전이 나타나는 데, 그것은 수학을 본격적으로 이용한다는 것이다. 그래서 2세대 이후의 암호화 방식은 수학 문제를 푸는 것과 같은데, 로직을 숨겨 놓은 1세대 암호화와는 다르게 2세대 이후는 전체 로직을 모두에게 공개 한다. 다만 그 수학문제를 풀 때 힌트인 암호화키를 모를 경우는 풀이 난이도가 엄청 상승되게 되어, 하나하나 숫자 대입 방식으로 풀려면 컴퓨터로 몇백년 만큼의 시간이 걸린다는 점이다.

 

  2세대 암호화는 대칭키의 성질을 이용한 암호화이다. 위에서 얘기했듯이 엑셀이나 zip파일에 암호화를 할 때 사용하는 방식으로, 암호화를 사용할때 사용한 키가 복호화 할때도 동일하게 사용된다.

 

 

  어찌보면 현실의 자물쇠-열쇠 조합과 비슷해 아주 직관적이라 암호화 계의 모범생이라고 보면 될것 같다. 그래서 현실에서 복사한 열쇠를 가족들과 나눠갖는 것과 마찬가지로 복사한 열쇠를 얼마나 조심히 잘 전달하고, 관리하는 지가 중요하다. 한 사람이라도 어수룩한 사람이 있게되면 자물쇠는 어처구니 없이 열리게 된다(물론 보안과 마찬가지로 중요한 자물쇠가 있는 장소 앞을 여러가지 물리보안이나, 추가적인 논리적 보안 수단을 통해서 보호해야 해야한다. 집문 앞에 CCTV 가 있다든지, 추가로 홍채 인식을 해야한다든지 말이다).  

 

 대칭키 암호화는 엑셀, zip 같은거 이외에도 우리가 잘 알고 있는 로그인이나, Gmail, 은행 등에서 사용하고 있는 HTTPS(SSL) 연결에서 키 교환 후 실제 데이터를 주고 받을 때도 사용하고, VPN 에서 VPN 장비와 컴퓨터 사이에서의 모든 데이터(여기서 암호화되어 전달되는 데이터 흐름을 터널링이라고 표현합니다)도 마찬가지 이다. 모바일 폰 내의 데이터 암호화도 사용자 패스워드에 기반한 키를 생성하여 대칭키 방식으로 저장하는 것으로 알고 있다. 그래서 패스워드를 모르면 데이터를 복구할 수 없다는 얘기가 나오게 된다. 또는 여러 회사나 단체에서 고객의 정보를 저장할 때, 중요한 개인정보나 카드 정보 같은 경우는 실제 프로그램 내부에서 불러와 사용해야 하기 때문에, 데이터베이스에 저장할때는 대칭키로 암호화해 저장하고, 필요할때 적절한 권한을 획득하여 복호화 된 평문 정보를 얻게된다.

 

  대칭키는 암호화 키에 풀이가 의존적인 수학 문제기 때문에 암호화키를 사용하지 않고 숫자들을 하나하나 대입할 경우 언제 쯤 답을 찾을 수 있는지가 중요하게 된다. 해당 시간이 짧거나, 많은 컴퓨터를 병렬로 연결하여 계산하거나, 몇 십년후의 컴퓨터에서는 금방 찾을 수 있는 수준이라면 나중에 현재 데이터를 암호화 해서 보호하고 있는 기술들이 모두 무용지물 되는 상황이 생길 수 있게된다. 그래서 여러가지 안전한 암호화 방식이 권장되고 있지만 가장 잘 알려지고 널리 쓰이고 있는 것은 AES 방식이다(보통 128, 256 정도의 키 길이를 가지며 키길이가 길어질 수록 2의 N승으로 풀이 난이도가 올라가게 된다).

 

 

  대칭키를 쓰다보면 몇 가지 정도의 주의해야 하는 이슈가 있는데, 그 중 하나가 키의 안전한 전달(교환)과 보관, 관리 이다. 만약 두 사람이 인터넷에서 특정한 대칭키를 기반으로 암호화해서 데이터를 보내기로 하면 최초 한쪽에서 만든 키를 전달해 줘야한다. 전화로 불러주거나, 직접 만나서 얘기해주거나, 종이로 적어 전해주거나, 암호화 해서 보낸후 구두로 암호화 키를 알려주거나 하는 많은 방법의 경우 "낮말은 새가 듣고, 밤말은 쥐가 듣는다"는 속담을 피해갈 수는 없게 된다. 또 암호화 키라는게 보통 의미 없는 숫자로 길게 만들어지기 때문에 가독성이나 암기하기에도 좋지 않다. 그래서 3세대에 설명할 비대칭 키와 인증이라는 개념을 이용해서 보통 현실적인 키교환을 하게 된다. 해당 부분은 비대칭 키 부분에서 설명하도록 하겠다(하지만 어쩌면 현실적으로는 사람이 와서 주위에 아무도 없는 것(도청장치 포함)을 확인한 후에 외운 내용을 불러주고 가는게 더 안전할 수도 있을 것도 같다).

 

  추가로 보관하는데 있어서도 암호키와 키를 사용하는 프로그램이 분리되어야 하는 이슈가 있게 된다(해당 부분은 법적인 이슈이기도 하다). 왜 그래야 하는지 생각해 본다면, 집문 앞의 화분뒤에 열쇠를 숨겨놓는 것과 같은 행위이기 때문이다. 물론 해당 집 문앞까지 가는 행위가 IT 로 이루어진 세상에서는 해당 서버내의 프로그램 실행 경로까지 침투해야되는 어려운 일이긴 할테지만, 일단 행위가 일어나게 되면 키의 탈취가 아주 쉬워지기 때문이다. 그래서 많은 프로그램 예제에 있듯이(이 글의 예제도 마찬가지 입니다) 소스 내부나, 컨피그 파일내에 암호화키가 덩그라니 들어있는 것은 옳지 않은 일이다.

 

  JAVA 등의 컴파일 되는 언어라도 바이너리를 분석석하여 끄집어내거나, 디버그 툴 등으로 해당 키 기능을 호출 할 수 있기 때문에, 집 앞에 구덩이를 파서 몰래 열쇠를 숨겨놓는 정도 밖에 안전하지 않다고 본다. 그래서 사실 여러가지 키관리 솔루션이나 설계를 이용하여, 권한 제어를 통해 키를 외부에 숨겨서 사용하긴 하지만 그것도 100% 안전한 방법이라고는 하긴 힘들것 같고(보안적으로 100% 안전하다는 것은 사실 좀 거짓말인듯도 싶다), 결국은 분리된 키관리와 함께 문앞에 낯선 사람이 맘대로 오지 않게하고, 혹시 오더라도 수상한 행동을 하지 않나 모니터링이 되도록 defense in depth 측면의 설계를 택하는게 현실적인 것 같다.

 

  마지막으로 한번 정해진 암호화 방식이나, 키를 바꾸는 것은 상당히 어렵기 때문에(프로그램 변경 이외에도 이미 기존 방식으로 암호화된 데이터가 있기 때문에, 해당 데이터를 모두 복호화 해서 평문으로 복구 후, 다시 새 방식으로 암호화를 하는 데이터마이그레이션을 해줘야 한다. 게다가 패스워드 등을 저장한 해시 같은 일방향 암호화 같은 경우는 원래 평문 값을 알 수 없기 때문에, 다시 사용자에게 값을 받기 전에는 기존 것을 없애고 새로 만드는 마이그레이션 자체가 불가능 하기도 하다), 처음 설계부터 이런 쪽은 제대로 표준과 법률에 맞추어 설계하는 것이 맞을듯 싶다.

 

 

  AES256 에 대한 예제는 파이썬에서 있던 예제를 가져와 보려한다. 우선 파이썬 3.7이 c:\Python 폴더에 설치되 있다는 가정에서 시작한다. 설치 및 실행 방법을 모른다면 파이썬 글 2교시를 참조하면 된다.

 

  파이썬 3.7에서는 pycrypto 의 상위 호환버전인 pycryptodome 의 한글 인코딩 문제가 해결되어 그대로 쓰면 될것 같다. 커맨드 창을 열고 PIP 명령어를 이용해 설치한다.

c:\Python\code>pip install pycryptodome

Collecting pycryptodome
...
Successfully installed pycryptodome-3.6.4

 

  예제는 아래와 같다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
# 모듈을 불러옵니다.
import base64
import hashlib
from Crypto import Random
from Crypto.Cipher import AES
 
# 암호화할 문자열을 일정 크기로 나누기 위해서, 모자란 경우 크기를 채워줍니다.
BS = 16
pad = lambda s: s + (BS - len(s) % BS) * chr(BS - len(s) % BS).encode()
unpad = lambda s : s[0:-s[-1]]
 
 
# 암호화를 담당할 클래스 입니다.
class AESCipher:
 
    # 클래스 초기화 - 전달 받은 키를 해시 값으로 변환해 키로 사용합니다.
    def __init__( self, key ):
        self.key = key
        self.key = hashlib.sha256(key.encode()).digest()
 
    # 암호화 - 전달받은 평문을 패딩 후, AES 256 으로 암호화 합니다.
    def encrypt( self, raw ):
        raw = raw.encode()
        raw = pad(raw)
        iv = Random.new().read( AES.block_size )
        cipher = AES.new( self.key, AES.MODE_CBC, iv )
        return base64.b64encode( iv + cipher.encrypt( raw ) ).decode()
    
    # 복호화 - 전달 받은 값을 복호화 한후, 언패딩해 원문을 전달합니다.
    def decrypt( self, enc ):
        enc = base64.b64decode(enc)
        iv = enc[:16]
        cipher = AES.new(self.key, AES.MODE_CBC, iv )
        return unpad(cipher.decrypt( enc[16:] )).decode()
 
 
# 암호화 클래스를 이용해 cipherinstance 객체를 만들면서, 암호화키를 넣습니다.
cipherinstance = AESCipher('mysecretpassword')
 
# 암호화를 합니다.
encrypted = cipherinstance.encrypt('감추고 싶은 말')
 
# 암호화 한 값을 다시 복호화 합니다.
decrypted = cipherinstance.decrypt(encrypted)
 
# 암호화 한 값과 복호화 한 값을 출력 합니다.
print('암호화된 값 : ' + encrypted)
print('복호화된 값 : ' + decrypted)
cs

[파이썬 소스 - aes_example_in_python.py]

 

   그럼 위의 파일을 aes_example_in_python.py 로 UTF-8 포맷으로 저장하고 실행 한다.

c:\Python\code>python pycrypto_aes256_sample.py

암호화된 값 : C0u2hrCZrAca69P7D3VFnSitOkTlPZbCxat9vMvZXN2cPSJUMu+Et3Ca+nZoYEO9
복호화된 값 : 감추고 싶은 말

 

  실행된 내용을 보면 같은 키로 암호화와 복호화를 하는 것을 볼 수 있다.

 

 

 

4. 3세대

  3세대는 비대칭 키라고 하며 공개키와 개인키라는 특이한 개념의 수학적 도구를 사용하게 된다. 2세대와 틀린 부분은 키가 하나가 아니라 2개로 이루어진 한 쌍이라는 것이다. 개인키로 암호화된 값은 공개키로 복호화 될수 있고, 공개키로 암호화된 값은 개인키로 복호화 될수 있다. 개인키를 가진 쪽이 좀더 빨리 복호화가 된다고 하는 것 같으나, 가장 주요한 차이는 공개키 쪽이 열쇠의 역활도 하지만 자물쇠의 역활도 한다는 것입니다(물론 개인키도 전자서명의 측면에서는 자물쇠의 역활도 한다고 볼수 있지만, 주로 하는 역활은 열쇠라고 보는게 맞을 듯 싶다)

 

  보통 알고리즘으로는 RSA 와 좀더 최근에 나온 ECC(elliptic curve cryptography-타원곡선암호) 를 사용하게 되는데 일반적으로 ECC가 같은 수준에서 키가 더 짧아 간결하다고 하고, 자세한 차이점을 정말 이해하려면 수학적 차이일 테니 양쪽의 수학적 원리를 이해해야 할듯하다.

 

[Which one is better: elliptic curve cryptography or RSA algorithm and why? - Quora 사이트]

https://www.quora.com/Which-one-is-better-elliptic-curve-cryptography-or-RSA-algorithm-and-why

 

 

  가장 흔히 쓰이는 분야가 앞서 얘기한 HTTPS(SSL)의 경우인데, 최초 브라우저와 서버가 서로 사용할 대칭키를 비밀스럽게 교환하기 위해서 사용한다. 다만 여기서 현실적인 딜레마가 생기게 되는데, 서버가 보내준 공개키를 어떻게 믿고 클라이언트 쪽의 브라우저가 암호화에 사용할 대칭키를 해당 서버의 공개키로 암호화해 보내느냐 이다.

 

  이러한 딜레마를 해결하기 위해 인증서의 개념이 생기게 됬는데, 사실상 해결책이 신뢰할 수 있는 국제 기관이나 국내 기관의 공개키를 클라이언트쪽 OS(예:윈도우즈, 리눅스)가 인지하여 관리하고, 해당 기관의 개인키를 이용해서, 서버 사이트의 공개키를 보증 하는 방식이다. 뭔가 절대적으로 안전해 보이진 않지만 마치 우리가 은행이나 국가를 믿듯, 일단은 OS나 저러한 (루트) 인증 기관을 믿는것이 전제로 되어있다(앞에도 얘기했지만 보안은 100%인 것은 없어 보인다. 사실 우리가 사는 현실자체가 100% 는 없기 때문에 당연할 것을 수도 있다). 

 

 여기서 또 전자서명이라는 개념이 추가로 들어오게 되는데, 하나의 개인키로 특정한 값을 암호화 해서 만들어 내면, 공개키를 가진 사람이 해당 값을 복호화 하게 되서 기대했던 일련의 값들을 얻을 수 있다면, 해당 복호화된 내용은 해당 개인키를 가진 사람이 작성했다는 것을 증명하게 된다는 것이다(왜냐하면 개인키는 그 사람만 가지고 있어야만 하는 것이기 때문이다-물론 해킹을 당하는 경우는 아니겠지만, 이런 아닌 경우는 비트코인 지갑이 털리거나 할 때 일어나는 일이 된다).

 

 

  예를 들자면 특정 A 회사가 서버가 추가되서 SSL 통신을 해야되는 일이 생기면, 베리사인 같은 루트 인증 기관에 1년에 특정한 금액을 내고 인증서를 발급 받게 된다. 인증서 안에는 A 회사 도메인의 주소, 인증서 유효기간 등등의 정보와, A 사의 공개키가 포함되어 있고, 그 모든 정보를 적절히 믹스하여 루트인증기관의 개인키로 암호화한 전자서명이 들어있다. 사용자의 브라우저에서는 해당 인증서를 받아서, 알고 있는 루트인증기관의 공개키로 전자서명을 풀어, 복호화된 내용이 인증서에 기재한 내용들과 일치하는지 확인한다. 내용이 일치하게 되면 A 사의 공개키는 믿을 수 있으므로, A사의 공개키로 HTTPS 통신에 사용할 대칭키를 암호화해 보낸다. A 사의 서버는 해당 암호화된 내용을 받아 개인키로 풀어 대칭키를 얻어낸 후, 이후 통신 부터는 해당 대칭키로 암호화해 내용을 주고 받게 된다(공개키-개인키 방식이 연산 비용이 많이 들어 대칭키로 실제 암복호화를 한다고 한다).

 

  개인이 받는 공인인증서도 비슷하다. 공개키를 증명하는 인증서를 신용평가 회사에서 받게 된다. 조금 다른 부분은 개인키 또한 같이 발급받아 보관하면서, 개인키는 유출이 되면 큰일이 나니까 따로 대칭키 방식을 이용해서 개인키를 암호화 하여 보관한다(공인인증서를 발급 받을때 입력하는 개인의 비밀번호가 해당 대칭 암호키 이다). 그럼 아마도 확실한 내부 동작은 모르겠지만, 은행 사이트에 접속하면 은행 쪽에서 개인의 인증서를 가져가 신용평가 회사의 공개키로 풀어서 내용을 확인해, 신용평가사에서 해당 개인 계좌주인에게 발급한 공개키라는 것을 확인하할 것이다. 이후에는 그 공개키를 이용해서 거래에 관련된 정보를 암호화해 보내거나, 같이 저장된 개인키를 이용해서 거래를 증명하는 전자서명을 보내거나, HTTPS 에서 사용할 대칭키를 보내거나 할것 같다.  

 

[공인인증서 비밀번호의 안정성 - CPUU의 DayDreamin']

https://cpuu.postype.com/post/177466

 

[네이버 애플리케이션의 전사 서명 원리 - 네이버 D2]

https://d2.naver.com/helloworld/744920

 

  실제로 보안 분야 뿐만 아니라(물론 안전하게 인증을 하면서 편하게 사용하기 위한 보안적 측면을 위해 도입된 것이겠지만), 비트코인, GIT, SSH, PGP, 빅데이터 시스템 쪽에서도 이러한 개념을 가져다 사용한다. 비트코인은 코인주소를 나타내는데 공개키를, 지갑 열쇠를 나타내는데 개인키를 사용하고, GIT 또한 SSH(Secure Shell) 연결을 위해 공개키-개인키 쌍을 생성하여 깃서버와 개인 컴퓨터가 나눠가져 해당 키 인증으로 사용을 한다. 리눅스도 마찬가지로 id/password 대신 공개키 인증을 통해 로그인을 하여 사용할 수 있다(그게 id/password 보다 더 안전하냐는 별개의 문제겠지만).

 

  PGP 도 각각의 공개키를 공개키 서버에서 얻어 공개키로 메일 내용을 암호화 안전하게 보내는 것이라고 보면되고, 하둡 등의 여러 클러스터링 설정 시에도 아마 주키퍼 등에서 공개키, 개인키를 이용해 서버간의 작업 수행에 대한 권한 인증을 하기도 했던 것으로 기억한다(앞의 공인인증서의 개인키와 마찬가지로 추가로 패스워드를 지정하기도 한다). 공개키, 개인키 쌍으로 로그인을 하는 것과 같은 경우는, 공개키가 본인만의 자물쇠를 나타내며, 등록한 자체가 해당 공개키를 믿는 것을 의미하는 것이기 때문에(이 자물쇠를 연다면 들여보내줘...), 마냥 공개적인 것만은 아닌 측면도 살짝 보이는 것 같다. 그래서 공개키-개인키의 이름에 넘 칩착하면 뭔가 꼬여 버릴 수도 있다. 공개키는 쓰임에 따라서는 마냥 공개된 키만이 아니라는 것을 염두에 두어야 한다. 

 

 

  그럼 뭔가 예제가 없으면 섭섭할 것 같아서, 조촐하지만 파이썬을 이용해서 RSA 공개키와 개인키 쌍을 하나 만들어 보도록 하겠다. 구글에서 "python generate rsa key" 라고 찾으면 아래의 깃허브 페이지가 나온다.

 

[Python PyCrypto: Generate RSA Keys Example.py - lkdocs 깃허브]

https://gist.github.com/lkdocs/6519378

 

  밑의 댓글하고 섞어서 RSA2048 키를 만들도록 적당히 주석을 달았다. PEM 포맷은 공개키, 개인키를 교환할때 사용하는 표준 포맷 중 하나이다(편하게 위의 인코딩+형식을 정의한 규칙이라고 봐도 될 듯 하다)

1
2
3
4
5
6
7
8
9
10
11
12
13
from Crypto.PublicKey import RSA 
 
# 새로운 RSA 생성 
new_key = RSA.generate(2048)
 
# 공개키를 얻어 옵니다.
public_key = new_key.publickey().exportKey("PEM"
 
# 개인키를 얻어 옵니다.
private_key = new_key.exportKey("PEM"
 
print (private_key)
print (public_key)
cs

 

   그럼 위의 파일을 aes_example_in_python.py 로 UTF-8 포맷으로 저장하고 실행한다.

c:\Python\code>python rsa_gen.py

b'-----BEGIN RSA PRIVATE KEY-----\nMIIEogIBAAKCAQEAkhB0qnHrNpFO5rlyiMzBkU55pvIjj5Zgk3TfPEFXzMvyORW/\nuuiL8mIfmIaouPUj+eEPvfG7Zdk2rV2rf6bUL1Of9 .....

 

 

 

5. 특수형태 - 해시

  해시는 보안에 들어오기전 처음 프로그래밍 공부할때 봤을때 참 신기한 기능을 하는 함수라고 생각이 들었었다. 사실 해시의 유용함은 보안적 관점을 추가해 봤을때 가장 잘 이해되는 것도 같다. 

 

  해시 또한 수학적 개념으로 아무리 큰 숫자라도 해시라는 함수를 적용하게 되면 고정 길이를 가진(SHA256 같은 경우 256bit 길이의 숫자가 나온다는 의미이다) 숫자로 변환되게 된다. 해시가 유용한 것은 서로 다른 숫자라면 같은 해시 값이 나올 가능성이 거의 없고, 만약 있더라도 같은 해시값을 가지는 서로 다른 숫자를 의도적으로 만들기에는 너무 많은 시간이 걸린다는 성격을 가지고 있다. 또한 해시값으로 부터 원래 값을 유추하기가 아주 많이 힘들다는 특징도 가지고 있다(이것은 2, 3 세대 암호화와 비슷한 부분이다)  

 

 

  해시는 보통 검증을 위한 측면과, 정체를 들키지 않기 위해 숨기려는 2가지 측면을 동시에 가지고 있다. 검증하기 위한 측면은 백신 프로그램에서 특정 악성코드 파일의 해시 값을 비교 하거나, 게임이나 어플의 패치시 패치파일의 유효성이나, 설치된 어플이 조작되지 않았다는 것을 체크하는데도 해시 값을 사용한다. 또는 여러 파일 공유 사이트에서 불법, 저작권 파일 등을 체크해 내기 위해서도 파일의 해시값을 비교하곤 한다. 파일의 내용이 1비트만 바뀌더라도 파일을 구성하는 숫자가 달라지는 것이기 때문에, 새로운 해시값이 만들어지는 특징을 이용한 검사 이다. 비트 코인 같은데서도 채굴 및 블록의 검증을 하는 경우에도 사용하고 있다.

 

  또한 가입한 회원들의 패스워드를 저장할때도, 법적으로 해시화 해서 저장하도록 되어 있다. 사람들은 보통 여러 사이트에 동일한 패스워드를 사용하기 때문에, 특정 회사에서 저장한 패스워드의 평문을 복구할 수 있다면 위험 부담이 생길 수 있을 것이다. 그래서 혹시나 인터넷의 수상한 사이트(?)를 회원가입을 통해서만 사용할 수 있다면, 첫째는 사용하지 않는 것이 제일 좋을 테고, 어쩔수 없이 사용해야할 때에는 다른 주요 사이트에서 사용하는 id/password 로는 등록하지 않는 것이 좋아보인다.  그 사이트에서 패스워드를 해시를 해서 저장할지, 평문으로 저장할지도 모르고, 그것과 상관없이 중간에서 빼내어 다른데에 나쁘게 쓸지는 아무도 모르니까 말이다. 또 내부 직원은 풀수 있는 양방향 암호화로 저장하거나 하는 실수를 할 수도 있고 말이다.

 

  해시로 저장한 경우 원본 값을 알 수 없기 때문에,  사이트에서는 사용자가 입력한 패스워드를 받아서 해시함수로 넘긴 후, 결과에 나온 해시 값을 회원 가입때 입력했던 패스워드 해시값과 비교해서 검증하게 된다(그래서 사이트에서 비밀번호 찾기 할때 무조건 새로운 비밀번호로 바꾸지, 원래 비밀번호를 알려주진 못하게 된다. 만약 잊어버린 비밀번호를 알려주는 사이트라면 평문으로 저장됬거나 양방향으로 잘못 저장된 경우라고 논리적으로 확신할 수 있다).

 

 

  반대로 해시값을 숨겨야 하는 측면도 있다. 여기서 숨긴다는 의미는 레인보우 테이블 같은 시도로부터 정체를 숨긴다는 의미이다. 레인보우 테이블은 평문을 해시함수로 만들면 항상 일정한 값이 나온다는 것에 착안해서, 해시와 평문의 매칭 테이블을 만든다고 한다. 뭐 단순하게 1:1 매칭으로 테이블을 만드는건 아니고 빠른 검색을 위해 이런저런 구조의 최적화를 한다고는 한다. 이런 문제 때문에 현실에서의 외모의 변장과 같은 일들을 해시값을 만들어 낼때 추가로 해야한다.

 

  첫번째는 솔트(salt)로 요리에 소금을 치듯이 사용자가 입력한 패스워드에 특정한 랜덤 문자열을 더한 후 해시 함수를 적용해서, 만들어진 해시 값을 다르게 한다. 패스워드마다 서로 다른 솔트 값을 만들어 내야 하는 이유는, 안 그러면 하나의 패스워드만 알아내게 되면, 이후 고정된 솔트값을 알수 있게 되기 때문에 해당 솔트가 가미된 새로운 레인보우 테이블도 만들수 있게 될 것이기 때문이다. 두 번째는 해시를 몇번씩 다시 해싱을 해서 전혀 다른 값을 만든다는 것인데, 이건 마치 악성 코드들이 코드를 안 들키기 위해서 여러번 포장을 하는 것과 비슷해 보인다(가끔 방어 기법과 공격기법이 마찬가지인 경우가 있다. 랜섬웨어 처럼 말이다). 이 경우 값도 달라지고 brute force 방식으로 진행시 한번 계산하는 시간을 많이 걸리게 해서 찾기 힘들 게 만든다고 한다. 뭐 여튼 이것도 100% 완벽하다고는 못하겠지만 안 그런 데이터를 공격할 때 보다는 공격자의 ROI가 확실히 안 나오게는 만들 순 있을 것 같다. 

 

[패스워드 털려서 써보는 패스워드 암호화 - 장모님 브런치]

https://brunch.co.kr/@jangcnet/11

 

[안전한 패스워드 저장 - 네이버 D2]

https://d2.naver.com/helloworld/318732

 

 

  그럼 python.exe 파일을 열어 SHA256 해시값을 얻는 예제를 하나 보겠다. 구글에서 "python file sha256" 라고 검색하여 제일 처음의 github 샘플을 봅니다.

 

[simple SHA256 hashing example, written in Python using hashlib - rji님 깃허브]

https://gist.github.com/rji/b38c7238128edf53a181

 

  역시 적당히 한글 주석과 함께 python.exe 파일을 가져오도록 편집을 해보면 아래와 같다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
import hashlib
import sys
 
# 파일 읽어들일 블록 사이즈
block_size = 65536
 
sha256 = hashlib.sha256()
with open("c:\python\python.exe"'rb') as f:
    for block in iter(lambda: f.read(block_size), b''):
        # 읽어 들인 값을 계속 해시객체에 추가한다.
        sha256.update(block)
    # 최종 해시 계산
    print (sha256.hexdigest())
 
cs

 

  그럼 위의 파일을 "aes_example_in_python.py" 로 "UTF-8" 인코딩으로 저장하고 실행 한다. 아래와 같이 해시 값이 나온다. 여러번 실행해도 계속 같은 값이 나오는 것을 볼 수 있다.

c:\Python\code>python sha256_gen.py
e964f2e498ab3141d86da5f0d6e135be82986c66aaafef356b6e7751b779a796

 

 

 

 

6. 제3자 인증 형태 - 설계적 인증

  이제 마지막 부분이다. 이 부분은 앞에서 얘기한 베리사인같은 CA 기관이나 신용 정보회사 같은데서 하는 서비스하는 공개키의 대한 신원의 보증같은 측면도 있지만, 추가로 언급하고 싶은 부분은 설계적 인증 형태라고 보는 것이 어떨까 싶다. 이 부분을 암호화 글에 넣어 설명하는 경우가 맞을까는 싶지만(뒤에서도 아마 계속 언급되어질 주제같다), 암호화와 연관지어 설명해야 가장 맘에 닿을 것 같기 때문에 일단 이 곳에서 우선 언급하려 한다.

 

  1번째는 서버 측면의 로직이다. 패스워드 추측 공격을 피하기 위해서 시도 횟수를 제한하거나,  특정 횟수 후 캡챠를 걸거나, 입력 할때마다 인증 받는 시간을 증가시키거나 하는 경우도 안전한 암호화를 돕는 방법이 될 것 같다.

 

  2번째로 핸드폰, 태그 방식의 도어키, OTP 등 소유에 대한 안정성을 기반으로 한 인증도 역시 마찬가지로 암호화와 동등한 레벨의 방어를 가지게 된다(defense in depth 측면이기도 하지만, 법적으로 암호화 행위와, 전용선의 사용이 등가적인 보호수단으로 취급되는 것도 이런 측면이라고 생각한다).

  

  세 번째로 I-PIN 같은 기술이 주민번호를 대체하기 위해 나와서, 이전 같으면 주민번호가 양방향 암호화 되서 저장될 수 있는 부분을 개인정보와 관련있는 임의의 고유키의 저장으로 대체하게 되었다(물론 I-PIN 회사 내부에서는 주민번호와 해당 CI, DI 값의 연결고리를 알고 있겠지만, CI나 DI 값만을 사용하는 일반 회사들은 해당 주민번호를 알 순 없다). OTP 도 개인만 아는 패스워드로 인증 받는 체계를, 소유 기반 인증에 더해서, 서버만이 알고 있는 임의의 패스워드(OTP 생성번호)로 대체했다고 보면 될것 같다.

 

  네 번째로 쿠키 등의 특정 장소에 보관된 암호화된 인증 값에 대한 재사용 방지 이슈도 있다. 특정 값을 암호화 했더라도 해시나, AES 같은 경우는 해당 값의 고유성이 사라지진 않는다. 그래서 해당 데이터를 그대로 복제해 사용할 경우 인증을 할 수 있는 재사용 이슈가 있다. 해당 부분에 대해서는 랜덤 값인 시간, 거래 고유 번호 등 항상 달라지는 서버 측면 요소들을 더해 암호함으로서 항상 값이 달라지게 만들고, 해당 달라지는 값들을 서버 측면에서 검증(시간이 5분이상 지났다든지, 거래 고유 번호 등의 값이 맞는다 든지)해 사용해야 되는 이슈가 있다. 뭐 이렇게 특정 값을 unvalidate 시키는 것은, 토큰인, 비트 코인등 다른 쪽에서도 마찬가지 인것 같다.

 

 

 

7. 마무리 하면서

  써 놓은 글을 뒤돌아 보니, 요약해 보면 간단한 암호화에 대한 얘기를 너무 거창하게 펼쳐 놓지 않았나도 싶다. 하지만 앞에서 봤듯이 암호화 부분이 정말 많은 기술 분야 안에 기초 구조로 숨어 있기 때문에, 해당 측면들을 인지하지 못한다면, 어플리케이션의 취약점에 대해 불완전하게 이해할 가능성이 높다. 아마 다음 시간에 얘기할 클라이언트 코드 쪽 보안에 대한 얘기도 불완전하게 될 가능성이 높고 말이다.

 

  그리고 전공이 맞아 천천히 공부해서 수학적으로 깊게 이해한 사람들도 있겠지만, 그렇지 못한 사람에게는 논리적으로라도 해당 개념을 정확하게 잡고 있는 것이 중요한 듯 싶다. 안 그럼 자꾸 상상의 나래를 펼치게 되어 잘못된 의견을 가지게 될 수도 있으니 말이다. 그럼 이렇게 이번 시간을 마무리를 하도록 하겠다. 

 

 

2018.7.22 by 자유로운설탕
cs

 

 

posted by 자유로운설탕