암호화폐 파쇄 샘플 앱 MongoDB의 클라이언트 측 필드 레벨 암호화 (CSFLE) 를 사용하여 민감한 데이터를 제거하는 절차를 강화하는 방법을 보여줍니다.
샘플 애플리케이션 정보
잊힐 권리라고도 하는 삭제 권리는 GDPR 과 같은 법률 및 규정에 따라 개인에게 부여되는 권리입니다. 즉, 개인의 개인 데이터를 저장하는 회사는 요청 시 해당 데이터를 삭제 수 있어야 합니다. 데이터는 여러 시스템에 분산될 수 있으므로 이러한 회사에서 데이터를 모든 위치에서 식별하고 제거 것은 기술적으로 어려울 수 있습니다. 올바르게 실행하더라도 삭제된 데이터가 향후 백업에서 복원되어 법적 및 재정적 위험을 초래할 수 있는 위험이 있습니다.
경고
MongoDB 이 문서에 설명된 솔루션과 기술이 삭제 권리와 관련된 모든 규제 요건을 충족한다는 보장 제공하지 않습니다. 조직 GDPR 과 같은 규제 요구 사항을 준수하기 위해 적절하고 충분한 조치를 결정해야 합니다.
암호화폐 파쇄 샘플 애플리케이션 삭제 권한을 구현 한 가지 방법을 보여줍니다. 데모 애플리케이션 사용자 추가, 로그인, 데이터 입력을 위한 프런트 엔드가 있는 Python (Flask) 웹 애플리케이션 입니다. 또한 암호화폐 파쇄 기능을 보여주는 "관리자" 페이지도 포함되어 있습니다.
암호화폐 파쇄란 무엇인가요?
암호화 삭제라고도 하는 암호화폐 파쇄는 암호화됨 데이터를 파기하는 대신 데이터를 해독하는 데 필요한 암호화 키를 파기하는 데이터 파기 기술입니다. 이로 인해 데이터를 해독할 수 없게 됩니다.
예시 들어 여러 사용자에 대한 데이터를 저장한다고 가정해 보겠습니다. 먼저 각 사용자에게 고유한 DEK 제공하고 이를 해당 고객에 매핑합니다.
다이어그램에서 "사용자 A"와 "사용자 B"는 각각 키 저장 에 고유한 DEK를 가집니다. 각 키는 해당 사용자의 데이터를 암호화하거나 해독하는 데 사용됩니다.

사용자 B의 모든 데이터를 제거 한다고 가정해 보겠습니다. 사용자 B의 DEK를 제거 하면 더 이상 해당 데이터를 해독할 수 없습니다. 데이터 저장소의 모든 내용은 해독할 수 없는 암호 텍스트가 됩니다. 사용자 A의 DEK가 여전히 존재하므로 데이터는 영향을 받지 않습니다.

CSFLE란 무엇인가요?
애플리케이션은 CSFLE를 사용하여 데이터를 서버로 전송하기 전에 문서의 민감한 필드를 암호화할 수 있습니다. 메모리의 데이터베이스 에서 데이터를 사용하는 경우에도 일반 텍스트로 저장되지 않습니다. 데이터베이스 클라이언트 만 해독할 수 있는 암호화됨 데이터를 저장하고 전송합니다.
CSFLE는 최상위 엔벨로프 키( ' 고객 마스터 키' 또는 CMK 라고도 함)로 자체 암호화됨 데이터 키로 일반 텍스트 데이터를 암호화하는 방식인 봉투 암호화 사용합니다.

암호화 키 관리(Encryption Key Management)
CMK는 일반적으로 KMS (KMS )에서 managed . CSFLE는 Amazon Web Services (Amazon Web Services), Azure Key Vault, Google Cloud Platform (GCP), KMIP 표준을 지원 키 저장소(예: Hashicorp Keyvault) 등 여러 KMS를 지원합니다. 샘플 앱 Amazon Web Services KMS 로 사용합니다.
자동 및 명시적 암호화
CSFLE는 자동 또는 명시적 모드 또는 이 둘의 조합으로 사용할 수 있습니다. 샘플 앱 명시적 암호화 사용합니다.
자동 암호화 사용하면 정의된 암호화 스키마 기반으로 암호화됨 읽기 및 쓰기 (write) 작업을 수행할 수 있으므로 필드를 암호화하거나 해독하는 방법을 지정하는 애플리케이션 코드가 필요하지 않습니다.
명시적 암호화 사용하면 MongoDB 드라이버의 암호화 라이브러리를 사용하여 애플리케이션 의 필드를 수동으로 암호화하거나 해독할 수 있습니다.
샘플 앱 안내
샘플 앱 명시적 암호화 와 함께 CSFLE 를 사용하고 Amazon Web Services KMS 로 사용합니다.

