* 들어가기에 앞서
이전 포스팅에 이어서 작성하는 컬럼 암호화 입니다. 이전 포스팅에서 기본적인 암호화를 설명해 드렸습니다. 하지만 기본적인 내용들로는 완전한 암호화를 할 수 없음을 아셨을 겁니다. 더불어 이 포스팅을 작성하는 이유는 HEX 가 왜 쓰이는지에 대한 의문점으로부터 시작했습니다.
포스팅을 시작하기 전에 간단히 다시한번 짚고 넘어가도록 하겠습니다.
첫째 AES_ENCRYPT 에 들어가는 key 값이 고정일 경우 노출이 될 경우 전부 데이터 복호화가 가능
둘째 보완하기 위해 사용자 암호를 key값으로 설정. 하지만 사용자 실수 또는 뜻하지 않게 유출이 되었을 경우 사용자 1회에 대해 유출 및 암호해독을 위해 사용자 암호길이는 작은 편에 속함
셋째 사용자 암호와 개발자가 제공한 암호문을 합쳐서 key값으로 설정. 문자열 길이가 늘어나 해독에 시간이 걸리지만 레인보우 테이블에 속해 있을 확률이 높아 언젠간 해독이 가능
이정도로 요약이 가능합니다.
추가로 전 포스팅에서 뺀 HEX를 왜 쓰는지 해시함수를 왜 쓰는지에 대해 설명하도록 하겠습니다.
* 레인보우 테이블
레인보우 테이블은 간단히 key값을 풀기 위해 모든 경우의 수를 모두 저장해 놓은 테이블 입니다. 검색 결과로는 약 100Gbyte 이상이 된다고 합니다. 더군다나 컴퓨터의 발전으로 SHA-1 해시 함수도 빠르게 해석이 가능합니다.
* 암호화: 문자 + 문자 = 솔팅
가장 이상적이었던 세번째 ‘사용자 암호’ 와 ‘개발자가 제공한 암호문’ 에 대해서는 레인보우 테이블에 취약하다고 했습니다. 솔팅은 아직도 유효한 암호화 방식 중 하나입니다. 이 방식의 이름은 솔팅 이라고 부릅니다. 먼저 솔팅 이란 용어부터 설명 드리도록 하겠습니다. 솔팅은 소금(솔트) 에서 소금을 치다 라고 하여 솔팅 이라고 부릅니다.
사용자 암호(원재료) + 개발자가 제공한 암호문(소금) = 솔팅
으로 압축해서 설명을 드릴 수 있습니다.
* 솔팅을 발전시키자
솔팅에 단점으로 지적되는 것이 ‘개발자가 제공한 고정된 암호문’ 입니다. 보통 이렇게 구현한다고 하면 간단히 Java 에서는 String(Builder) 로 단순히 합쳐 제공되거나 조금 더 생각한다면 암호문을 따로 둬서 읽은 다음에 적용시킬 것입니다. 특히나 Java 같은 경우 jar 파일이나 따로 빼낸 암호문이 유출된다면 바로 *들어가기 앞서 에 설명된 두번째 문제에 바로 직면하게 됩니다.
그래서 생겨난 것이 임의의 2차 암호를 랜덤하게 하나 더 생성하자 입니다.
* 2차 암호를 랜덤하게 하나 더 생성하는 것은 추후에 이 내용들을 종합적으로 구현하는 포스팅에서 설명하도록 하겠습니다.
1.1 MariaDB에서의 해시 함수(HEX 쓰는 이유)
이제야 본문으로 진입했습니다!.
여타 다른 블로그 게시글에 보면 암호화를 할 때
HEX(AES_ENCRYPT('data', SHA2('encrypt-key',512)))
앞에 HEX을 사용하니 해결만 되었다 라고만 적혀 있는 것이 대다수 였습니다.
HEX를 사용하는데 먼저 MariaDB(MySQL) 에서의 해시함수가 어떻게 작동이 되는지 이해가 필요합니다.
해시 함수 MD5(), SHA1(), SHA2() 는 ASCII 코드의 문자열을 반환합니다.
또한 시스템에 영향을 받지 않기 때문에 시스템 문자셋이 UTF-8로 되어있어도 ASCII 로 고정입니다.
그러기 때문에 문자셋을 바꾸기 위해 1차적으로 하는 일이 HEX(16진수)로 변환하는 작업입니다.
그럼 바로 변경해야 할 것은 전체적인 16진수(HEX) 변환이 아닌 SHA2() 함수에 대해서만 이라고 생각합니다.
AES_ENCRYPT('data', HEX(SHA2('encrypt-key',512)))
1.2 해시 함수를 왜 쓸까?
이전 포스팅에서 AES_ENCRYPT(‘data’,’key’) 로 기본 구문을 적어 두었습니다. Key 값으로는 암호 문이 들어가야 하나 상관없어 보이는 해시를 사용하고 있습니다.
AES_ENCRYPT('data', HEX(SHA2('encrypt-key',512)))
해시는 보통 ‘무결성’에 사용되어지며 같은 문자열에는 같은 값이 생성이 됩니다. 하지만 다시 짚고 넘어가야 할 것은 SHA 나 MD5는 해시 암호라는 것입니다.
제가 해시에 대한 두가지 의미를 설명 드린 이유는 이 두가지를 같이 사용되기 때문에 적었습니다.
첫째 무결성
둘째 같은 값에는 같은 해시 값이 생성
종합해서 설명해 드리자면 무결성은 이 값이 잘 맞는지에 대한 확인 작업입니다. 파일을 받고 해시를 검사하는 경우를 예로 들을 수 있습니다. 이것을 둘째의 이유와 종합해서 설명 드리자면 사용자가 입력한 암호를 확인할 때 원시값과 원시값을 비교하는 경우가 가장 기본적인 비교법입니다. 하지만 DB에서 원시 값을 어플리케이션으로 던져준다면 암호는 통하는 사이에 그대로 노출이 되어집니다. 그렇다면 DB에서 해시로 암호화가 된 값을 어플리케이션에게 던져주고 어플리케이션에서 사용자에게서 받은 원시값을 동일한 해시 암호로 바꿔서 비교를 한다면 좀더 안정적으로 비교가 가능해 지기 때문에 쓰입니다.
1.3 암호화에 추천되는 타입은 BLOB?
MySQL 공식문서를 참고하면 많은 암호화 함수의 암호문에는 임의의 byte값이 들어있는 경우가 있다고 합니다. 그러다보니 BLOB이 추천한다고 적혀 있었습니다. 이와 다르게 VARCHAR나 CHAR, TEXT 같은 경우는 2진수로 된 데이터 타입이 아닌 문자열로 이루어진 데이터 타입이라고 합니다. 또한 이러한 문자열로 이루어진 데이터 타입은 문자셋과 공백 등으로 인해 잠재적인 위험이 있다고 합니다.
하지만 이미 TEXT나 VARCHAR 형태로 되어있는 곳은 1.1 항목에서 처음에 소개된 16진수로 변환하는 함수인 HEX를 제일 앞에 붙여 사용하면 됩니다.
HEX(AES_ENCRYPT('data', SHA2('encrypt-key',512)))
* 마치면서
늦게까지 작성한 포스팅에 HEX 를 왜 쓰지부터 시작한 것이 약 2개월에 걸쳐 제 나름대로의 결론이 난 공부였습니다. 이걸로 인해 블로그겸 포트폴리오도 개발 진행이 많이 늦어졌습니다. 아무래도 실제 적용을 하려다보니 많은 공부가 필요해서 자꾸만 늦어지는 듯 합니다.
조만간 java로 솔팅을 하면서 로그인을 하는 포스팅으로 돌아오도록 하겠습니다.
* 레퍼런스
Encryption, Hashing and Compression Functions (mariadb.com/kb/en/mariadb/encryption-hashing-and-compression-functions/)
12.13 Encryption and Compression Functions (dev.mysql.com/doc/refman/5.7/en/encryption-functions.html)
비밀번호 해시에 소금치기 - 바르게 쓰기 (starplatina.tistory.com/entry/비밀번호-해시에-소금치기-바르게-쓰기)
'DB > MariaDB' 카테고리의 다른 글
[MariaDB] 컬럼 암호화(Encrypt) (0) | 2017.05.18 |
---|---|
[MariaDB] CentOS에서 TokuDB 사용하기 (0) | 2017.04.06 |
댓글