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

明示的な暗号化の使用

項目一覧

  • Overview
  • 始める前に
  • 手順
  • CMK の作成
  • キーヴォールト コレクションでの一意のインデックスの作成
  • データ暗号化キーと暗号化されたコレクションの作成
  • 暗号化された読み取りと書込みのための MongoClient の設定
  • 暗号化されたフィールドを含むドキュメントの挿入
  • 暗号化されたフィールドを使用したドキュメントの取得
  • 詳細

このガイドでは、明示的な暗号化と MongoDB ドライバーを使用してドキュメントを暗号化する方法を説明します。

このガイドを完了すると、明示的な暗号化を使用してドキュメント内のフィールドを暗号化するようにドライバーを構成できるようになります。 この知識により、明示的な暗号化を使用するクライアント アプリケーションを作成できるはずです。 自動復号化付き。

重要

このサンプル アプリケーションは本番環境では使用しないでください

このチュートリアルの手順では、暗号化のキーを安全でない環境に保存することが含まれているため、本番環境ではこのアプリケーションの変更されていないバージョンを使用しないでください。 このアプリケーションを本番環境で使用すると、暗号化のキーへの不正アクセスや、データの復号に必要なキーが失われるリスクがあります。 このチュートリアルの目的は、キー管理システムを設定する必要なく、Queryable Encryption を使用する方法を説明することです。

キー管理システムを使用して、暗号化のキーを本番環境に安全に保存できます。 KMSは、暗号化のキーを安全に保存および管理するリモート サービスです。 KMSを使用する Queryable Encryption 対応アプリケーションを設定する方法については、「 Queryable Encryption チュートリアル 」を参照してください。

このガイドのコードを完了して実行するには、インストール要件ページに示されているように開発環境を設定する必要があります。

Tip

詳細: フルアプリケーション

このガイドで作成するアプリケーションの完全なコードを表示するには、使用する MongoDB ドライバーに対応するタブを選択し、提供されたリンクに従ってください。

完全な Node.js アプリケーション

1

Queryable Encryption を実行するには、カスタマー マスター キー( CMK )を作成する必要があります。

96 バイトのカスタマー マスター キーを作成し、ファイル master-key.txtに保存します。

using (var randomNumberGenerator = System.Security.Cryptography.RandomNumberGenerator.Create())
{
var bytes = new byte[96];
randomNumberGenerator.GetBytes(bytes);
var localMasterKeyBase64Write = Convert.ToBase64String(bytes);
File.WriteAllText("master-key.txt", localMasterKeyBase64Write);
}
func localMasterKey() []byte {
key := make([]byte, 96)
if _, err := rand.Read(key); err != nil {
log.Fatalf("Unable to create a random 96 byte data key: %v", err)
}
if err := ioutil.WriteFile("master-key.txt", key, 0644); err != nil {
log.Fatalf("Unable to write key to file: %v", err)
}
return key
}
byte[] localMasterKeyWrite = new byte[96];
new SecureRandom().nextBytes(localMasterKeyWrite);
try (FileOutputStream stream = new FileOutputStream("master-key.txt")) {
stream.write(localMasterKeyWrite);
}
const fs = require("fs");
const crypto = require("crypto");
try {
fs.writeFileSync("master-key.txt", crypto.randomBytes(96));
} catch (err) {
console.error(err);
}
path = "master-key.txt"
file_bytes = os.urandom(96)
with open(path, "wb") as f:
f.write(file_bytes)

警告

本番環境ではローカルキー ファイルを使用しない

ファイルシステム内のローカルキー ファイルは安全でなく、本番環境には推奨されません。 代わりに、CMK をリモート キー管理システム に保存する必要があります KMS )。

Queryable Encryption の実装でリモートKMSを使用する方法については、チュートリアルのガイドを参照してください。

Tip

コマンドラインから CMK を生成

次のコマンドを使用して、Unix shell または PowerShell からCMKを生成します。

  • Unix shell:

    echo $(head -c 96 /dev/urandom | base64 | tr -d '\n')
  • PowerShell:

    $r=[byte[]]::new(64);$g=[System.Security.Cryptography.RandomNumberGenerator]::Create();$g.GetBytes($r);[Convert]::ToBase64String($r)

上記のコマンドの出力をcustomer-master-key.txtという名前のファイルに保存します。

Tip

参照: 完全なコード

カスタマー マスター キーを作成するための完全なコードについては 、 Queryable Encryption サンプル アプリケーションのリポジトリ を参照してください。

カスタマー マスター キーを作成するための完全なコードについては 、 Queryable Encryption サンプル アプリケーションのリポジトリ を参照してください。

カスタマー マスター キーを作成するための完全なコードについては 、 Queryable Encryption サンプル アプリケーションのリポジトリ を参照してください。

カスタマー マスター キーを作成するための完全なコードについては 、 Queryable Encryption サンプル アプリケーションのリポジトリ を参照してください。

カスタマー マスター キーを作成するための完全なコードについては 、 Queryable Encryption サンプル アプリケーションのリポジトリ を参照してください。

2

encryption.__keyVault名前空間のkeyAltNamesフィールドに一意のインデックスを作成します。

使用する MongoDB ドライバーに対応するタブを選択します。

