클라이언트 측 암호화
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에 이미 생성되었다고 가정하는 샘플 앱입니다. 이 예제에서는 로컬 키를 사용하지만 AWS/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());