프로그램을 짜다보면 인코딩/디코딩과 암호화/복호화를 할 일이 매우 많다
근데 우리 눈으로 보기에는 AzmS192Mdks01Aakd9xl1와 같이 알아보지도 못할 이상한 문자열만 잔뜩 늘어서 있는 것 처럼 보여서 그게 그거 아닌가 라는 생각이 들기도 한다
인코딩과 암호화 모두 정해진 알고리즘에 따라 일정한 코드를 생성하는 것이라 더더욱 그렇게 느껴질 만도 하다
그럼 인코딩/디코딩과 암호화/복호화의 차이는 무엇일까?
인코딩은 심볼을 코드로 바꾸는 작업을 말한다. 디코딩은 반대로 코드를 심볼로 바꾸는 작업이다
이 인코딩과 암호화의 가장 결정적인 차이는 인코딩은 누가 못알아보게 만들려는 처리가 아니라 사용성을 좋게하기 위한 가공이다
단순하게 사용성을 좋게하기 위한 가공일뿐이라서 인코딩한 값은 당장은 알아볼 수 없을지언정 디코딩해서 원래대로 되돌린다면 알아보기가 쉽다. 더군다나 누구던지 인코딩/디코딩 알고리즘에 따라 데이터만 변환하면 되니 인코딩한 값을 누구라도 볼 수 있다
즉 인코딩의 목적은 사용성의 증대와 정보의 호환성이라 볼 수 있다
예를 들어서 이미지를 전송한다고 가정해보자. 만일 이미지를 별다른 가공 없이 전송하려 하면 충돌이나 알아볼 수 없는 값, 읽기 힘든 구조로 인해 사용하기가 제한적인 상황이 될 수 밖에 없다
그런데 만약 이걸 일정한 규칙에 따라 문자열로 변한한다면 어떨까?
문자열은 범용적으로 쓰이므로 전송이나 사용성 등이 좋아질 것이다
이렇게 인코딩된 데이터를 받았다면 다시 인코딩한 규칙을 따라 원래 데이터로 디코딩해주면 된다
인코딩/디코딩의 가장 대표적인 예로는 우리가 흔히 쓰는 UTF-8이나 Base64등이 있다
암호화/복호화는 인코딩과는 반대로 사용성의 개선보다는 제3자가 내가 보내는 데이터의 내용을 알아볼 수 없게 하기위한 처리다
그렇기 때문에 기본적으로 암호화와 복호화하는 과정에 '키(Key)'라 불리는 특수한 데이터가 필요하며, 이 키를 가지고 있지 않으면 해당 암호의 평문을 볼 수가 없다
암호화는 크게 두 가지 종류로 나누어 진다
단방향 암호화란 암호화만 가능하고 복호화가 불가능한 암호화 방식을 말한다. 일반적으로 해시함수를 많이 이용한다
설명만 들어서는 도대체 어디다 써먹는건지 감이 안잡히겠지만, 대표적으로 유저들의 비밀번호를 단방향 암호화를 통해 암호화한 후 저장한다(이는 보안성이 좋기 때문이기도 하지만 우리나라의 경우 법으로 비밀번호 등의 민감한 정보는 반드시 단방향 암호화를 통해 저장하도록 강제되어있다)
복호화가 불가능하다는 특징 덕분에 각종 비밀번호같이 유출사고가 일어나도 남이 알아볼 수 없어야 하는 데이터를 저장하는데 사용한다
그러나 완벽한 보안을 자랑하는 방식은 아닌데 레인보우 테이블이라는 일종의 브루트 포스나 다름없는 존재 때문이다
레인보우 테이블이란 해시함수를 통해 변환될 수 있는 모든 해시값을 저장해놓은 표이다. 설명만 들어도 대단히 무식하면서도 확실할 것 같은 포스를 풍긴다
레인보우 테이블 때문에 실제로 해시값을 그대로 쓰는 경우는 없고 보통은 원래의 평문에다 소금(salt)이라 불리는 추가 데이터를 붙이거나, 여러번 해시함수를 통하게 만드는 등의 방법을 써서 레인보우 테이블을 무력화 시키는 방법을 쓴다
물론 이런 처리 방법만 믿고 유추하기 쉬운 비밀번호를 썼다가는 각종 암호화처리 과정이 무색하게 손쉽게 해커에게 계정을 탈취당하는 불상사가 벌어질 수도 있으니 비밀번호는 어려운 것을 쓰도록 하자
어디까지나 레인보우 테이블이란 수단을 무력화 시킬 수 있을 뿐이지 진짜 브루트 포스 앞에서는 답이 없다. 특히 브루트 포스 공격 시 쉬운 비밀번호 부터 대입해본다는 사실을 생각하면 더더욱 그렇다
양방향 암호화는 단방향 암호화와 달리 암호화와 복호화가 모두 가능한 방식을 말한다
우리가 생각하는 아주 일반적인 방식의 암호화로 특정 키 값을 가지고 암호화 알고리즘에 따라 암호화 한 뒤, 키를 가진 사람이 복호화 알고리즘에 따라 복호화하여 암호화하기 전의 평문을 볼 수 있다
여러 정보들이 양방향 암호화 알고리즘을 통해 암호화되는데 이 양방향 암호화도 두 가지로 나누어진다
대칭 암호화 알고리즘이란 암호화와 복호화에 쓰이는 키가 같은 암호화 알고리즘을 말한다. 대표적으로 AES, SEED 등의 방식이 있다
송신자가 특정 키 값으로 평문을 암호화해서 보내면 수신자 역시 같은 키 값으로 복호화해서 평문을 볼 수 있다
대칭키 암호화 알고리즘은 암호화/복호화에 쓰이는 키가 동일하고, 키 값의 사이즈가 작아 연산량이 적고 빠르게 암호화/복호화가 진행된다는 장점이 있다
하지만 암호화/복호화에 쓰이는 키 값이 같은 만큼 키를 중간에 탈취당하거나, 브루트 포스 등의 방법으로 공격자가 키 값을 알아내게 될 경우 별 다른 수 없이 평문이 노출되게 되어 보안에 취약하다는 단점이 있다
비대칭 암호화 알고리즘이란 암호화와 복호화에 쓰이는 키가 다른 암호화 알고리즘을 말한다. 대표적으로 RSA가 있다
비대칭 암호화 알고리즘에선 일반적으로 공개키라 불리는 누구나 사용가능한 키와 개인키라고 해서 특정 사용자만이 보유하고 있는 키로 나뉘게 되는데, 일반적으로 송신자는 누구에게나 개방된 공개키를 이용해 암호화를 진행하고 수신자는 자신이 가진 개인키를 이용해 복호화를 진행해 평문을 볼 수 있다
물론 일반적으로 그렇다는 것이고 실제로는 개인키로 암호화해서 공개키로 복호화할 수 있는 등 딱히 정해진 제약이 존재하진 않는다. 물론 공개키로 암호화해서 공개키로 복화하는 등의 짓은 불가능하다
비대칭 암호화 알고리즘은 암호화와 복호화에 쓰이는 키가 다른 만큼 제3자가 공개키를 알고 있더라도 이를 복호화하기 위한 개인키를 알아내기는 쉽지 않아 보안성이 좋다는 장점이 있다
하지만 반대급부로 공개키와 개인키의 사이즈가 커서 데이터양이 많아지고, 해당 암호화 방식 자체가 연산량이 많기 때문에 속도가 느리다는 단점이 있다
물론 이 질문에는 정해진 답이 없다. 자신의 목적에 맞게 적당한 알고리즘을 골라서 사용하면 된다