var connectionString = "<Your MongoDB URI>";
var keyVaultNamespace = CollectionNamespace.FromFullName("encryption.__keyVault");
var keyVaultClient = new MongoClient(connectionString);
var indexOptions = new CreateIndexOptions<BsonDocument>
{
Unique = true,
PartialFilterExpression = new BsonDocument
{{"keyAltNames", new BsonDocument {{"$exists", new BsonBoolean(true)}}}}
};
var builder = Builders<BsonDocument>.IndexKeys;
var indexKeysDocument = builder.Ascending("keyAltNames");
var indexModel = new CreateIndexModel<BsonDocument>(indexKeysDocument, indexOptions);
var keyVaultDatabase = keyVaultClient.GetDatabase(keyVaultNamespace.DatabaseNamespace.DatabaseName);
// Drop the Key Vault Collection in case you created this collection
// in a previous run of this application.
keyVaultDatabase.DropCollection(keyVaultNamespace.CollectionName);
var keyVaultCollection = keyVaultDatabase.GetCollection<BsonDocument>(keyVaultNamespace.CollectionName);
keyVaultCollection.Indexes.CreateOne(indexModel);

重要

go build または go run を使用してこのガイドのGoコードをビルドまたは実行する場合は、 Queryable Encryptionを有効にするために常に cse ビルド制約を含めてください。 ビルド制約を含めた例については、次の shell コマンドを参照してください。

go run -tags cse make-data-key.go
uri := "<Your MongoDB URI>"
keyVaultClient, err := mongo.Connect(context.TODO(), options.Client().ApplyURI(uri))
if err != nil {
return fmt.Errorf("Connect error for regular client: %v", err)
}
defer func() {
_ = keyVaultClient.Disconnect(context.TODO())
}()
keyVaultDb := "encryption"
keyVaultColl := "__keyVault"
keyVaultNamespace := keyVaultDb + "." + keyVaultColl
keyVaultIndex := mongo.IndexModel{
Keys: bson.D{{"keyAltNames", 1}},
Options: options.Index().
SetUnique(true).
SetPartialFilterExpression(bson.D{
{"keyAltNames", bson.D{
{"$exists", true},
}},
}),
}
// Drop the Key Vault Collection in case you created this collection
// in a previous run of this application.
if err = keyVaultClient.Database(keyVaultDb).Collection(keyVaultColl).Drop(context.TODO()); err != nil {
log.Fatalf("Collection.Drop error: %v", err)
}
_, err = keyVaultClient.Database(keyVaultDb).Collection(keyVaultColl).Indexes().CreateOne(context.TODO(), keyVaultIndex)
if err != nil {
panic(err)
}
String keyVaultDb = "encryption";
String keyVaultColl = "__keyVault";
MongoClient keyVaultClient = MongoClients.create(connectionString);
String encryptedDbName = "medicalRecords";
String encryptedCollName = "patients";
// Drop the Key Vault Collection in case you created this collection
// in a previous run of this application.
keyVaultClient.getDatabase(keyVaultDb).getCollection(keyVaultColl).drop();
MongoCollection keyVaultCollection = keyVaultClient.getDatabase(keyVaultDb).getCollection(keyVaultColl);
IndexOptions indexOpts = new IndexOptions().partialFilterExpression(new BsonDocument("keyAltNames", new BsonDocument("$exists", new BsonBoolean(true) ))).unique(true);
keyVaultCollection.createIndex(new BsonDocument("keyAltNames", new BsonInt32(1)), indexOpts);
keyVaultClient.close();
const uri = "<Your Connection String>";
const keyVaultClient = new MongoClient(uri);
await keyVaultClient.connect();
const keyVaultDB = keyVaultClient.db(keyVaultDatabase);
// Drop the Key Vault Collection in case you created this collection
// in a previous run of this application.
await keyVaultDB.dropDatabase();
const keyVaultColl = keyVaultDB.collection(keyVaultCollection);
await keyVaultColl.createIndex(
{ keyAltNames: 1 },
{
unique: true,
partialFilterExpression: { keyAltNames: { $exists: true } },
}
);
connection_string = "<your connection string here>"
key_vault_coll = "__keyVault"
key_vault_db = "encryption"
key_vault_namespace = f"{key_vault_db}.{key_vault_coll}"
key_vault_client = MongoClient(connection_string)
# Drop the Key Vault Collection in case you created this collection
# in a previous run of this application.
key_vault_client.drop_database(key_vault_db)
key_vault_client[key_vault_db][key_vault_coll].create_index(
[("keyAltNames", ASCENDING)],
unique=True,
partialFilterExpression={"keyAltNames": {"$exists": True}},
)
3
1

このガイドの「 カスタマー マスター キーの作成」ステップで生成したカスタマー マスター キー ファイルの内容を取得します。

CMK値を KMS プロバイダー設定に渡します。 クライアントはこれらの設定を使用してCMKを検出します。 プロバイダー名をlocalに設定して、ローカルキー プロバイダーを使用しているドライバーに通知します。

使用する MongoDB ドライバーに対応するタブを選択します。

var kmsProviders = new Dictionary<string, IReadOnlyDictionary<string, object>>();
const string provider = "local";
var localMasterKeyBase64Read = File.ReadAllText("master-key.txt");
var localMasterKeyBytes = Convert.FromBase64String(localMasterKeyBase64Read);
var localOptions = new Dictionary<string, object>
{
{"key", localMasterKeyBytes}
};
kmsProviders.Add(provider, localOptions);
key, err := ioutil.ReadFile("master-key.txt")
if err != nil {
log.Fatalf("Could not read the key from master-key.txt: %v", err)
}
provider := "local"
kmsProviders := map[string]map[string]interface{}{"local": {"key": key}}
String kmsProvider = "local";
String path = "master-key.txt";
byte[] localMasterKeyRead = new byte[96];
try (FileInputStream fis = new FileInputStream(path)) {
if (fis.read(localMasterKeyRead) < 96)
throw new Exception("Expected to read 96 bytes from file");
}
Map<String, Object> keyMap = new HashMap<String, Object>();
keyMap.put("key", localMasterKeyRead);
Map<String, Map<String, Object>> kmsProviders = new HashMap<String, Map<String, Object>>();
kmsProviders.put("local", keyMap);
const provider = "local";
const path = "./master-key.txt";
// WARNING: Do not use a local key file in a production application
const localMasterKey = fs.readFileSync(path);
const kmsProviders = {
local: {
key: localMasterKey,
},
};
provider = "local"
path = "./master-key.txt"
# WARNING: Do not use a local key file in a production application
with open(path, "rb") as f:
local_master_key = f.read()
kms_providers = {
"local": {
"key": local_master_key # local_master_key variable from the previous step
},
}
2

