이 페이지에서는 Cloud SQL에서 클라이언트 측 암호화를 구현하는 방법을 설명합니다.
개요
클라이언트 측 암호화는 Cloud SQL에 데이터를 기록하기 전에 데이터를 암호화하는 작업입니다. 애플리케이션만 복호화할 수 있는 방식으로 Cloud SQL 데이터를 암호화할 수 있습니다.
클라이언트 측 암호화를 사용 설정하려면 다음 옵션을 사용하세요.
- Cloud Key Management Service(Cloud KMS)에 저장된 암호화 키를 사용합니다.
- 애플리케이션에 로컬로 저장된 암호화 키를 사용합니다.
이 문서에서는 가장 원활한 키 관리 옵션을 제공하는 첫 번째 옵션을 사용하는 방법을 설명합니다. Google에서는 Cloud KMS에 암호화 키를 만들고 Google의 오픈소스 암호화 라이브러리인 Tink를 사용하여 봉투 암호화를 구현합니다.
클라이언트 측 암호화가 필요한 이유는 무엇인가요?
열 수준에서 Cloud SQL 데이터를 보호하려면 클라이언트측 암호화가 필요합니다. 이름과 신용카드 번호를 포함하는 테이블이 있다고 가정해 보겠습니다. 사용자에게 이 테이블에 대한 액세스 권한을 부여하려고 하지만 사용자가 신용카드 번호를 보는 것은 원하지 않을 수 있습니다. 클라이언트 측 암호화를 사용하여 번호를 암호화할 수 있습니다. 사용자가 Cloud KMS의 암호화 키에 대한 액세스 권한을 부여받지 않는 한 신용카드 정보를 읽을 수 없습니다.
인스턴스 또는 데이터베이스 수준에서 액세스를 제한할 수도 있습니다.
Cloud KMS를 사용하여 키 만들기
Cloud KMS를 사용하면 Google Cloud에서 키를 만들고 관리할 수 있습니다.
Cloud KMS는 다양한 키 유형을 지원합니다. 클라이언트 측 암호화의 경우 대칭 키를 만들어야 합니다.
애플리케이션에 Cloud KMS의 키에 대한 액세스 권한을 부여하려면 애플리케이션에서 사용하는 서비스 계정에 cloudkms.cryptoKeyEncrypterDecrypter 역할을 부여해야 합니다. gcloud CLI에서는 다음 명령어를 사용하여 이 작업을 수행합니다.
gcloud kms keys add-iam-policy-binding key \ --keyring=key-ring \ --location=location \ --member=serviceAccount:[email protected] \ --role=roles/cloudkms.cryptoKeyEncrypterDecrypter
KMS 키를 사용하여 직접 데이터를 암호화할 수 있지만 여기에서는 봉투 암호화라는 더 유연한 솔루션을 사용합니다. 그러면 Cloud Key Management Service API가 지원할 수 있는 최대 메시지 크기인 64KB보다 긴 메시지를 암호화할 수 있습니다.
Cloud KMS 봉투 암호화
봉투 암호화에서 KMS 키는 키 암호화 키(KEK) 역할을 합니다. 즉, 실제 데이터를 암호화하는 데 사용되는 데이터 암호화 키(DEK)를 암호화하는 데 사용됩니다.
Cloud KMS에서 KEK를 만든 후 각 메시지를 암호화하려면 다음을 수행해야 합니다.
- 로컬에서 데이터 암호화 키(DEK)를 생성합니다.
- 이 DEK를 로컬에서 사용하여 메시지를 암호화합니다.
- Cloud KMS를 호출하여 KEK로 DEK를 암호화(래핑)합니다.
- 암호화된 데이터와 래핑된 DEK를 저장합니다.
이 주제에서는 봉투 암호화를 처음부터 구현하는 대신 Tink를 사용합니다.
Tink
Tink는 고수준 암호화 API를 제공하는 다국어 교차 플랫폼 라이브러리입니다. Tink의 봉투 암호화로 데이터를 암호화하려면 Cloud KMS의 KEK를 가리키는 키 URI 및 Tink가 KEK를 사용할 수 있도록 하는 사용자 인증 정보를 Tink에 제공해야 합니다. Tink는 DEK를 생성하고, 데이터를 암호화하고, DEK를 래핑하고, 암호화된 데이터와 래핑된 DEK가 있는 단일 암호문을 반환합니다.
Tink는 AEAD API를 사용하여 C++, 자바, Go, Python에서 봉투 암호화를 지원합니다.
public interface Aead{
  byte[] encrypt(final byte[] plaintext, final byte[] associatedData)
  throws…
  byte[] decrypt(final byte[] ciphertext, final byte[] associatedData)
  throws…
}
일반 메시지/암호문 인수 외에도 암호화 및 복호화 메서드는 추가 관련 데이터를 지원합니다. 이 인수는 암호문을 데이터 조각과 연결하는 데 사용할 수 있습니다. 예를 들어 user-id 필드와 encrypted-medical-history 필드가 있는 데이터베이스가 있다고 가정해 보겠습니다. 이 경우 의료 기록을 암호화할 때 user-id 필드를 연결된 데이터로 사용해야 할 수 있습니다. 이렇게 하면 공격자가 한 사용자의 의료 기록을 다른 사용자로 이동할 수 없습니다. 또한 쿼리를 실행할 때 올바른 데이터 행이 있는지 확인하는 데도 사용됩니다.
샘플
이 섹션에서는 클라이언트 측 암호화를 사용하는 유권자 정보 데이터베이스의 샘플 코드를 살펴봅니다. 샘플 코드는 다음을 수행하는 방법을 보여줍니다.
- 데이터베이스 테이블 및 연결 풀 만들기
- 봉투 암호화를 위한 Tink 설정
- Cloud KMS의 KEK로 Tink의 봉투 암호화를 사용하여 데이터 암호화 및 복호화
시작하기 전에
- 다음 안내에 따라 Cloud SQL 인스턴스를 만듭니다. 생성한 연결 문자열, 데이터베이스 사용자, 데이터베이스 비밀번호를 기록해 둡니다. 
- 안내에 따라 애플리케이션용 데이터베이스를 만듭니다. 데이터베이스 이름을 기록해 둡니다. 
- 안내에 따라 애플리케이션의 KMS 키를 만듭니다. 생성된 키의 리소스 이름을 복사합니다. 
- 안내에 따라 'Cloud SQL 클라이언트' 권한으로 서비스 계정을 만듭니다. 
- 안내에 따라 서비스 계정에 키에 대한 'Cloud KMS CryptoKey 암호화/복호화' 권한을 추가합니다.