Docs Menu
Docs Home
/
MongoDBマニュアル
/ / / / /

明示的な暗号化

項目一覧

  • Overview
  • 明示的な暗号化の使用
  • ClientEncryption インスタンスの作成
  • 読み取り操作と書込み操作におけるフィールドの暗号化
  • 手動復号化
  • 自動復号化
  • MongoClient インスタンスの作成
  • ClientEncryption インスタンスの作成
  • フィールドの暗号化と挿入
  • フィールドの取得と復号化
  • サーバー側のフィールドレベル暗号化の強制
  • 詳細

明示的な暗号化により、セキュリティをきめ細やかに制御できますが、コレクションの構成や MongoDB ドライバー のコード記述の複雑さは増します。 明示的な暗号化では、データベースで実行する各操作に対してドキュメント内のフィールドを暗号化する方法を指定し、このロジックをアプリケーション全体に含めます。

次の MongoDB 製品で明示的な暗号化が利用できます。

  • MongoDB Community Server

  • MongoDB Enterprise Advanced

  • MongoDB Atlas

明示的な暗号化を使用するには、CSFLE 対応のアプリケーションで次のアクションを実行する必要があります。

  • ClientEncryption インスタンスの作成

  • 読み取り操作と書込み操作におけるフィールドの暗号化

  • ドキュメントのフィールドを手動または自動で復号化

明示的な暗号化を使用するには、 ClientEncryptionインスタンスを作成する必要があります。 ClientEncryptionmongoshはドライバー全体で使用される抽象化であり、Key Vault コレクションと明示的な暗号化に関係する KMS 操作をカプセル化する とします。

ClientEncryptionインスタンスを作成するには、次の情報を指定する必要があります。

  • キーヴォールト コレクションへのアクセス権を持つMongoClientインスタンス

  • キーヴォールト コレクションの名前空間

  • カスタマー マスター キーをホストするKMSプロバイダーへのアクセス用に構成されたkmsProvidersオブジェクト

その他のClientEncryptionオプションについては、CSFLE 用の MongoClient オプションを参照してください。

ClientEncryptionインスタンスの作成方法を示すコード スニペットは、このガイドのセクションを参照してください。

読み取りおよび書込み操作を実行する前に、アプリケーション全体で読み取りおよび書込み操作を更新し、アプリケーションがフィールドを暗号化する必要があります。

フィールドを暗号化するには、 ClientEncryptionインスタンスのencryptメソッドを使用します。

encryptメソッドの使用方法を示すコード スニペットは、このガイドのセクションを参照してください。

明示的な暗号化を使用する場合、暗号化されたフィールドを手動または自動で復号化できます。

フィールドを手動で復号化するには、 ClientEncryptionインスタンスのdecryptメソッドを使用します。

decryptメソッドの使用方法を示すコード スニペットは、このガイドのセクションを参照してください。

フィールドを自動的に復号化するには、 MongoClientインスタンスを次のように構成します。

  • キーヴォールトコレクションを指定する

  • kmsProvidersオブジェクトを指定する

  • MongoDB Community Server を使用する場合は、 bypassAutoEncryptionオプションをTrueに設定します

注意

MongoDB Community Server で自動復号化が利用可能

自動暗号化には MongoDB Enterprise または MongoDB Atlas が必要ですが、自動復号化には次の MongoDB 製品で利用できます。

  • MongoDB Community Server

  • MongoDB Enterprise Advanced

  • MongoDB Atlas

自動復号化を有効にする方法を示すコード スニペットは、ご希望の言語に対応するタブを選択します。

var autoEncryptionOpts = {
keyVaultNamespace: keyVaultNamespace,
kmsProviders: kmsProviders,
bypassAutoEncryption: true,
};
var encryptedClient = Mongo(
connectionString,
autoEncryptionOpts
);
var clientSettings = MongoClientSettings.FromConnectionString(connectionString);
var autoEncryptionOptions = new AutoEncryptionOptions(
keyVaultNamespace: keyVaultNamespace,
kmsProviders: kmsProviders,
bypassAutoEncryption: true);
clientSettings.AutoEncryptionOptions = autoEncryptionOptions;
var client = new MongoClient(clientSettings);
autoEncryptionOpts := options.AutoEncryption().
SetKmsProviders(kmsProviders).
SetKeyVaultNamespace(KeyVaultNamespace).
SetBypassAutoEncryption(true)
client, err := mongo.Connect(context.TODO(), options.Client().ApplyURI(URI).SetAutoEncryptionOptions(autoEncryptionOpts))
if err != nil {
return fmt.Errorf("Connect error for encrypted client: %v", err)
}
defer func() {
_ = client.Disconnect(context.TODO())
}()
MongoClientSettings clientSettings = MongoClientSettings.builder()
.applyConnectionString(new ConnectionString(connectionString))
.autoEncryptionSettings(AutoEncryptionSettings.builder()
.keyVaultNamespace(keyVaultNamespace)
.kmsProviders(kmsProviders).bypassAutoEncryption(true)
.build())
.build();
MongoClient mongoClient = MongoClients.create(clientSettings);
const client = new MongoClient(connectionString, {
monitorCommands: true,
autoEncryption: {
keyVaultNamespace,
kmsProviders,
bypassAutoEncryption: true,
},
});
auto_encryption_opts = AutoEncryptionOpts(
kms_providers=kms_providers,
key_vault_namespace=key_vault_namespace,
bypass_auto_encryption=True,
)
client = MongoClient(auto_encryption_opts=auto_encryption_opts)