MongoDB接続stringと Key Vault コレクションの名前空間を使用してクライアントを構築し、データ暗号化キーを作成します。

注意

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

このチュートリアルを完了するには、アプリケーションが MongoDB への接続に使用するデータベースユーザーが、次の名前空間に対するdbAdmin権限を持っている必要があります。

  • encryption.__keyVault

  • medicalRecords database

var clientEncryptionOptions = new ClientEncryptionOptions(
keyVaultClient,
keyVaultNamespace,
kmsProviders: kmsProviders
);
var clientEncryption = new ClientEncryption(clientEncryptionOptions);
var dataKeyOptions1 = new DataKeyOptions(alternateKeyNames: new List<string> { "dataKey1" });
var dataKeyOptions2 = new DataKeyOptions(alternateKeyNames: new List<string> { "dataKey2" });
BsonBinaryData CreateKeyGetID(DataKeyOptions options)
{
var dateKeyGuid = clientEncryption.CreateDataKey(provider, options, CancellationToken.None);
return new BsonBinaryData(dateKeyGuid, GuidRepresentation.Standard);
}
var dataKeyId1 = CreateKeyGetID(dataKeyOptions1);
var dataKeyId2 = CreateKeyGetID(dataKeyOptions2);
var dataKeyId3 = CreateKeyGetID(dataKeyOptions3);
var dataKeyId4 = CreateKeyGetID(dataKeyOptions4);
clientEncryptionOpts := options.ClientEncryption().SetKeyVaultNamespace(keyVaultNamespace).
SetKmsProviders(kmsProviders)
clientEnc, err := mongo.NewClientEncryption(keyVaultClient, clientEncryptionOpts)
if err != nil {
return fmt.Errorf("NewClientEncryption error %v", err)
}
defer func() {
_ = clientEnc.Close(context.TODO())
}()
dataKeyOpts1 := options.DataKey().
SetKeyAltNames([]string{"demoDataKey1"})
dataKeyID1, err := clientEnc.CreateDataKey(context.TODO(), provider, dataKeyOpts1)
if err != nil {
return fmt.Errorf("create data key error %v", err)
}
dataKeyOpts2 := options.DataKey().
SetKeyAltNames([]string{"demoDataKey2"})
dataKeyID2, err := clientEnc.CreateDataKey(context.TODO(), provider, dataKeyOpts2)
if err != nil {
return fmt.Errorf("create data key error %v", err)
}
String keyVaultNamespace = keyVaultDb + "." + keyVaultColl;
ClientEncryptionSettings clientEncryptionSettings = ClientEncryptionSettings.builder()
.keyVaultMongoClientSettings(MongoClientSettings.builder()
.applyConnectionString(new ConnectionString(connectionString))
.build())
.keyVaultNamespace(keyVaultNamespace)
.kmsProviders(kmsProviders)
.build();
ClientEncryption clientEncryption = ClientEncryptions.create(clientEncryptionSettings);
List<String> keyAlts1 = new ArrayList<String>();
keyAlts1.add("dataKey1");
BsonBinary dataKeyId1 = clientEncryption.createDataKey(kmsProvider, new DataKeyOptions()
.keyAltNames(keyAlts1));
List<String> keyAlts2 = new ArrayList<String>();
keyAlts2.add("dataKey2");
BsonBinary dataKeyId2 = clientEncryption.createDataKey(kmsProvider, new DataKeyOptions()
.keyAltNames(keyAlts2));
const clientEnc = new ClientEncryption(keyVaultClient, {
keyVaultNamespace: keyVaultNamespace,
kmsProviders: kmsProviders,
});
const dek1 = await clientEnc.createDataKey(provider, {
keyAltNames: ["dataKey1"],
});
const dek2 = await clientEnc.createDataKey(provider, {
keyAltNames: ["dataKey2"],
});
client = MongoClient(connection_string)
client_encryption = ClientEncryption(
kms_providers, # pass in the kms_providers variable from the previous step
key_vault_namespace,
client,
CodecOptions(uuid_representation=STANDARD),
)
data_key_id_1 = client_encryption.create_data_key(provider, key_alt_names=["dataKey1"])
data_key_id_2 = client_encryption.create_data_key(provider, key_alt_names=["dataKey2"])
3

Queryable Encryption が有効なMongoClientインスタンスを使用して、暗号化する必要があるフィールドを指定し、暗号化されたコレクションを作成します。

