Docs Menu

클라이언트 측 암호화

v4.2 부터 시작됩니다. MongoDB는 클라이언트 사이드 암호화를 지원합니다. 클라이언트 사이드 암호화를 통해 관리자와 개발자는 다른 MongoDB 암호화 기능을 제공할 뿐만 아니라 특정 데이터 필드를 암호화할 수 있습니다.

필드 수준 암호화를 사용하면 개발자는 서버 사이드 구성이나 지시문 없이 클라이언트 사이드에서 필드를 암호화할 수 있습니다. 클라이언트 사이드 필드 수준 암호화는 서버 관리자를 포함한 권한이 없는 당사자가 암호화된 데이터를 읽을 수 없도록 애플리케이션이 보장해야 하는 워크로드를 지원합니다.

중요

이 가이드 에서는 퀵 스타트 프라이머에 설명된 Subscriber 구현을 사용합니다.

프로젝트에서 필드 수준 암호화를 사용하여 시작하는 데 권장되는 방법은 종속성 관리 시스템을 사용하는 것입니다. 필드 수준 암호화에는 드라이버 외에 추가 패키지가 필요합니다.

참고

Java Reactive Streams 운전자 를 설치하는 방법에 대한 지침은 설치 가이드 를 참조하세요.

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'
}

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());