클라이언트 측 암호화
v4.2 부터 시작됩니다. MongoDB는 클라이언트 사이드 암호화를 지원합니다. 클라이언트 사이드 암호화를 통해 관리자와 개발자는 다른 MongoDB 암호화 기능을 제공할 뿐만 아니라 특정 데이터 필드를 암호화할 수 있습니다.
필드 수준 암호화를 사용하면 개발자는 서버 사이드 구성이나 지시문 없이 클라이언트 사이드에서 필드를 암호화할 수 있습니다. 클라이언트 사이드 필드 수준 암호화는 서버 관리자를 포함한 권한이 없는 당사자가 암호화된 데이터를 읽을 수 없도록 애플리케이션이 보장해야 하는 워크로드를 지원합니다.
중요
이 가이드 에서는 퀵 스타트 프라이머에 설명된 Subscriber
구현을 사용합니다.
설치
프로젝트에서 필드 수준 암호화를 사용하여 시작하는 데 권장되는 방법은 종속성 관리 시스템을 사용하는 것입니다. 필드 수준 암호화에는 드라이버 외에 추가 패키지가 필요합니다.
참고
Java Reactive Streams 운전자 를 설치하는 방법에 대한 지침은 설치 가이드 를 참조하세요.
libmongocrypt
libmongocrypt
바인딩이 포함된 별도의 JAR 파일이 있습니다.
Maven 을 사용하는 경우 패키지를 관리 하려면 pom.xml
종속성 목록에 다음 항목을 추가하세요.
<dependencies> <dependency> <groupId>org.mongodb</groupId> <artifactId>mongodb-crypt</artifactId> <version>1.2.1</version> </dependency> </dependencies>
Gradle 을 사용하는 경우 패키지를 관리 하려면 종속성 목록에 다음 항목을 추가하세요.
dependencies { implementation 'org.mongodb:mongodb-crypt:1.2.1' }
mongocryptd 구성
libmongocrypt
바인딩을 사용하려면 mongocryptd
데몬/프로세스가 실행 중이어야 합니다. extraOptions
설정에서 mongocryptdURI
를 설정하여 AutoEncryptionSettings
클래스에서 특정 데몬/프로세스 URI를 구성할 수 있습니다.
예시
다음 예시 는 키와 스키마 가 MongoDB 에 이미 생성되었다고 가정하는 샘플 앱 입니다. 이 예시 에서는 로컬 키를 사용하지만 Amazon Web Services/Azure/GCP KMS 를 사용할 수도 있습니다. encryptedField
필드 의 데이터는 삽입 시 자동으로 암호화됨 되고 클라이언트 사이드에서 찾기를 사용할 때 해독됩니다.
이 코드 예시 는 ClientSideEncryptionSimpleTour.java 에서 가져온 것입니다. 파일 을 운전자 소스 코드 리포지토리 Github 에 저장합니다.
import com.mongodb.AutoEncryptionSettings; import com.mongodb.MongoClientSettings; import com.mongodb.reactivestreams.client.MongoClient; import com.mongodb.reactivestreams.client.MongoClients; import com.mongodb.reactivestreams.client.MongoCollection; import org.bson.Document; import java.security.SecureRandom; import java.util.HashMap; import java.util.Map; public class ClientSideEncryptionSimpleTour { public static void main(final String[] args) { // This would have to be the same master key as was used to create the encryption key final byte[] localMasterKey = new byte[96]; new SecureRandom().nextBytes(localMasterKey); Map<String, Map<String, Object>> kmsProviders = new HashMap<String, Map<String, Object>>() {{ put("local", new HashMap<String, Object>() {{ put("key", localMasterKey); }}); }}; String keyVaultNamespace = "admin.datakeys"; AutoEncryptionSettings autoEncryptionSettings = AutoEncryptionSettings.builder() .keyVaultNamespace(keyVaultNamespace) .kmsProviders(kmsProviders) .build(); MongoClientSettings clientSettings = MongoClientSettings.builder() .autoEncryptionSettings(autoEncryptionSettings) .build(); MongoClient mongoClient = MongoClients.create(clientSettings); MongoCollection<Document> collection = mongoClient.getDatabase("test").getCollection("coll"); ObservableSubscriber<Void> successSubscriber = new OperationSubscriber<>(); collection.drop().subscribe(successSubscriber); successSubscriber.await(); successSubscriber = new OperationSubscriber<>(); collection.insertOne(new Document("encryptedField", "123456789")).subscribe(successSubscriber); successSubscriber.await(); ObservableSubscriber<Document> documentSubscriber = new PrintDocumentSubscriber(); collection.find().first().subscribe(documentSubscriber); documentSubscriber.await(); } }
참고
자동 암호화 는 엔터프라이즈 전용 기능 입니다.
다음 예시 에서는 AutoEncryptionSettings
인스턴스 를 구성하여 새 키를 만들고 JSON schema 맵을 설정하다 하는 방법을 보여 줍니다.
이 코드 예제는 ClientSideEncryptionAutoEncryptionSettingsTour.java 파일을 드라이버 소스 코드 Github 리포지토리에 저장합니다.
import com.mongodb.ClientEncryptionSettings; import com.mongodb.ConnectionString; import com.mongodb.client.model.vault.DataKeyOptions; import com.mongodb.client.vault.ClientEncryption; import com.mongodb.client.vault.ClientEncryptions; import org.bson.BsonBinary; import org.bson.BsonDocument; import java.util.Base64; ... String keyVaultNamespace = "admin.datakeys"; ClientEncryptionSettings clientEncryptionSettings = ClientEncryptionSettings.builder() .keyVaultMongoClientSettings(MongoClientSettings.builder() .applyConnectionString(new ConnectionString("mongodb://localhost")) .build()) .keyVaultNamespace(keyVaultNamespace) .kmsProviders(kmsProviders) .build(); ClientEncryption clientEncryption = ClientEncryptions.create(clientEncryptionSettings); BsonBinary dataKeyId = clientEncryption.createDataKey("local", new DataKeyOptions()); final String base64DataKeyId = Base64.getEncoder().encodeToString(dataKeyId.getData()); final String dbName = "test"; final String collName = "coll"; AutoEncryptionSettings autoEncryptionSettings = AutoEncryptionSettings.builder() .keyVaultNamespace(keyVaultNamespace) .kmsProviders(kmsProviders) .schemaMap(new HashMap<String, BsonDocument>() {{ put(dbName + "." + collName, // Need a schema that references the new data key BsonDocument.parse("{" + " properties: {" + " encryptedField: {" + " encrypt: {" + " keyId: [{" + " \"$binary\": {" + " \"base64\": \"" + base64DataKeyId + "\"," + " \"subType\": \"04\"" + " }" + " }]," + " bsonType: \"string\"," + " algorithm: \"AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic\"" + " }" + " }" + " }," + " \"bsonType\": \"object\"" + "}")); }}).build();
명시적 암호화 및 암호 해독
명시적 암호화 및 암호 해독은 MongoDB Community 기능이며 mongocryptd
프로세스를 사용하지 않습니다. 명시적 암호화는 ClientEncryption
클래스에서 제공합니다.
이 코드 예제는 ClientSideEncryptionExplicitEncryptionAndDecryptionTour.java 파일을 드라이버 소스 코드 Github 리포지토리에 저장합니다.
// This would have to be the same master key as was used to create the encryption key final byte[] localMasterKey = new byte[96]; new SecureRandom().nextBytes(localMasterKey); Map<String, Map<String, Object>> kmsProviders = new HashMap<String, Map<String, Object>>() {{ put("local", new HashMap<String, Object>() {{ put("key", localMasterKey); }}); }}; MongoNamespace keyVaultNamespace = new MongoNamespace("encryption.testKeyVault"); MongoClientSettings clientSettings = MongoClientSettings.builder().build(); MongoClient mongoClient = MongoClients.create(clientSettings); // Set up the key vault for this example MongoCollection<Document> keyVaultCollection = mongoClient .getDatabase(keyVaultNamespace.getDatabaseName()) .getCollection(keyVaultNamespace.getCollectionName()); ObservableSubscriber<Void> successSubscriber = new OperationSubscriber<>(); keyVaultCollection.drop().subscribe(successSubscriber); successSubscriber.await(); // Ensure that two data keys cannot share the same keyAltName. ObservableSubscriber<String> indexSubscriber = new OperationSubscriber<>(); keyVaultCollection.createIndex(Indexes.ascending("keyAltNames"), new IndexOptions().unique(true) .partialFilterExpression(Filters.exists("keyAltNames"))) .subscribe(indexSubscriber); indexSubscriber.await(); MongoCollection<Document> collection = mongoClient.getDatabase("test").getCollection("coll"); successSubscriber = new OperationSubscriber<>(); collection.drop().subscribe(successSubscriber); successSubscriber.await(); // Create the ClientEncryption instance ClientEncryptionSettings clientEncryptionSettings = ClientEncryptionSettings.builder() .keyVaultMongoClientSettings(MongoClientSettings.builder() .applyConnectionString(new ConnectionString("mongodb://localhost")) .build()) .keyVaultNamespace(keyVaultNamespace.getFullName()) .kmsProviders(kmsProviders) .build(); ClientEncryption clientEncryption = ClientEncryptions.create(clientEncryptionSettings); BsonBinary dataKeyId = clientEncryption.createDataKey("local", new DataKeyOptions()); // Explicitly encrypt a field BsonBinary encryptedFieldValue = clientEncryption.encrypt(new BsonString("123456789"), new EncryptOptions("AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic").keyId(dataKeyId)); ObservableSubscriber<InsertOneResult> insertOneSubscriber = new OperationSubscriber<>(); collection.insertOne(new Document("encryptedField", encryptedFieldValue)) .subscribe(insertOneSubscriber); insertOneSubscriber.await(); ObservableSubscriber<Document> documentSubscriber = new OperationSubscriber<>(); collection.find().first().subscribe(documentSubscriber); Document doc = documentSubscriber.get().get(0); System.out.println(doc.toJson()); // Explicitly decrypt the field System.out.println( clientEncryption.decrypt(new BsonBinary(doc.get("encryptedField", Binary.class).getData())) );
명시적 암호화 및 자동 암호 해독
자동 암호화 에는 MongoDB 4.2 엔터프라이즈 또는 MongoDB 4.2 이 필요합니다. Atlas cluster, 모든 사용자에 대해 자동 암호 해독이 지원됩니다. 자동 자동 암호화 해독을 구성하려면 bypassAutoEncryption(true)
를 설정하다 합니다.
이 코드 예제는 ClientSideEncryptionExplicitEncryptionOnlyTour.java 에서 가져온 것입니다. 파일을 드라이버 소스 코드 Github 리포지토리에 저장합니다.
... MongoClientSettings clientSettings = MongoClientSettings.builder() .autoEncryptionSettings(AutoEncryptionSettings.builder() .keyVaultNamespace(keyVaultNamespace.getFullName()) .kmsProviders(kmsProviders) .bypassAutoEncryption(true) .build()) .build(); MongoClient mongoClient = MongoClients.create(clientSettings); ... // Explicitly encrypt a field BsonBinary encryptedFieldValue = clientEncryption.encrypt(new BsonString("123456789"), new EncryptOptions("AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic").keyId(dataKeyId)); ObservableSubscriber<InsertOneResult> insertOneSubscriber = new OperationSubscriber<>(); collection.insertOne(new Document("encryptedField", encryptedFieldValue)) .subscribe(insertOneSubscriber); insertOneSubscriber.await(); ObservableSubscriber<Document> documentSubscriber = new OperationSubscriber<>(); collection.find().first().subscribe(documentSubscriber); Document doc = documentSubscriber.get().get(0); System.out.println(doc.toJson());