var encryptedCollectionNamespace = CollectionNamespace.FromFullName("medicalRecords.patients");
var encryptedFieldsMap = new Dictionary<string, BsonDocument>
{
{
encryptedCollectionNamespace.FullName, new BsonDocument
{
{
"fields", new BsonArray
{
new BsonDocument
{
{"keyId", dataKeyId1},
{"path", new BsonString("patientId")},
{"bsonType", new BsonString("int")},
{
"queries", new BsonDocument
{
{"queryType", new BsonString("equality")}
}
}
},
new BsonDocument
{
{"keyId", dataKeyId2},
{"path", new BsonString("medications")},
{"bsonType", new BsonString("array")},
},
}
}
}
}
};
var extraOptions = new Dictionary<string, object>()
{
{ "cryptSharedLibPath", "<path to crypt_shared library>" },
};
var autoEncryptionOptions = new AutoEncryptionOptions(
keyVaultNamespace,
kmsProviders,
encryptedFieldsMap: encryptedFieldsMap,
extraOptions: extraOptions);
var clientSettings = MongoClientSettings.FromConnectionString(connectionString);
clientSettings.AutoEncryptionOptions = autoEncryptionOptions;
var secureClient = new MongoClient(clientSettings);
var encryptedDatabase = secureClient.GetDatabase(encryptedCollectionNamespace.DatabaseNamespace.DatabaseName);
// Drop the encrypted collection in case you created this collection
// in a previous run of this application.
encryptedDatabase.DropCollection(encryptedCollectionNamespace.CollectionName);
encryptedDatabase.CreateCollection(encryptedCollectionNamespace.CollectionName);
Console.WriteLine("Created encrypted collection!");
dbName := "medicalRecords"
collName := "patients"
encNamespace := (dbName + "." + collName)
encryptedFieldsMap := bson.M{
encNamespace: bson.M{
"fields": []bson.M{
{
"path": "patientId",
"bsonType": "int",
"keyId": dataKeyID1,
"queries": []bson.M{
{
"queryType": "equality",
},
},
},
{
"path": "medications",
"bsonType": "array",
"keyId": dataKeyID2,
},
},
},
}
extraOptions := map[string]interface{}{
"cryptSharedLibPath": "<Your Crypt Shared lib Path>",
}
autoEncryptionOpts := options.AutoEncryption().
SetKmsProviders(kmsProviders).
SetKeyVaultNamespace(keyVaultNamespace).
SetEncryptedFieldsMap(encryptedFieldsMap).
SetExtraOptions(extraOptions)
secureClient, 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() {
_ = secureClient.Disconnect(context.TODO())
}()
// Drop the encrypted collection in case you created this collection
// in a previous run of this application.
if err = secureClient.Database(dbName).Collection(collName).Drop(context.TODO()); err != nil {
log.Fatalf("Collection.Drop error: %v", err)
}
err = secureClient.Database(dbName).CreateCollection(context.TODO(), collName)
if err != nil {
return fmt.Errorf("Error creating collection: %v", err)
}
String encryptedNameSpace = encryptedDbName + "." + encryptedCollName;
BsonDocument encFields = new BsonDocument().append("fields",
new BsonArray(Arrays.asList(
new BsonDocument().append("keyId", dataKeyId1)
.append("path", new BsonString("patientId"))
.append("bsonType", new BsonString("int"))
.append("queries", new BsonDocument().append("queryType", new BsonString("equality"))),
new BsonDocument().append("keyId", dataKeyId2)
.append("path", new BsonString("medications"))
.append("bsonType", new BsonString("array")),
)));
Map<String, BsonDocument> encryptedFieldsMap = new HashMap<String, BsonDocument>();
encryptedFieldsMap.put(encryptedNameSpace, encFields);
Map<String, Object> extraOptions = new HashMap<String, Object>();
extraOptions.put("cryptSharedLibPath", "<path to crypt_shared>");
MongoClientSettings clientSettings = MongoClientSettings.builder()
.applyConnectionString(new ConnectionString(connectionString))
.autoEncryptionSettings(AutoEncryptionSettings.builder()
.keyVaultNamespace(keyVaultNamespace)
.kmsProviders(kmsProviders)
.encryptedFieldsMap(encryptedFieldsMap)
.extraOptions(extraOptions)
.build())
.build();
MongoClient mongoClientSecure = MongoClients.create(clientSettings);
MongoDatabase encDb = mongoClientSecure.getDatabase(encryptedDbName);
// Drop the encrypted collection in case you created this collection
// in a previous run of this application.
encDb.getCollection(encryptedCollName).drop();
encDb.createCollection(encryptedCollName);
const encryptedFieldsMap = {
[`${secretDB}.${secretCollection}`]: {
fields: [
{
keyId: dek1,
path: "patientId",
bsonType: "int",
queries: { queryType: "equality" },
},
{
keyId: dek2,
path: "medications",
bsonType: "array",
},
],
},
};
const extraOptions = {
cryptSharedLibPath: "<path to FLE Shared Library>",
};
const encClient = new MongoClient(uri, {
autoEncryption: {
keyVaultNamespace,
kmsProviders,
extraOptions,
encryptedFieldsMap,
},
});
await encClient.connect();
const newEncDB = encClient.db(secretDB);
// Drop the encrypted collection in case you created this collection
// in a previous run of this application.
await newEncDB.dropDatabase();
await newEncDB.createCollection(secretCollection);
console.log("Created encrypted collection!");
encrypted_db_name = "medicalRecords"
encrypted_coll_name = "patients"
encrypted_fields_map = {
f"{encrypted_db_name}.{encrypted_coll_name}": {
"fields": [
{
"keyId": data_key_id_1,
"path": "patientId",
"bsonType": "int",
"queries": {"queryType": "equality"},
},
{
"keyId": data_key_id_2,
"path": "medications",
"bsonType": "array",
},
],
},
}
key_vault_namespace = "encryption.__keyVault"
auto_encryption = AutoEncryptionOpts(
kms_providers,
key_vault_namespace,
encrypted_fields_map=encrypted_fields_map,
crypt_shared_lib_path="<path to FLE Shared Library>",
)
secure_client = MongoClient(connection_string, auto_encryption_opts=auto_encryption)
# Drop the encrypted collection in case you created this collection
# in a previous run of this application.
secure_client.drop_database(encrypted_db_name)
encrypted_db = secure_client[encrypted_db_name]
encrypted_db.create_collection(encrypted_coll_name)
print("Created encrypted collection!")