사용자 추가
앱 app.mongodb_encryption_client
객체 초기화하여 ClientEncryption
클래스를 인스턴스화합니다. 이 암호화 클라이언트 DEK를 생성한 다음 Amazon Web Services KMS 에서 CMK 사용하여 암호화하는 작업을 담당합니다.
사용자가 등록하면 애플리케이션 create_data_key
메서드를 사용하여 고유한 DEK를 생성한 다음 data_key_id
을 반환합니다.
# flaskapp/db_queries.py def create_key(userId): data_key_id = \app.mongodb_encryption_client.create_data_key (kms_provider, master_key, key_alt_names=[userId]) return data_key_id
그런 다음 앱 사용자 정보를 저장할 때 이 메서드를 사용합니다.
# flaskapp/user.py def save(self): dek_id = db_queries.create_key(self.username) result = app.mongodb[db_name].user.insert_one( { "username": self.username, "password_hash": self.password_hash, "dek_id": dek_id, "createdAt": datetime.now(), } ) if result: self.id = result.inserted_id return True else: return False
데이터 추가 및 암호화
등록이 완료되면 사용자는 로그인 입력 양식을 통해 키-값 쌍으로 데이터를 입력할 수 있습니다.

데이터베이스 이 데이터를 'data'라는 이름의 MongoDB 컬렉션 에 저장하며, 각 문서 에는 사용자 이름 과 키-값 쌍이 포함됩니다.
{ "name": "shoe size", "value": "10", "username": "tom" }
샘플 앱 value
및 username
필드를 암호화하지만 name
는 암호화하지 않습니다. 앱 사용자의 DEK와 지정된 암호화 알고리즘 사용하여 필드를 암호화합니다.
# flaskapp/db_queries.py # Fields to encrypt, and the algorithm to encrypt them with ENCRYPTED_FIELDS = { # Deterministic encryption for username, because we need to search on it "username": Algorithm.AEAD_AES_256_CBC_HMAC_SHA_512_Deterministic, # Random encryption for value, as we don't need to search on it "value": Algorithm.AEAD_AES_256_CBC_HMAC_SHA_512_Random, }
insert_data
함수는 암호화되지 않은 문서 가져와서 ENCRYPTED_FIELDS
루프를 통해 암호화합니다.
# flaskapp/db_queries.py def insert_data(document): document["username"] = current_user.username # Loop over the field names (and associated algorithm) we want to encrypt for field, algo in ENCRYPTED_FIELDS.items(): # if the field exists in the document, encrypt it if document.get(field): document[field] = encrypt_field(document[field], algo) # Insert document (now with encrypted fields) to the data collection app.data_collection.insert_one(document)
지정된 필드 문서 에 있는 경우 함수는 encrypt_field
를 호출하여 지정된 알고리즘 사용하여 문서를 암호화합니다.
# flaskapp/db_queries.py # Encrypt a single field with the given algorithm def encrypt_field(field, algorithm): try: field = app.mongodb_encryption_client.encrypt( field, algorithm, key_alt_name=current_user.username, ) return field except pymongo.errors.EncryptionError as ex: # Catch this error in case the DEK doesn't exist. Log a warning and # re-raise the exception if "not all keys requested were satisfied" in ex._message: app.logger.warn( f"Encryption failed: could not find data encryption key for user: {current_user.username}" ) raise ex
데이터를 추가한 후 웹 앱 에서 해당 데이터를 볼 수 있습니다.

암호화 키 삭제
이제 DEK를 삭제 하면 어떻게 되는지 살펴보겠습니다. 샘플 앱 관리자 페이지에서 이 작업을 수행하며, 이 페이지는 키를 관리 할 권한 부여 있는 개인으로만 제한되어야 합니다.