次の構造を持つドキュメントを MongoDB インスタンスに挿入するとします。

{
"name": "<name of person>",
"age": <age of person>,
"favorite-foods": ["<array of foods>"]
}
1

この例では、同じMongoClientインスタンスを使用して Key Vault コレクションにアクセスし、暗号化されたデータの読み取りと書込みを行います。

次のコード スニペットは、 MongoClientインスタンスを作成する方法を示しています。

const autoEncryptionOpts = {
keyVaultNamespace: keyVaultNamespace,
kmsProviders: kmsProviders,
};
const encryptedClient = Mongo(connectionString, autoEncryptionOpts);
var client = new MongoClient(connectionString);
client, err := mongo.Connect(context.TODO(), options.Client().ApplyURI(URI))
if err != nil {
panic(fmt.Errorf("Client connect error %v", err))
}
MongoClient client = MongoClients.create(connectionString);
const client = new MongoClient(connectionString);
client = MongoClient(your_connection_uri)
2

次のコード スニペットは、 ClientEncryptionインスタンスを作成する方法を示しています。

const clientEncryption = encryptedClient.getClientEncryption();
var collection = client.GetDatabase(db).GetCollection<BsonDocument>(coll);
var clientEncryptionOptions = new ClientEncryptionOptions(
keyVaultClient: client,
keyVaultNamespace: keyVaultNamespace,
kmsProviders: kmsProviders);
var clientEncryption = new ClientEncryption(clientEncryptionOptions);
coll := client.Database(DbName).Collection(CollName)
clientEncryptionOpts := options.ClientEncryption().SetKeyVaultNamespace(KeyVaultNamespace).SetKmsProviders(kmsProviders)
clientEnc, err := mongo.NewClientEncryption(client, clientEncryptionOpts)
if err != nil {
panic(fmt.Errorf("NewClientEncryption error %v", err))
}
defer func() {
_ = clientEnc.Close(context.TODO())
}()
MongoCollection<Document> collection = client.getDatabase(db).getCollection(coll);
ClientEncryptionSettings clientEncryptionSettings = ClientEncryptionSettings.builder()
.keyVaultMongoClientSettings(MongoClientSettings.builder()
.applyConnectionString(new ConnectionString(connectionString))
.build())
.keyVaultNamespace(keyVaultNamespace)
.kmsProviders(kmsProviders)
.build();
ClientEncryption clientEncryption = ClientEncryptions.create(clientEncryptionSettings);
const collection = client.db(db).collection(coll);
const encryption = new ClientEncryption(client, {
keyVaultNamespace,
kmsProviders,
});
coll = client.employees.foods
client_encryption = ClientEncryption(
kms_providers,
"encryption.___keyVault",
client,
coll.codec_options,
)

注意

CodecOptions

MongoDB Python ドライバーでは、ドキュメントを暗号化および復号化するCodecOptionsを指定する必要があります。

暗号化および復号化されたアプリケーション データを MongoDB に書き込むMongoClientDatabase 、またはCollectionに構成したCodecOptionsを指定します。

3

次のアルゴリズムを使用して、ドキュメントのフィールドを暗号化します。

フィールド名
暗号化アルゴリズム
BSON フィールド型

name

決定的な

文字列

age

暗号化なし

Int

favorite-foods

ランダム

配列

次のコード スニペットは、ドキュメント内のフィールドを手動で暗号化し、ドキュメントを MongoDB に挿入する方法を示しています。

注意

次の例のdataKeyId変数は、データ暗号化キー(DEK)を参照しています。 ローカル キー プロバイダーを使用して DEK を生成する方法については、クイック スタートを参照してください。 特定のキー管理システムを使用して DEK を作成する方法については、チュートリアル を参照してください。

const encName = clientEncryption.encrypt(
dataKeyId,
"Greg",
"AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic"
);
const encFoods = clientEncryption.encrypt(
dataKeyId,
["Cheese", "Grapes"],
"AEAD_AES_256_CBC_HMAC_SHA_512-Random"
);
db.getSiblingDB(database).getCollection(collection).insertOne({
name: encName,
foods: encFoods,
});