このセクションのコードからの出力は、次のようになります。

Created encrypted collection!

Tip

参照: 完全なコード

データ暗号化キーを作成するための完全なコードについては 、 Queryable Encryption サンプル アプリケーションのリポジトリ を参照してください。

データ暗号化キーを作成するための完全なコードについては 、 Queryable Encryption サンプル アプリケーションのリポジトリ を参照してください。

データ暗号化キーを作成するための完全なコードについては 、 Queryable Encryption サンプル アプリケーションのリポジトリ を参照してください。

データ暗号化キーを作成するための完全なコードについては 、 Queryable Encryption サンプル アプリケーションのリポジトリ を参照してください。

データ暗号化キーを作成するための完全なコードについては 、 Queryable Encryption サンプル アプリケーションのリポジトリ を参照してください。

4
1

キーヴォールト コレクションの名前空間としてencryption.__keyVaultを指定します。

var connectionString = "<Your MongoDB URI>";
var keyVaultNamespace = CollectionNamespace.FromFullName("encryption.__keyVault");
var coll = "patients";
var db = "medicalRecords";
keyVaultColl := "__keyVault"
keyVaultDb := "encryption"
keyVaultNamespace := keyVaultDb + "." + keyVaultColl
dbName := "medicalRecords"
collName := "patients"
String db = "medicalRecords";
String coll = "patients";
String keyVaultDb = "encryption";
String keyVaultColl = "__keyVault";
String keyVaultNamespace = String.format("%1$s.%2$s", keyVaultDb, keyVaultColl);
String connectionString = "<Your MongoDB URI>";
const eDB = "encryption";
const eKV = "__keyVault";
const keyVaultNamespace = `${eDB}.${eKV}`;
const secretDB = "medicalRecords";
const secretCollection = "patients";
key_vault_namespace = "encryption.__keyVault"
key_vault_db_name, key_vault_coll_name = key_vault_namespace.split(".", 1)
2

KMS プロバイダーを指定し、CMK をインラインで指定します。

var kmsProviders = new Dictionary<string, IReadOnlyDictionary<string, object>>();
const string provider = "local";
const string localMasterKeyPath = "master-key.txt";
var localMasterKeyBase64Read = File.ReadAllText(localMasterKeyPath);
var localMasterKeyBytes = Convert.FromBase64String(localMasterKeyBase64Read);
var localOptions = new Dictionary<string, object>
{
{"key", localMasterKeyBytes}
};
kmsProviders.Add(provider, localOptions);
key, err := ioutil.ReadFile("master-key.txt")
if err != nil {
log.Fatalf("Could not read the key from master-key.txt: %v", err)
}
kmsProviders := map[string]map[string]interface{}{"local": {"key": key}}
String kmsProvider = "local";
String path = "master-key.txt";
byte[] localMasterKeyRead = new byte[96];
try (FileInputStream fis = new FileInputStream(path)) {
if (fis.read(localMasterKeyRead) < 96)
throw new Exception("Expected to read 96 bytes from file");
}
Map<String, Object> keyMap = new HashMap<>();
keyMap.put("key", localMasterKeyRead);
Map<String, Map<String, Object>> kmsProviders = new HashMap<>();
kmsProviders.put(kmsProvider, keyMap);
const fs = require("fs");
const path = "./master-key.txt";
// WARNING: Do not use a local key file in a production application
const localMasterKey = fs.readFileSync(path);
const kmsProviders = {
local: {
key: localMasterKey,
},
};
path = "./master-key.txt"
with open(path, "rb") as f:
local_master_key = f.read()
kms_providers = {
"local": {
"key": local_master_key # local_master_key variable from the previous step
},
}
3

このガイドの「 データ暗号化キーの作成 」ステップで作成されたデータ暗号化キーを取得します。