'데이터 암호화 키 삭제' 옵션은 DEK를 제거하지만 사용자의 암호화됨 데이터는 그대로 유지합니다. 그 후에는 애플리케이션 에서 더 이상 데이터를 해독할 수 없습니다. 로그인한 사용자의 데이터를 조회 하려고 하면 오류가 발생합니다.

참고
DEK를 삭제한 후에도 애플리케이션 최대 60 초 후 캐시 만료될 때까지 데이터를 해독하고 표시할 수 있습니다.
그러나 실제로 데이터베이스 에 남아 있는 것은 무엇입니까? 관리자 페이지로 돌아가서 Fetch data for all users을 클릭하여 정보를 검토 할 수 있습니다. 애플리케이션 이 데이터를 해독할 수 없는 경우 이 보기에서는 예외가 발생하지 않습니다. 대신 데이터베이스 에 저장된 내용을 정확히 표시합니다.
실제로 사용자 데이터를 삭제하지 않았더라도 데이터 암호화 키 더 이상 존재하지 않기 때문에 애플리케이션 암호화됨 필드 ' 사용자 이름' 및 'value'에 대한 암호 텍스트만 표시할 수 있습니다.

다음은 이 데이터를 가져오는 데 사용되는 코드입니다. 앞서 설명한 encrypt
메서드와 유사한 로직을 사용합니다. 애플리케이션 필터 없이 find
작업을 실행하여 모든 데이터를 조회 다음 ENCRYPTED_FIELDS
딕셔너리를 반복하여 필드를 해독합니다.
# flaskapp/db_queries.py def fetch_all_data_unencrypted(decrypt=False): results = list(app.data_collection.find()) if decrypt: for field in ENCRYPTED_FIELDS.keys(): for result in results: if result.get(field): result[field], result["encryption_succeeded"] = decrypt_field(result[field]) return results
해독할 각 필드 에 대해 decrypt_field
함수가 호출되지만, 이 경우 애플리케이션 DEK 누락으로 인해 암호를 성공적으로 해독할 수 없는 경우 오류를 포착합니다.
# flaskapp/db_queries.py # Try to decrypt a field, returning a tuple of (value, status). This will be either (decrypted_value, True), or (raw_cipher_text, False) if we couldn't decrypt def decrypt_field(field): try: # We don't need to pass the DEK or algorithm to decrypt a field field = app.mongodb_encryption_client.decrypt(field) return field, True # Catch this error in case the DEK doesn't exist. except pymongo.errors.EncryptionError as ex: if "not all keys requested were satisfied" in ex._message: app.logger.warn( "Decryption failed: could not find data encryption key to decrypt the record." ) # If we can't decrypt due to missing DEK, return the "raw" value. return field, False raise ex
mongosh 셸 사용하여 데이터베이스 에서 직접 확인할 수 있는 항목이 없음을 증명할 수도 있습니다.

이 점 에서도 사용자의 암호화됨 데이터는 여전히 존재합니다. 누군가 데이터베이스 백업 에서 암호화 키 복원하여 액세스 할 수 있습니다.
이를 방지하기 위해 샘플 애플리케이션 두 개의 개별 데이터베이스 클러스터를 사용합니다: 하나는 데이터 저장용이고 다른 하나는 DEK("키 볼트") 저장용입니다. 별도의 클러스터를 사용하면 애플리케이션 데이터와 키 볼트에 대한 백업 복원이 분리됩니다. 백업 에서 데이터 클러스터 복원해도 키 볼트 클러스터 에서 삭제된 DEK는 복원 않습니다.
결론
클라이언트 측 필드 레벨 암호화 특정 데이터를 '잊는' 작업 간소화할 수 있습니다. 데이터 키를 삭제하면 다양한 데이터베이스, 컬렉션, 백업 및 로그에 존재하는 데이터를 효과적으로 삭제할 수 있습니다.
프로덕션 애플리케이션 에서는 암호화 키 제거하는 것 외에도 암호화됨 데이터 자체를 삭제 수도 있습니다. 이 '심층 방어' 접근 방식은 데이터가 실제로 분실되었는지 확인하는 데 도움이 됩니다. 데이터 삭제 외에도 암호화폐 파쇄를 구현하면 삭제 작업이 실패하거나 삭제되어야 하는 데이터가 포함되지 않을 경우의 영향 최소화할 수 있습니다.