어떻게 안전한 서비스를 만들 수 있을까, [인크립션]

안전한 서비스를 위해서는 암호화는 빼놓을 수 없다.
암호화는 어떤 내용은 메시지를 전달받은 사람 이외에 다른사람들은 메시지를 알아볼 수 없게 하는 것이다.
고전 암호에서는 메시지의 내용을 바꾸거나 위치를 바꾸는 기본적인 암호화 방식을 사용하거나 기계암호를 사용했다.
현대 암호에서는 공통키 암호화와 공개키 암호화를 사용한다.
암호화의 세 가지 보안 기능은 기밀성, 무결성, 인증이다.
기밀성은 보안 대상을 잘 감췄다는 뜻이고,
무결성은 자격이 없는 자에 의해 내용이 위변조되지 않았다는 뜻이고,
인증은 어떤 사물이나 사람의 신원을 증명하는 과정을 의미한다.
암호화를 뜻하는 Encipherment는 기밀성을 유지하기 위해 보안 대상을 감추는 것에 중점을 두고 있고,
Cryptographic Processing은 기밀성, 무결성, 인증에 사용하는 넓은 개념이다.
그리고 Encryption은 기밀성을 유지하는 도구에도 사용될 수 있고 기밀성, 무결성, 인증에 대한 개념에도 사용될 수 있는 개념이다.
암호 시스템에서는 전송하려는 내용을 암호화 알고리즘과 암호화 키로 암호문으로 바꿔서 보내고,
암호문은 복호화 키로 풀어서 평문으로 되돌린다.
이 암호 시스템이 현대 암호화의 기본 기준이기 때문에 IT 시스템의 모든 암호화는 암호화&복호화 모델로 설명할 수 있다.
어떤 서비스가 안전하다는 것은 시스템을 구성하는 계층마다 보안에 필요한 요소를 모두 구현해서 동작하는 것이다.
기존 시스템을 안전하게 만들려면 시스템 계층마다 보안 핵심 요소를 모두 적용해야 안전성을 확보할 수 있다.
IT 시스템 계층에는 네트워크, 시스템, 애플리케이션 세 계층이 있다.
그리고 안전한 IT 시스템은 각 계층에서 암호화하고, 해킹을 방어하고 적절한 관리를 수행하는,
암호화, 인증, 권한 관리, 취약점 탐지, 침해 대응, 감사, 교육 및 관리를 하는 시스템이다.
보안요소는 크게 암호화, 관리, 해킹 방어 세 가지로 구성된다.
암호화에는 인증, 암호화, 권한 권리가 포함되고,
관리에는 감사와 교육 및 관리가 포함되고,
해킹 방어에는 취약점 탐지, 침해 대응이 포함된다.
해킹 방어와 관리는 바뀌는 상황에 따라 대응을 해주어야 하지만,
암호화는 수학, 공학 이론과 체계가 잘 정립되어 있기 때문에 안전한 IT을 위한 핵심 도구이다.
침해 사고가 발생하더라도 암호화를 해두면 현재 컴퓨팅 성능에 대해 안전한 설계 및 구현을 보장할 수 있다.
해킹방어는 네트워크 계층에서는 네트워크 보안이, 시스템 계층에서는 안티바이러스가, 애플리케이션 계층에서는 웹 보안으로 한다.
데이터 보안을 하는 암호화는 데이터를 잘 숨기고, 데이터에 접근할 수 있는 권한을 제어하고, 로그로 기록한다.
각 계층마다 암호화를 해야되기 때문에 네트워크 계층의 패킷, 시스템 계층의 파일, 어플리케이션 계층의 개인 정보들을 모두 암호화해야한다.
시스템 수준의 암호화는 하드디스크가 자동으로 암호화, 복호화하는 것이 있다.
네트워크 수준의 암호화는 패킷을 암호화하는 것이다.
이 때 네트워크와 시스템 수준에서도 데이터 암호화를 해야하지만, 애플리케이션 수준에서 데이터를 암호화를 잘 해야한다.
애플리케이션 수준에서 암호화를 하면 데이터가 시스템과 네트워크를 거치면서 암호화된 상태로 이동하기 때문이다.
컴퓨터 성능이 좋아짐에 대응할 때는 키 길이만 늘려도 암호화를 복잡한 알고리즘을 사용할 필요없이 대응할 수 있다.
유명한 암호화 방식인 DES는 파이스텔 암호화 방식의 SPN을 16번 반복해서 수행하는 암호화 알고리즘이다.
알고리즘은 특정한 크기의 데이터를 처리하는데, 알고리즘이 처리하는 데이터 덩어리를 블록이라고 한다.
DES는 블럭 크기가 64비트이다.
만약 블럭 크기보다 큰 데이터를 암호화해야된다면 블럭 크기로 데이터를 자르고, 자른 부분마다 알고리즘을 적용해서 결과물을 합치게 된다.
운영 모드는 알고리즘이 다양한 크기의 데이터를 처리하도록 구성하는 단위 암호 시스템을 구성하는 방식을 말하고,
운영 모드를 이용해서 다양한 크기의 데이터 전체를 정해진 크기의 데이터 블럭을 처리하는 알고리즘으로 처리할 수 있게 된다.
치환과 순서 바꿈으로 SPN(Substitution Permutatiom Network)을 설계하고, SPN을 반복 조합하여 알고리즘을 만들고,
알고리즘을 특정한 방식으로 동작해서 단위 암호 시스템을 만들고, 단위 암호시스템 여러 개가 모여 전체 암호 시스템을 구성할 수 있다.
그리고 전체 암호 시스템의 안전성은 암호화된 결과물에서 원본 메시지나 키 정보를 찾을 수 있는지를 통해 판단할 수 있다.
암호화되어 있어도 안심을 할 수는 없다.
암호 시스템도 공격을 당할 수 있기 때문이다.
암호 시스템 공격 유형에는 세 가지가 있다.
COA는 공격자가 암호문만 알 때 사용하는 공격 방식이고,
KPA는 공격자가 원문의 일부와 일부에 해당하는 암호문을 알 때 사용하는 공격 방식이고,
CPA는 공격자가 원문의 일부를 선택해서 그에 해당하는 암호문을 확인할 수 있을 때 사용하는 공격 방식이다.
CPA, KPA, COA 순으로 위험하다.
운영 모드나 알고리즘, 암호 시스템의 안정성을 평가할 때는 이 세 가지 공격 유형을 고려해야 한다.
암호화를 할 때는 암호 알고리즘으로 단위 암호 시스템을 구성하는 기본적인 방법인 운영 모드를 적절히 선택을 해야한다.
NIST가 표준으로 정하고 안전성을 인정한 아홉가지 운영모드가 있는데, 이는 기밀성 모드, 무결성 모드, 기밀성+무결성 모드로 구분된다.
데이터를 숨길 때는 기밀성 모드를 사용하고,
기밀성 모드에는 ECB, CBC, CFB, OFB, CTR등이 있다.
많은 기밀성 모드에서 XOR연산을 활용한다.
XOR연산은 배타적 논리합이라고 하는데, 컴퓨터가 하는 연산 중 가장 간단한 연산이다.
이 연산을 수행하려면 두 값의 크기가 같아야 한다.
그리고 A+B = C면 C+B=A이다.
따라서 어떤 값에 대한 XOR연산의 결과 값에 동일한 XOR연산을 수행하면 원래 값으로 돌아간다.
ECB
암호화할 데이터를 알고리즘이 처리할 수 있는 크기의 블록으로 자르고, 각 블록을 암호화해서 합치는 방식이다.
이 때 같은 내용의 블록이 있다면 암호화된 블럭도 동일하기 때문에, 반복해서 나오는 단어나 문장이 어떤 정보인지 유추할 수 있다면 매우 위험해진다.
원문에 대한 정보를 알 수 없는 확산이 달성되지 않고, 암호문에 원문의 통계적 특성이 드러나기 때문에 ECB는 안전한 운영 모드가 아니다.
CBC는 원문이 같아도 동일한 암호화 결과물이 나오지 않도록 하기 위해 암호화하기 전에 원문 블록을 가공하고,
이전 블록의 암호화 결과를 다음 원문 블록의 암호화에 사용한다.
이전 블록의 암호화된 결과물을 다음 블록의 원문과 XOR연산을 하게 되기 때문에 원문이 같아도 다른 암호문이 도출된다.
또한 암호화 결과물이 같아도 원문이 같다고 할 수 없기 때문에 CBC는 안전한 운영 모드라고 할 수 있다.
첫 원문 블록은 이전 블록이 없기 때문에 운영자가 초기화 벡터라는 특정한 값을 넣어야 하는데,
원문 데이터 블록과 크기가 같은 임의의 값을 난수나 복잡한 값으로 넣을수록 확산이 잘 돼서 더 안전한 운영 모드가 된다.
복호화를 할 때 초기화 벡터가 필요하기 때문에 초기화 벡터를 복호화하는 쪽에 잘 전달해야 하고, 잘 관리해야 한다.
CBC모드의 단점은 블록 암호화 값들이 연결되어 있기 때문에 특정 부분만 복호화할 수 없고, 전체를 복호화한 뒤 특정 부분의 값을 찾아야 한다는 것이다.
CFB
원문을 암호화하기 전에 암호 알고리즘을 거친 값과 원문을 XOR연산해서 암호문을 만든다.
이전 블록의 암호문이 암호 알고리즘을 거친 후에 다음 블록의 원문을 XOR연산해 블록의 암호문을 만드는 것을 반복한다.
초기화 벡터는 운영자가 선택하고, 관리해야 한다.
OFB
처음에 넣은 초기화 벡터 값이 암호 알고리즘을 반복해서 거친 값과 블록의 원문을 XOR연산해서 암호문을 만든다.
초기화 벡터만 정하면 원문 블록과 XOR하기 직전의 값들을 미리 계산할 수 있어서 순차적으로 암호화하지 않고 한꺼번에 암호화할 수 있어서 병렬 처리가 가능하다.
한꺼번에 많은 양을 암호화할 수 있다는 장점이 있고,
초기화 벡터가 암호화 알고리즘을 거칠 때 주기성이 발견되면 안전성에 문제가 생길 수 있다는 단점이 있다.
따라서 초기화 벡터를 매번 다르게 설정해서 정보가 노출되지 않도록 하는 것이 중요하다.
CTR
초기화 벡터로 단 한 번만 사용하는 숫자인 넌스를 넣고, 그 다음 블록부터는 넌스값에 1씩 더해 난수를 생성하고,
난수와 원문 메시지를 XOR연산을 수행해서 암호화한다.
넌스에 1만 더해도 블록마다 안전한 난수를 얻을 수 있는 것은 암호 알고리즘이 입력 값을 아주 조금만 바꿔도 출력 값이 완전히 달라지는 쇄도 효과가 있기 때문이다.
따라서 OFB모드의 장점을 가지면서 확산을 강화한 운영 모드에 해당한다.
기밀성 모드에서 ECB는 원문의 패턴이 드러날 수 있고, OFB보다는 CTR이 조금 더 안전하고,
CTR에서는 초기화 벡터로 사용하는 넌스가 유일한 값이어야 한다는 점을 유의해야 한다.
암호화에 사용하는 키의 길이도 매우 중요하다.
보안 강도는 어떤 길이의 키의 보안성 정도를 뜻하고, 키 길이와 보안 강도는 보통 비례한다.
최소 보안 강도는 최소 키 길이이다.
키 길이가 길수록 키를 알아내기 더 어렵고, 무차별 대입 공격으로 키를 알아내기 어려워진다.
컴퓨터의 성능이 향상됨에 따라 권고하는 키 길이도 길어진다.
대칭키 알고리즘에서도 해당 알고리즘이 사용하는 키 길이만큼 보안 강도가 세진다.
따라서 알고리즘은 가능한 모든 경우의 수를 대입하는 것이 가장 쉬운 해독 방법이고, 다른 지름길이 없을 때 안전하다고 판단할 수 있다.
암호화에 많이 사용되는 해시 함수에 대해서도 알아보자.
해시 함수는 임의의 길이의 데이터를 특정 길이의 데이터로 변환하는 함수이다.
해시 함수는 원본 데이터 길이에 관계 없이 정해진 길이로 변환한다.
해시 함수는 암호화 알고리즘에서 필요한 키가 필요 없고, 해시 값의 길이가 암호화 알고리즘의 키 길이와 동일한 역할을 한다.
이 때 안정성을 보장하기 위해 해시 함수에 필요한 키 길이는 대칭 키 알고리즘의 두 배 이상이다.
해시 함수는 일정한 길이로 바꾸는 과정에서 정보의 손실이 발생할 수 있고,
원본 데이터가 달라도 결과물이 동일하게 나타나는 충돌 가능성이 있다.
해시함수는 역상 저항성, 제2 역상 저항성, 충돌 저항성의 특징을 지닌다.
역상 저항성은 해시 값이 주어졌을 때 그 해시 값을 만드는 입력값을 알아낼 수 없는 특성이다.
역상 저항성이 있다면 비밀번호의 해시 값을 획득해도 비밀번호를 알아낼 수 없게 된다.
제2 역상 저항성은 동일한 해시값을 가지는 다른 입력 값을 찾을 수 없다는 특성이다.
제2 역상 저항성을 통해 위조를 방지할 수 있게 된다.
충돌 저항성은 동일한 해시 값을 생성하는 두 값을 찾을 수 없다는 특성이다.
충돌 저항성이 없다면 비밀번호를 몰라도 같은 해시값을 도출하는 입력값을 찾으면 로그인할 수 있기 때문에
서로 다른 비밀번호를 한 가지 비밀번호로 로그인할 수 있게 된다.
따라서 해시 함수로 비밀번호를 암호화할 때 키 길이를 일반 대칭 키 암호화 알고리즘보다 두 배로 설정하는 것이 좋다.
NIST에 따르면 해시 값의 길이가 L일 때 역상 저항성 강도는 L이고, 제2 역상 저항성 강도도 키 길이와 비슷한데,
충돌 저항성 강도는 0.5L정도이기 때문에 충돌 저항성이 중요한 상황일 때
해시 함수는 대칭키 알고리즘보다 해시값 길이가 2배 정도 되어야 보안 강도가 비슷해진다.
사용자를 정확하게 인증해야 되는 경우 두 사용자가 동일한 해시값을 갖게 되는 충돌 저항성이 문제가 될 수 있기 때문에 키 길이가 길어야 한다.
해시 함수와 블록 암호화 알고리즘
둘 다 난수처럼 보이는 결과물을 생성하고, 입력 값이 살짝만 바뀌어도 결과물이 완전 달라지는 쇄도 효과를 갖고 있다.
하지만 복호화 할 수 있는 블록 암호화 알고리즘과 달리 해시 함수는 일정한 길이로 바꾸기 때문에
입출력이 일대일 대응을 하지 않아서 복호화할 수 없다.
데이터베이스에 인덱스가 설정된 컬럼을 암호화할 때는 성능 저하를 막기 쉽지 않다.
왜냐하면 접근하기위해 사용되는 인덱스가 암호화되면 순서가 뒤섞여서 인덱스 역할을 하지 못하기 때문이다.
따라서 인덱스가 설정된 컬럼을 암호화할 때는 권한이 없는 사람에게 데이터를 노출해서는 안된다는 안정성 문제와
빠르게 데이터를 꺼내 쓸 수 있어야 한다는 가용성 문제를 함께 고민해야 한다.
암호화된 인덱스 데이터에서 원하는 정보를 찾으려면 암호화된 데이터를 복호화해서 값을 찾아야 하므로 시간이 많이 걸린다.
따라서 암호화된 데이터를 기준으로도 검색이 가능한 데이터의 정렬 순서를 유지하면서 암호화를 수행하는 OPE방식이 있다.
하지만, OPE는 순서가 유지되기 때문에 데이터가 기존 암호화처럼 최대한 흩트려지지 않아서 안전하다고 보기 어렵다.
OPE는 입력 값이 커짐에 따라 암호화된 값도 커지는 일차함수 형태의 정렬 방식이다.
안전한 암호화는 암호문에서 원본 데이터 정보를 얻을 수 있으면 안되는데 OPE는 암호화되어도 데이터의 순서정보를 얻을 수 있기 때문에 암호문 사이의 간격을 최대한 불규칙하게 만들어도 순서 정보가 있기 때문에
어떤 원문에 해당하는 암호문을 알고 있는 선택 평문 공격을 하는 경우 매우 취약하다.
만약 두 값의 암호문을 알고 있다면 그 사이에 있는 암호문은 두 값 사이에 있다고 확정지을 수 있기 때문이다.
따라서 OPE를 사용할 때는 OPE의 안전성이 다른 표준화된 알고리즘들보다 부족할 수 있다는 것을 인지하고,
키를 자주 변경하는 등의 보안 방안을 마련해야 한다.
FPE는 형태를 보존하는 암호화인데, 데이터를 암호화할 때 일반적으로 원본 데이터의 속성과 크기가 달라지는데, 이 과정에서 데이터베이스의 성능이 떨어질 수 있지만, FPE를 이용하면 암호화되어도 형태가 유지되므로 성능 저하를 막을 수 있다.
하지만 데이터의 원래 속성과 크기를 알 수 있기 때문에 안전한 암호화라고 보기 어렵다.
데이터 검색에 유용한 OPE나 암호화로 인한 성능 저하를 최소화할 수 있는 FPE가 안전하지 않아서 무조건 사용하면 안된다고 판단하기 보다는
상황에 따라 보안 강도를 정확히 알고 암호화를 하는 것이 중요하다.
데이터베이스는 데이터베이스 관리시스템(DBMS)과 저장소로 나뉜다.
DBMS는 저장소에서 데이터를 읽고 쓰거나 데이터베이스 사용자 권한을 관리하기 위해 사용한다.
데이터 베이스를 사용하는 어플리케이션은 DMBS로 명령을 내리고, DBMS는 저장소로 명령어를 전달한다.
데이터 베이스 암호화에는 네 가지 방식이 있다.
1. API 방식
2. 플러그인 방식
3. 하이브리드 방식
4. TDE방식
API 방식
어플리케이션 서버에 암호화 모듈을 설치한다.
어플리케이션에서 데이터를 암호화해서 데이터베이스에 넣는 방식이다.
모든 데이터베이스 종류에 적용할 수 있고, 데이터베이스에 부하도 주지 않고,
어플리케이션 기능까지 보호할 수 있기 때문에 어플리케이션을 수정할 수 있을 때 사용하면 효과적이다.
어플리케이션에서 암호화를 해야하는 데이터와 관련된 부분을 모두 수정해야돼서 구축하는데 시간과 비용이 많이 든다.
또한 인덱스가 암호화된 경우는 순서가 섞이게 되므로 암호화된 인덱스를 사용할 수 없다는 단점이 있다.
플러그인 방식
DBMS에 암호화 수행 모듈을 설치한다.
데이터를 컬럼 단위로 암호화할 수 있어서 세부적으로 암호화를 적용할 수 있지만,
암호화와 복호화에 DBMS에 있는 자원을 사용하게 된다.
따라서 정보를 선별해서 암호화하거나 관리할 때 유용하지만 데이터베이스 서버의 성능을 고려해야 한다.
하이브리드 방식
플러그인 방식과 API 방식을 섞어 사용한다.
어플리케이션 서버와 데이터베이스 서버에 모두 암호화 모듈을 설치하고, 상황에 따라 암호화를 어떻게 할 지 결정한다.
잘 활용하면 두 방식의 장점을 얻을 수 있지만, 구조가 복잡하고, 키 관리도 복잡해진다.
또한 적용하기 전에 전체 시스템을 정확하게 분석하고 판단해야 한다.
TDE방식
DBMS가 제공하는 암호화 기능을 이용한다.
데이터베이스 내부에서 DBMS가 저장소에 저장된 데이터를 통째로 암호화한다.
따라서 플러그인 방식처럼 컬럼 단위로 관리하는데에는 한계가 있다.
또한 서로 다른 DBMS는 다른 방식을 사용하기 때문에 여러 종류의 DBMS를 하나의 보안 정책으로 관리할 수 없다.
데이터베이스는 암호화되어야 하지만 동시에 권한이 있는 사용자는 데이터에 접근, 삽입, 삭제를 할 수 있어야 하고, 빠른 속도로 데이터를 제공할 수 있어야 한다.
하지만 데이터에 읽기 권한이 있는 사람은 COA유형의 공격을 할 수 있는 가능성이 있고,
데이터를 삽입, 수정할 수 있는 사람은 CPA유형의 공격을 할 수 있는 가능성이 있기 때문에
키 관리 외에도 데이터에 접근할 수 있는 사람에 대한 보안책도 필요하다.
보안책 중 하나로 직무 분리가 있다.
암호화된 데이터에 접근할 수 있는 사람과 복호화된 데이터에 접근할 수 있는 사람을 분리하는 것이 좋다.
또 다른 보안책은 키를 주기적으로 바꿔서 최대한 키를 유추하기 힘들게 하는 방법이다.
또한 컬럼마다 서로 다른 암호화 키를 사용하고, 행마다 다른 초기화 벡터를 설정해두면 암호문에서 원문을 유추하는 것을 어렵게 만들 수 있다.
암호화된 데이터베이스에 인덱스를 구축할 때는 '암호화된 데이터'와 'OPE 또는 부분 암호화된 인덱스 데이터'를 연결하는 과정이 필요하고, OPE나 부분 암호화는 보안성이 높지 않기 때문에 구축된 인덱스는 권한 관리를 엄격하게 해야한다.
자주 사용되는 공개키 암호 시스템에 대해서도 알아보자.
공개키 암호 시스템은 수신자 지정 암호화와 전자서명에 모두 사용할 수 있다.
RSA알고리즘은 두 기능을 모두 효율적으로 제공하는 최초의 공개 키 알고리즘이다.
하지만 비대칭 수학연산을 해야돼서 연산 난이도가 높아 속도가 느리다.
따라서 실질적 데이터 암호화에는 비밀키 방식을 사용하고, 비밀 키의 분배, 관리나 전자서명(사용자 인증, 부인 방지)를 구현할 때는 공개키 방식을 사용한다.
웹 브라우저로 웹 서버에 접근할 때 암호화 통신을 하는 SSL통신이 이 방식을 사용한다.
웹 브라우저와 웹 서버가 암호화 비밀 키를 공유할 때 공개키 방식을 사용하고,
비밀키로 통신 데이터를 암호화한다.
안전한 서비스를 위해서는 알고리즘과 운영 모드, 키 관리, 키 길이가 모두 중요하다.
또한 보안의 핵심은 공격 비용을 높여서 공격을 해도 이득이 별로 없게 만드는 것이다.
개발을 할 때 기본적인 부분들을 챙겨서 사용자들의 개인정보가 유출되지 않을 수 있는 안전한 서비스를 만들기 위해 노력해야 될 것 같다.