var regularClient = new MongoClient(connectionString);
var keyVaultCollection = regularClient.GetDatabase(keyVaultNamespace.DatabaseNamespace.DatabaseName)
.GetCollection<BsonDocument>(keyVaultNamespace.CollectionName);
Guid GetKeyId(string altName)
{
var filter = Builders<BsonDocument>.Filter.Eq<BsonString>("keyAltNames", altName);
return keyVaultCollection.Find(filter).First<BsonDocument>()["_id"].AsGuid;
}
var dataKeyId1 = GetKeyId("dataKey1");
var dataKeyId2 = GetKeyId("dataKey2");
uri := "<Your MongoDB URI>"
regularClient, err := mongo.Connect(context.TODO(), options.Client().ApplyURI(uri))
if err != nil {
panic(fmt.Errorf("Client connect error %v", err))
}
var foundDoc1 bson.M
err = regularClient.Database(keyVaultDb).Collection(keyVaultColl).FindOne(context.TODO(), bson.D{{"keyAltNames", "demoDataKey1"}}).Decode(&foundDoc1)
if err != nil {
panic(err)
}
var dataKeyID1 = foundDoc1["_id"].(primitive.Binary)
var foundDoc2 bson.M
err = regularClient.Database(keyVaultDb).Collection(keyVaultColl).FindOne(context.TODO(), bson.D{{"keyAltNames", "demoDataKey2"}}).Decode(&foundDoc2)
if err != nil {
panic(err)
}
var dataKeyID2 = foundDoc2["_id"].(primitive.Binary)
MongoClient client = MongoClients.create(connectionString);
MongoCollection<Document> keyVaultClient = client.getDatabase(keyVaultDb).getCollection(keyVaultColl);
BsonBinary dataKeyId1 = new BsonBinary(BsonBinarySubType.UUID_STANDARD, keyVaultClient.find(eq("keyAltNames", "dataKey1")).first().get("_id", Binary.class).getData());
BsonBinary dataKeyId2 = new BsonBinary(BsonBinarySubType.UUID_STANDARD, keyVaultClient.find(eq("keyAltNames", "dataKey2")).first().get("_id", Binary.class).getData());
const uri = "<Your MongoDB URI>";
const unencryptedClient = new MongoClient(uri);
await unencryptedClient.connect();
const keyVaultClient = unencryptedClient.db(eDB).collection(eKV);
const dek1 = await keyVaultClient.findOne({ keyAltNames: "dataKey1" });
const dek2 = await keyVaultClient.findOne({ keyAltNames: "dataKey2" });
connection_string = "<your connection string here>"
client = MongoClient(connection_string)
key_vault = client[key_vault_db_name][key_vault_coll_name]
data_key_id_1 = key_vault.find_one({"keyAltNames": "dataKey1"})["_id"]
data_key_id_2 = key_vault.find_one({"keyAltNames": "dataKey2"})["_id"]
4
var extraOptions = new Dictionary<string, object>()
{
{"cryptSharedLibPath", "<path to crypt_shared library>"},
};
extraOptions := map[string]interface{}{
"cryptSharedLibPath": "<path to crypt_shared library>",
}
Map<String, Object> extraOptions = new HashMap<>();
extraOptions.put("cryptSharedLibPath", "<path to crypt_shared library>");
const extraOptions = {
cryptSharedLibPath: "<path to crypt_shared library>",
};
opts = AutoEncryptionOpts(
kms_providers,
key_vault.full_name,
bypass_query_analysis=True,
key_vault_client=client,
crypt_shared_lib_path="<path to FLE Shared Library>",
)

Tip

詳細

このパスで参照されるライブラリの詳細については、「 Queryable Encryption のための自動暗号化共有ライブラリ」ページを参照してください。

5

次の自動暗号化設定を使用してMongoClientオブジェクトをインスタンス化します。

var clientSettings = MongoClientSettings.FromConnectionString(connectionString);
var autoEncryptionOptions = new AutoEncryptionOptions(
keyVaultNamespace,
kmsProviders,
bypassQueryAnalysis: true,
extraOptions: extraOptions);
clientSettings.AutoEncryptionOptions = autoEncryptionOptions;
var secureClient = new MongoClient(clientSettings);
var collection = secureClient.GetDatabase(db).GetCollection<BsonDocument>(coll);
autoEncryptionOpts := options.AutoEncryption().
SetKmsProviders(kmsProviders).
SetKeyVaultNamespace(keyVaultNamespace).
SetExtraOptions(extraOptions).
SetBypassQueryAnalysis(true)
secureClient, 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() {
_ = secureClient.Disconnect(context.TODO())
}()
var coll = secureClient.Database(dbName).Collection(collName)
MongoClientSettings clientSettings = MongoClientSettings.builder()
.applyConnectionString(new ConnectionString(connectionString))
.autoEncryptionSettings(AutoEncryptionSettings.builder()
.keyVaultNamespace(keyVaultNamespace)
.kmsProviders(kmsProviders)
.extraOptions(extraOptions)
.bypassQueryAnalysis(true)
.build())
.build();
MongoClient mongoClientSecure = MongoClients.create(clientSettings);
const encryptedClient = new MongoClient(uri, {
autoEncryption: {
kmsProviders: kmsProviders,
keyVaultNamespace: keyVaultNamespace,
bypassQueryAnalysis: true,
keyVaultClient: unencryptedClient,
extraOptions: extraOptions,
},
});
await encryptedClient.connect();
encrypted_client = MongoClient(connection_string, auto_encryption_opts=opts)
db = encrypted_client.medicalRecords
coll = db.patients

注意

自動復号化

自動暗号化が有効になっているMongoClientインスタンスを使用して自動復号化を実行します。

自動復号化による明示的な暗号化の詳細については、「基礎」セクションを参照してください。

6

次のようにClientEncryptionオブジェクトをインスタンス化します。

var clientEncryptionOptions = new ClientEncryptionOptions(
keyVaultClient: regularClient,
keyVaultNamespace: keyVaultNamespace,
kmsProviders: kmsProviders
);
var clientEncryption = new ClientEncryption(clientEncryptionOptions);
clientEncryptionOpts := options.ClientEncryption().SetKeyVaultNamespace(keyVaultNamespace).SetKmsProviders(kmsProviders)
clientEnc, err := mongo.NewClientEncryption(regularClient, clientEncryptionOpts)
if err != nil {
panic(fmt.Errorf("NewClientEncryption error %v", err))
}
defer func() {
_ = clientEnc.Close(context.TODO())
}()
ClientEncryptionSettings clientEncryptionSettings = ClientEncryptionSettings.builder()
.keyVaultMongoClientSettings(MongoClientSettings.builder()
.applyConnectionString(new ConnectionString(connectionString))
.build())
.keyVaultNamespace(keyVaultNamespace)
.kmsProviders(kmsProviders)
.build();
ClientEncryption clientEncryption = ClientEncryptions.create(clientEncryptionSettings);
const encryption = new ClientEncryption(unencryptedClient, {
keyVaultNamespace,
kmsProviders,
});
client_encryption = ClientEncryption(
kms_providers, key_vault_namespace, client, client.codec_options
)
5