注意

次の例のdataKeyId変数は、データ暗号化キー(DEK)を参照しています。 ローカル キー プロバイダーを使用して DEK を生成する方法については、クイック スタートを参照してください。 特定のキー管理システムを使用して DEK を作成する方法については、チュートリアル を参照してください。

var encryptedName = clientEncryption.Encrypt(
"Greg",
new EncryptOptions(algorithm: "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic", keyId: dataKeyId),
CancellationToken.None);
var encryptedFoods = clientEncryption.Encrypt(
new BsonArray { "Cheese", "Grapes" },
new EncryptOptions(algorithm: "AEAD_AES_256_CBC_HMAC_SHA_512-Random", keyId: dataKeyId),
CancellationToken.None);
collection.InsertOne(new BsonDocument { { "name", encryptedName }, { "age", 83 }, { "foods", encryptedFoods } });

注意

次の例のdataKeyId変数は、データ暗号化キー(DEK)を参照しています。 ローカル キー プロバイダーを使用して DEK を生成する方法については、クイック スタートを参照してください。 特定のキー管理システムを使用して DEK を作成する方法については、チュートリアル を参照してください。

nameRawValueType, nameRawValueData, err := bson.MarshalValue("Greg")
if err != nil {
panic(err)
}
nameRawValue := bson.RawValue{Type: nameRawValueType, Value: nameRawValueData}
nameEncryptionOpts := options.Encrypt().
SetAlgorithm("AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic").
SetKeyID(dataKeyId)
nameEncryptedField, err := clientEnc.Encrypt(
context.TODO(),
nameRawValue,
nameEncryptionOpts)
if err != nil {
panic(err)
}
foodsRawValueType, foodsRawValueData, err := bson.MarshalValue(bson.A{"Grapes", "Cheese"})
if err != nil {
panic(err)
}
foodsRawValue := bson.RawValue{Type: foodsRawValueType, Value: foodsRawValueData}
encryptionOpts := options.Encrypt().
SetAlgorithm("AEAD_AES_256_CBC_HMAC_SHA_512-Random").
SetKeyID(dataKeyId)
foodsEncryptedField, err := clientEnc.Encrypt(
context.TODO(),
foodsRawValue,
encryptionOpts)
if err != nil {
panic(err)
}
_, err = coll.InsertOne(
context.TODO(),
bson.D{{"name", nameEncryptedField}, {"foods", foodsEncryptedField}, {"age", 83}})
if err != nil {
panic(err)
}

注意

次の例のdataKeyId変数は、データ暗号化キー(DEK)を参照しています。 ローカル キー プロバイダーを使用して DEK を生成する方法については、クイック スタートを参照してください。 特定のキー管理システムを使用して DEK を作成する方法については、チュートリアル を参照してください。

BsonBinary encryptedName = clientEncryption.encrypt(new BsonString("Greg"), new EncryptOptions("AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic").keyId(dataKeyId));
BsonBinary encryptedFoods = clientEncryption.encrypt(new BsonArray().parse("[\"Grapes\", \"Foods\"]"), new EncryptOptions("AEAD_AES_256_CBC_HMAC_SHA_512-Random").keyId(dataKeyId));
collection.insertOne(new Document("name", encryptedName).append("foods", encryptedFoods).append("age", 83));

注意

次の例のdataKeyId変数は、データ暗号化キー(DEK)を参照しています。 ローカル キー プロバイダーを使用して DEK を生成する方法については、クイック スタートを参照してください。 特定のキー管理システムを使用して DEK を作成する方法については、チュートリアル を参照してください。

encryptedName = await encryption.encrypt("Greg", {
algorithm: "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic",
keyId: dataKeyId,
});
encryptedFoods = await encryption.encrypt(["Cheese", "Grapes"], {
algorithm: "AEAD_AES_256_CBC_HMAC_SHA_512-Random",
keyId: dataKeyId,
});
await collection.insertOne({
name: encryptedName,
age: 83,
foods: encryptedFoods,
});

注意

次の例のdata_key_id変数は、データ暗号化キー(DEK)を参照しています。 ローカル キー プロバイダーを使用して DEK を生成する方法については、クイック スタートを参照してください。 特定のキー管理システムを使用して DEK を作成する方法については、チュートリアル を参照してください。

encrypted_name = client_encryption.encrypt(
"Greg",
Algorithm.AEAD_AES_256_CBC_HMAC_SHA_512_Deterministic,
key_id=data_key_id,
)
encrypted_foods = client_encryption.encrypt(
["Cheese", "Grapes"],
Algorithm.AEAD_AES_256_CBC_HMAC_SHA_512_Random,
key_id=data_key_id,
)
coll.insert_one({"name": encrypted_name, "age": 83, "foods": encrypted_foods})
4

