RealMySQL 07장 데이터 암호화
암호화 기능은 처음에는 데이터 파일(테이블스페이스)에 대해서만 암호화 기능이 제공됐다. 그러나 MySQL 8.0으로 업그레이드되면서 데이터 파일뿐만 아니라 리두 로그나 언두 로그, 복제를 위한 바이너리 로그 등도 모두 암호화 기능을 지원하기 시작했다. 데이터 암호화 여부는 보안 감사에서 필수적으로 언급되는 부분이며, 핀테크 서비스처럼 중요한 정보를 저장하는 서비스에서는 응용 프로그램에서 암호화한 데이터를 데이터베이스 서버에서 다시 암호화하는 이중 암호화 방법을 선택하기도 한다. 응용 프로그램의 암호화는 주로 중요 정보를 가진 컬럼 단위로 암호화를 수행하며, 데이터베이스 수준에서는 테이블 단위로 암호화를 적용한다.
MySQL 서버의 데이터 암호화
데이터베이스 서버와 디스크 사이의 데이터 읽고 쓰기 지점에서 암호화 또는 복호화를 수행한다. 그래서 MySQL 서버에서 디스크 입출력 이외의 부분에서는 암호화 처리가 전혀 필요치 않다. 즉, MySQL 서버(InnoDB 스토리지 엔진)의 I/O 레이어에서만 데이터의 암호화 및 복호화 과정이 실행되는 것이다.

MySQL 내부와 사용자 입장에서는 아무런 차이가 없기 때문에 이러한 암호화 방식을 가리켜 **TDE(Transparent Data Encryption)**라고 부른다.
2단계 키 관리
지원되는 키 관리 플러그인 책 참조
키링 플러그인은 2단계 키관리 방식을 사용한다.
MySQL 서버의 데이터 암호화는 마스터 키와 테이블스페이스 키라는 두 가지 종류의 키가 있다.
HashiCorp Vault 같은 외부 키 관리 솔루션 또는 디스크의 파일에서 마스터 키를 가져오고 암호화된 테이블이 생성될 때마다 해당 테이블을 위한 임의의 테이블스페이스 키를 발급한다.
그리고 MySQL 서버는 마스터 키를 이용해서 각 테이블의 테이블 스페이스 키를 암호화해서 각 테이블의 데이터 파일 헤더에 저장한다.
데이터를 불러올 때는 마스터 키를 사용해서 복호화한 테이블 스페이스 키를 이용해서 데이터를 복호화한다.
이렇게 설계된 이유는 암호키 변경으로 인한 과도한 시스템 부하를 피하기 위해서이다.
암호화 성능
암호화해도 데이터 크기가 안변해서 메모리 크기는 떨어지지 않지만 버퍼 풀에 있는 데이터가 아닌 디스크에서 데이터를 읽어올 경우 읽기는 3~5배 정도 느리며, 쓰기는 5~6배 정도 느리다.
암호화와 복제
레플리카 서버는 각각의 마스터 키를 할당해서 사용해야 한다.
keyring_file 플러그인 설치
- 책 참조
테이블 암호화
하는 방법
ENCRYPTION='Y' 옵션을 사용해서 테이블을 생성하면 된다.
응용 프로그램 암호화와의 비교
응용 프로그램에서 직접 암호화해서 MySQL 서버에 저장하는 경우도 있는데, 이 경우 저장되는 칼럼의 값이 이미 암호화된 것인지 여부를 MySQL 서버는 인지하지 못한다. 또한 인덱스 기능을 100% 활용할 수 없다.
테이블 스페이스 이동
테이블스페이스 이동을 할 때 임시 마스터 키를 반드시 함께 복사해야 한다.
언두 로그 및 리두 로그 암호화
테이블의 암호화를 적용하더라도 디스크로 저장되는 데이터만 암호화되고 MySQL 서버의 메모리에 존재하는 데이터는 복호화된 평문으로 관리되며, 이 평문 데이터가 테이블의 데이터 파일 이외의 디스크 파일로 기록되는 경우에는 여전히 평문으로 저장된다.
그래서 테이블 암호화를 적용해도 리두 로그나 언두 로그, 그리고 복제를 위한 바이너리 로그에는 평문으로 저장되는 것이다.
MySQL 8.0.16 버전부터는 innodb_undo_log_encrypt 시스템 변수와 innodb_redo_log_encrypt 시스템 변수를 사용해서 리두 로그와 언두 로그를 암호화된 상태로 저장할 수 있게 개선됐다.
리두 로그와 언두 로그 데이터 모두 각각의 테이블스페이스 키로 암호화되고 테이블 스페이스키는 마스터 키로 암호화되는 테이블 암호화 방식과 동일하게 동작한다.
바이너리 로그 암호화
의도적으로 상당히 긴 시간동안 바이너리 로그를 보관하는 서비스도 있고 때론 증분 백업을 위해 바이너리 로그를 보관하기도 하기 때문에 바이너리 로그의 암호화는 상황에 따라 중요도가 높다.
바이너리 로그와 릴레이 로그 파일 암호화 기능은 디스크에 저장된 로그 파일에 대한 암호화만 담당하고 MySQL 서버의 메모리 내부 또는 소스 서버와 레플리카 서버 간의 네트워크 구간에서 로그 데이터를 암호화하지는 않는다.
복제 멤버 간의 네트워크 구간에서도 바이너리 로그를 암호화하고자 한다면 MySQL 복제를 위한 계정이 SSL을 사용하도록 설정하면 된다.
바이너리 로그 암호화 키 관리

바이너리 로그와 릴레이 로그 파일의 데이터는 파일 키로 암호화해서 디스크로 저장하고 파일 키는 바이너리 로그 암호화 키로 암호화해서 바이너리 로그와 릴레이 로그 파일의 헤더에 저장된다. 즉, 바이너리 로그 암호화 키는 테이블 암호화의 마스터 키와 동일한 역할을 하며 파일 키는 바이너리 로그와 릴레이 로그 단위로 자동으로 생성되어 해당 로그 파일의 데이터 암호화에만 사용된다.
mysqlbinlog 도구 활용
바이너리 로그 암호화 키는 MySQL 서버만 가지고 있기 때문에 바이너리 로그 파일의 내용을 볼 수 있는 방법은 MySQL 서버를 통해 가져오는 방법이 유일하다.