Queryable Encryption が有効なMongoClientインスタンスを使用し、次のコード スニペットを使用して、暗号化されたフィールドを含むドキュメントをmedicalRecords.patients名前空間に挿入します。

var patientId = 12345678;
var medications = new BsonArray
{
new BsonString("Atorvastatin"),
new BsonString("Levothyroxine")
};
var indexedEncrypted = clientEncryption.Encrypt(
patientId,
new EncryptOptions(algorithm: "Indexed", keyId: dataKeyId1, contentionFactor: 1),
CancellationToken.None);
var unindexedEncrypted = clientEncryption.Encrypt(
medications,
new EncryptOptions(algorithm: "Unindexed", keyId: dataKeyId2),
CancellationToken.None);
collection.InsertOne(new BsonDocument { { "firstName", "Jon" }, { "patientId", indexedEncrypted }, { "medications", unindexedEncrypted } });
patientIdRawValueType, patientIdRawValueData, err := bson.MarshalValue(12345678)
if err != nil {
panic(err)
}
patientIdRawValue := bson.RawValue{Type: patientIdRawValueType, Value: patientIdRawValueData}
patientIdEncryptionOpts := options.Encrypt().
SetAlgorithm("Indexed").
SetKeyID(dataKeyID1).
SetContentionFactor(1)
patientIdEncryptedField, err := clientEnc.Encrypt(
context.TODO(),
patientIdRawValue,
patientIdEncryptionOpts)
if err != nil {
panic(err)
}
medicationsRawValueType, medicationsRawValueData, err := bson.MarshalValue([]string{"Atorvastatin", "Levothyroxine"})
if err != nil {
panic(err)
}
medicationsRawValue := bson.RawValue{Type: medicationsRawValueType, Value: medicationsRawValueData}
medicationsEncryptionOpts := options.Encrypt().
SetAlgorithm("Unindexed").
SetKeyID(dataKeyID2)
medicationsEncryptedField, err := clientEnc.Encrypt(
context.TODO(),
medicationsRawValue,
medicationsEncryptionOpts)
if err != nil {
panic(err)
}
_, err = coll.InsertOne(
context.TODO(),
bson.D{{"firstName", "Jon"}, {"patientId", patientIdEncryptedField}, {"medications", medicationsEncryptedField}})
if err != nil {
panic(err)
}
BsonInt32 patientId = new BsonInt32(12345678);
ArrayList<BsonString> medications = new ArrayList<>();
medications.add(new BsonString("Atorvastatin"));
medications.add(new BsonString("Levothyroxine"));
BsonBinary indexedEncrypted = clientEncryption.encrypt(patientId, new EncryptOptions("Indexed").keyId(dataKeyId1).contentionFactor(1L));
BsonBinary unindexedEncrypted = clientEncryption.encrypt(new BsonArray(medications), new EncryptOptions("Unindexed").keyId(dataKeyId2));
MongoCollection<BsonDocument> collection = mongoClientSecure.getDatabase(db).getCollection(coll, BsonDocument.class);
collection.insertOne(new BsonDocument("firstName", new BsonString("Jon")).append("patientId", indexedEncrypted).append("medications", unindexedEncrypted));
const patientId = 12345678;
const medications = ["Atorvastatin", "Levothyroxine"];
const indexedInsertPayload = await encryption.encrypt(patientId, {
algorithm: "Indexed",
keyId: dek1._id,
contentionFactor: 1,
});
const unindexedInsertPayload = await encryption.encrypt(medications, {
algorithm: "Unindexed",
keyId: dek2._id,
});
const encryptedColl = encryptedClient
.db(secretDB)
.collection(secretCollection);
await encryptedColl.insertOne({
firstName: "Jon",
patientId: indexedInsertPayload,
medications: unindexedInsertPayload,
});
patientId = 12345678
medications = ["Atorvastatin", "Levothyroxine"]
indexed_insert_payload = client_encryption.encrypt(
patientId, Algorithm.INDEXED, data_key_id_1, contention_factor=1
)
unindexed_insert_payload = client_encryption.encrypt(
medications, Algorithm.UNINDEXED, data_key_id_2
)
coll.insert_one(
{
"firstName": "Jon",
"patientId": indexed_insert_payload,
"medications": unindexed_insert_payload,
}
)

ドキュメントを挿入すると、Queryable Encryption が有効なクライアントは次のようにドキュメントのフィールドを暗号化します。

{
"_id": {
"$oid": "6303e36053cc7ec2e6a630bd"
},
"firstName": "Jon",
"patientId": {
"$binary": {
"base64": "BxLJUBmg703civqMz8ASsD4QEYeSneOGiiYHfLE77ELEkp1EC/fXPrKCNRQl2mAFddszqDJ0P3znKrq0DVMEvJoU6wa0Ra+U+JjNVr8NtJE+TpTLCannY5Av6iGfLAaiHbM/E8Ftz1YCQsArQwuNp3wIV/GJPLa2662xsyk0wz7F6IRGC3FlnxpN4UIFaHE1M7Y6kEnx3tEy5uJBvU4Sex7I2H0kqHthClH77Q6xHIHc8H9d6upvgnEbkKBCnmc24A2pSG/xZ7LBsV3j5aOboPISuN/lvg==",
"subType": "06"
}
},
"medications": {
"$binary": {
"base64": "BvOsveapfUxiuQxCMSM2fYIEyRlQaSqR+0NxlMarwurBflvoMz1FrSjSGgCVCpK8X+YrilP6Bac99kkaUmRJfjo4savxcjpOfEnUj5bHciPyfQBYmYF4PMLDtTTzGZpPilb9d5KgpIMBXxHi+dIcog==",
"subType": "06"
}
},
"__safeContent__": [
{
"$binary": {
"base64": "ZLPIpgxzXpHUGrvdIHetwmMagR+mqvuUj5nzXNGf/WM=",
"subType": "00"
}
}
]
}