次のコード スニペットは、挿入されたドキュメントを取得し、暗号化されたフィールドを手動で復号化する方法を示しています。

const encNameQuery = clientEncryption.encrypt(
dataKeyId,
"Greg",
"AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic"
);
let doc = db.getSiblingDB(database).getCollection(collection).findOne({
name: encNameQuery,
});
console.log(doc);
doc.name = clientEncryption.decrypt(doc.name);
doc.foods = clientEncryption.decrypt(doc.foods);
console.log(doc);
var nameToQuery = "Greg";
var encryptedNameToQuery = clientEncryption.Encrypt(
nameToQuery,
new EncryptOptions(algorithm: "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic", keyId: dataKeyId),
CancellationToken.None);
var doc = collection.Find(new BsonDocument { { "name", encryptedNameToQuery } }).Single();
Console.WriteLine($"Encrypted document: {doc}");
doc["name"] = clientEncryption.Decrypt(doc["name"].AsBsonBinaryData, CancellationToken.None);
doc["foods"] = clientEncryption.Decrypt(doc["foods"].AsBsonBinaryData, CancellationToken.None);
Console.WriteLine($"Decrypted field: {doc}");
nameQueryRawValueType, nameQueryRawValueData, err := bson.MarshalValue("Greg")
if err != nil {
panic(err)
}
nameQueryRawValue := bson.RawValue{Type: nameQueryRawValueType, Value: nameQueryRawValueData}
nameQueryEncryptionOpts := options.Encrypt().
SetAlgorithm("AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic").
SetKeyID(dataKeyId)
nameQueryEncryptedField, err := clientEnc.Encrypt(
context.TODO(),
nameQueryRawValue,
nameQueryEncryptionOpts)
if err != nil {
panic(err)
}
var result bson.M
err = coll.FindOne(
context.TODO(),
bson.D{{"name", nameQueryEncryptedField}}).Decode(&result)
if err != nil {
if err == mongo.ErrNoDocuments {
return
}
panic(err)
}
fmt.Printf("Encrypted Document: %s\n", result)
nameDecrypted, err := clientEnc.Decrypt(
context.TODO(),
result["name"].(primitive.Binary))
foodsDecrypted, err := clientEnc.Decrypt(
context.TODO(),
result["foods"].(primitive.Binary))
result["foods"] = foodsDecrypted
result["name"] = nameDecrypted
fmt.Printf("Decrypted Document: %s\n", result)
BsonBinary encryptedNameQuery = clientEncryption.encrypt(new BsonString("Greg"), new EncryptOptions("AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic").keyId(dataKeyId));
Document result = collection.find(eq("name", encryptedNameQuery)).first();
System.out.println("Encrypted Document: " + result.toJson());
result.replace("name", clientEncryption.decrypt(new BsonBinary(result.get("name", Binary.class).getData())));
result.replace("foods", clientEncryption.decrypt(new BsonBinary(result.get("foods", Binary.class).getData())));
System.out.println("Decrypted Document: " + result.toJson());
queryEncryptedName = await encryption.encrypt("Greg", {
algorithm: "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic",
keyId: dataKeyId,
});
let doc = await collection.findOne({ name: queryEncryptedName });
console.log("Encrypted Document: ", doc);
doc.name = encryption.decrypt(doc.name);
doc.foods = encryption.decrypt(doc.foods);
console.log("Decrypted document: ", doc);
name_to_query = "Greg"
encrypted_name_to_query = client_encryption.encrypt(
name_to_query,
Algorithm.AEAD_AES_256_CBC_HMAC_SHA_512_Deterministic,
key_id=data_key_id,
)
doc = client.employees.foods.find_one({"name": encrypted_name_to_query})
print("Encrypted document: %s" % (doc,))
doc["name"] = client_encryption.decrypt(doc["name"])
doc["foods"] = client_encryption.decrypt(doc["foods"])
print("Decrypted document: %s" % (doc,))

MongoDB は、コレクション内の特定のフィールドの暗号化を強制するために、スキーマ検証を使用することをサポートしています。

特定のフィールドの暗号化を強制するように構成された MongoDB インスタンスで、明示的な暗号化メカニズムを使用してクライアント側のフィールドレベル暗号化を実行するクライアントは、MongoDB インスタンスに指定されたフィールドを暗号化する必要があります。

サーバー側で CSFLE を設定する方法については、「 CSFLE サーバー側でのスキーマ強制 」を参照してください。

キーヴォールト コレクション、データ暗号化キー、カスタマー マスター キーの詳細については、「暗号化キーとキーヴォールト 」を参照してください。

KMSプロバイダーとkmsProvidersオブジェクトの詳細については、「 KMS プロバイダー 」を参照してください。

戻る

自動暗号化