警告

MongoDB_ENUS_JAJP フィールドを変更しないでください

__safeContent__フィールドは Queryable Encryption に必須です。 このフィールドの内容は変更しないでください。

Tip

参照: 完全なコード

明示的な暗号化で暗号化されたドキュメントを挿入するための完全なコードを表示するには 、 Queryable Encryption のサンプル アプリケーション リポジトリを参照してください。

明示的な暗号化で暗号化されたドキュメントを挿入するための完全なコードを表示するには 、 Queryable Encryption のサンプル アプリケーション リポジトリを参照してください。

明示的な暗号化で暗号化されたドキュメントを挿入するための完全なコードを表示するには 、 Queryable Encryption のサンプル アプリケーション リポジトリを参照してください。

明示的な暗号化で暗号化されたドキュメントを挿入するための完全なコードを表示するには 、 Queryable Encryption のサンプル アプリケーション リポジトリを参照してください。

明示的な暗号化で暗号化されたドキュメントを挿入するための完全なコードを表示するには 、 Queryable Encryption のサンプル アプリケーション リポジトリを参照してください。

6

暗号化されたフィールドに対するクエリを実行して、このガイドの「 暗号化されたフィールドを含むドキュメントの挿入 」のステップで挿入した暗号化されたフィールドを含むドキュメントを取得します。

var findPayload = clientEncryption.Encrypt(
patientId,
new EncryptOptions(algorithm: "Indexed", keyId: dataKeyId1, queryType: "equality", contentionFactor: 1),
CancellationToken.None);
var doc = collection.Find(new BsonDocument { { "patientId", findPayload } }).Single();
Console.WriteLine($"Encrypted document: {doc}");
findPayloadRawValueType, findPayloadRawValueData, err := bson.MarshalValue(12345678)
if err != nil {
panic(err)
}
findPayloadRawValue := bson.RawValue{Type: findPayloadRawValueType, Value: findPayloadRawValueData}
findPayloadEncryptionOpts := options.Encrypt().
SetAlgorithm("Indexed").
SetKeyID(dataKeyID1).
SetQueryType("equality").
SetContentionFactor(1)
findPayloadEncryptedField, err := clientEnc.Encrypt(
context.TODO(),
findPayloadRawValue,
findPayloadEncryptionOpts)
if err != nil {
panic(err)
}
var resultSecure bson.M
coll.FindOne(context.TODO(), bson.D{{"firstName", findPayloadEncryptedField}}).Decode(&resultSecure)
if err != nil {
panic(err)
}
outputSecure, err := json.MarshalIndent(resultSecure, "", " ")
if err != nil {
panic(err)
}
fmt.Printf("\nFound document searching on explicitly encrypted field:\n%s\n", outputSecure)
BsonBinary findPayloadEncrypted = clientEncryption.encrypt(patientId, new EncryptOptions("Indexed").keyId(dataKeyId1).queryType("equality").contentionFactor(1L));
BsonDocument result = collection.find(eq("patientId", findPayloadEncrypted)).first();
System.out.println("Finding a document with manually encrypted field: " + result.toJson());
const findPayload = await encryption.encrypt(patientId, {
algorithm: "Indexed",
keyId: dek1._id,
queryType: "equality",
contentionFactor: 1,
});
console.log("Finding a document with manually encrypted field:");
console.log(await encryptedColl.findOne({ patientId: findPayload }));
find_payload = client_encryption.encrypt(
patientId,
Algorithm.INDEXED,
data_key_id_1,
query_type=QueryType.EQUALITY,
contention_factor=1,
)
doc = coll.find_one({"encryptedIndexed": find_payload})
print("\nReturned document:\n")
pprint.pprint(doc)

上記のコード スニペットの出力には、次のドキュメントが含まれている必要があります。

{
"__safeContent__": [
{
"Subtype": 0,
"Data": "LfaIuWm9o30MIGrK7GGUoStJMSNOjRgbxy5q2TPiDes="
}
],
"_id": "6303a770857952ca5e363fd2",
"firstName": "Jon",
"medications": ["Atorvastatin", "Levothyroxine"],
"patientId": 12345678
}

Tip

参照: 完全なコード

暗号化されたフィールドを含むドキュメントを取得するためのコードを表示するには 、 Queryable Encryption サンプル アプリケーションのリポジトリ を参照してください。

暗号化されたフィールドを含むドキュメントを取得するためのコードを表示するには 、 Queryable Encryption サンプル アプリケーションのリポジトリ を参照してください。

暗号化されたフィールドを含むドキュメントを取得するためのコードを表示するには 、 Queryable Encryption サンプル アプリケーションのリポジトリ を参照してください。

暗号化されたフィールドを含むドキュメントを取得するためのコードを表示するには 、 Queryable Encryption サンプル アプリケーションのリポジトリ を参照してください。

暗号化されたフィールドを含むドキュメントを取得するためのコードを表示するには 、 Queryable Encryption サンプル アプリケーションのリポジトリ を参照してください。

リモート KMS で Queryable Encryption を使用する方法のチュートリアルについては、「チュートリアル 」を参照してください。

Queryable Encryptionの仕組みについては、「明示的な暗号化 」を参照してください。

このガイドで言及されているトピックについて詳しくは、次のリンクを参照してください。

戻る

KMIP を使用する