【实操篇】详解MongoDB可搜索加密的使用方法!
@kenmaro 您好。我通常会发表关于秘密计算和同态加密等方面的文章。
对于与秘密计算相关的文章摘要,请参阅以下内容。
开始做密聊工程师已经过了2年半。
开始做密聊工程师已经过了3年。
关于私自进行密谋计算的圣诞日历的事情这篇文章是关于的话题。
《第二天》的文章
我在考虑要写。
有兴趣的人想不想参加圣诞日历呢?
期待收到你的回复。
总结在上一篇文章中,我们简要介绍了一篇关于MongoDB正式支持可搜索加密并开始作为测试版提供的文章。
这次我们对于关于MongoDB正式支持可搜索加密,并以测试版形式推出的文章进行了解说。
再次强调一下,
MongoDB 是众所周知的SaaS型数据库服务。
它是一种文档导向的数据库,也被称为NoSQL类型的数据库。
本文将实际尝试使用MongoDB的可搜索加密功能,即按照文档中的快速入门进行操作。
我想试着挑战一下。
为繁忙的人们提供便利MongoDBという世界最大規模のクラウド型DBが、検索可能暗号をサポートし、ベータ版として公開したよ
この記事では実際に検索可能暗号DBを使ってみるよ
AWS のKMSとの連携ができることを確認したよ
暗号化したいフィールドに対して暗号鍵を生成してみたよ
データをインサートして暗号状態で保存されていることを確認できたよ
暗号化されていないフィールドに対して一致クエリを投げると復号して返してくれることを確認できたよ
暗号化されているフィールドに対して一致クエリを投げるとエラーになってハマったので一旦検証を終了したよ
使ったコードはgithubに上げているよ
那么,我们开始吧。
首先
正如我在之前的文章中所提到的那样,
在可搜索加密数据库中,使用外部密钥管理系统是必需的。
从目前的情况来看,AWS、Azure和GCP这三个主要的云服务提供商似乎都可以使用,但是本次我打算尝试使用AWS。
所以,
我可能会跟进这个问题。
此外,作为准备
我們從這裡開始。
準備 + 錯誤集根据之前的需求,我们将逐步准备所需的物品。
Automatic Encryption Shared Library
获取并解压所需的加密库二进制文件。
本次存储在名为 “tmp_lib” 的文件夹中,
需要在后续程序中指定此路径。
mkdir tmp_lib && cd tmp_lib
wget https://downloads.mongodb.com/osx/mongo_crypt_shared_v1-macos-x86_64-enterprise-6.0.0-rc8.tgz?_ga=2.37189024.1258991149.1654659347-125648093.1654659347&_gac=1.150727364.1654660103.CjwKCAjw7vuUBhBUEiwAEdu2pBQ4IOlTXk-xf7_B_8edqZnsQkBERhlLtOKG2R_LyIXIhRr3gskXlRoCag4QAvD_BwE
tar -xzvf mongo_crypt_shared_v1-macos-x86_64-enterprise-6.0.0-rc8.tgz
- MongoDB driver Compatible with Queryable Encryption
获取MongoDB的驱动程序。
版本要遵循准确。Atlas在6.0以上的版本(专用服务器)上启动是必要的。
最初我为了省钱选择了共享服务器进行部署,但是发现它只支持5.x的版本,浪费了很多时间,所以建议你使用专用服务器并确保版本为6.0以上来进行部署。
顺便提一下,即使使用最新的版本来启动,也会出现连接错误,所以我认为使用6.0版本来启动比较可靠。
请注意教程代码。
在最終上你會需要複製貼上這個,但如果直接使用會發生錯誤,所以要小心。
ReferenceError: keyVaultColl is not defined
これは
const keyVaultColl = keyVaultClient.db(eDB).collection(eKV);
が記載漏れしています。
npm install mongodb-client-encryption
gitレポジトリにある
package.json
に従い、
npm install
しましょう。
"mongodb-client-encryption": "^2.2.0-alpha.0"
が必要です。
TypeError: A crypt_shared override path was specified
クリプトライブラリのパスは、
const extraOptions = {
cryptSharedLibPath: "/Users/xxx/Downloads/tmp_lib/lib/mongo_crypt_v1.dylib",
cryptSharedRequired: true,
};
というように指定します。
用户权限错误
MongoServerError: user is not allowed to do action [dropDatabase] on [Cluster0.]
MongoServerError: BSON field 'create.clusteredIndex' is the wrong type 'object', expected types '[bool, long, int, decimal, double']
有一个MongoDB Atlas版本的错误,当升级到6系列时,错误消失了。
连接错误
MongoServerSelectionError: connect ECONNREFUSED 127.0.0.1:27020
在MongoDB的Atlas版本中出现了错误,但是将它正确更新到6系列后,错误就消失了。
对于不熟悉MongoDB和NodeJS的人来说,需要进行简单的学习。
brew tap mongodb/brew
brew install mongodb-community
brew services start mongodb-community
brew install mongodb-atlas-cli
程序的解释用过
-
make_data_key.js
insert_encrypted_document.js
对于这个问题,我只需要用中文简单解释一下。
创建数据键.js .js)
是的,正如名字所示,
-
KMSのマスターキー
-
暗号化したいフィールドのコンフィギュレーション
から、フィールドを暗号化するための鍵を生成するプログラムです。
const eDB = "encryption";
const eKV = "__keyVault";
const keyVaultNamespace = `${eDB}.${eKV}`;
const secretDB = "Cluster0";
const secretCollection = "patients";
这段描述会生成在集合”encryption.__keyVault”中所需的密钥。
实际上,要存储的(加密的)数据表示为存储在 Cluster0.patients 集合中。
const clientEnc = new ClientEncryption(keyVaultClient, {
keyVaultNamespace: keyVaultNamespace,
kmsProviders: kmsProviders,
});
const dek1 = await clientEnc.createDataKey(provider, {
masterKey: masterKey,
keyAltNames: ["dataKey1"],
});
const dek2 = await clientEnc.createDataKey(provider, {
masterKey: masterKey,
keyAltNames: ["dataKey2"],
});
const dek3 = await clientEnc.createDataKey(provider, {
masterKey: masterKey,
keyAltNames: ["dataKey3"],
});
const dek4 = await clientEnc.createDataKey(provider, {
masterKey: masterKey,
keyAltNames: ["dataKey4"],
});
以此方式制作钥匙
const encryptedFieldsMap = {
[`${secretDB}.${secretCollection}`]: {
fields: [
{
keyId: dek1,
path: "phoneNumber",
bsonType: "string",
queries: { queryType: "equality" },
},
{
keyId: dek2,
path: "medications",
bsonType: "array",
},
{
keyId: dek3,
path: "patientRecord.ssn",
bsonType: "string",
queries: { queryType: "equality" },
},
{
keyId: dek4,
path: "patientRecord.billing",
bsonType: "object",
},
],
},
};
我将为要进行加密的字段分配各自的密钥。此外,在查询部分,通过指定相等性,明确表示要对该字段进行匹配搜索。这些是配置的一部分。
执行后,应该会生成如下的密钥。(使用MongoDB Compass进行确认。)
插入加密文档.js .js)接下来,关于这个程序,
实际上是要插入一条待加密的数据,然后对这条插入的数据进行处理。
-
鍵の存在を知らないクライアント(unencryptedClient)
鍵の存在を知っているクライアント(encryptedClient)
从两个客户端发出查询请求,并分别处理。
-
暗号化されているデータ
復号されたデータ
这是一个显示返回的程序。
详细说来,
await encryptedColl.insertOne({
firstName: "Jon",
lastName: "Doe",
patientId: 12345678,
address: "157 Electric Ave.",
phoneNumber: "012-3456-7890",
patientRecord: {
ssn: "987-65-4320",
billing: {
type: "Visa",
number: "4111111111111111",
},
},
medications: ["Atorvastatin", "Levothyroxine"],
});
通过插入一名患者的数据。
插入数据后,它被实际加密成这样。
其中,在 make_data_key.js 中指定的
-
phoneNumber
-
patientRecord.ssn
-
patientRecord.billing
medications
正在被加密处理。
此外,
await encryptedColl.findOne({ firstName: "Jon" })
await encryptedColl.findOne({ phoneNumber: "012-3456-7890" })
您可以在诸如此类的地方发送查询。
上方是针对未加密字段firstName的查询,
下方是针对已加密字段phoneNumber的查询。
查询的结果分别为
通过使用encryptedClient,我们可以确认数据被正确解密并进行查看。
验证结果
根据验证结果,
-
AWSのKMSで作ったマスター鍵との連携
-
暗号化したいフィールドの指定、コンフィギュレーション
-
データのインサート
-
インサートされたデータが暗号化されていることの確認
暗号化されていないフィールドに対しての一致検索、結果が復号されていることの確認
在中国的母语中进行改述:
虽然我能够完成,但关键的
暗号化されているフィールドに対しての一致検索
当尝试执行时遇到的错误无法解决,结果只能暂停并终止了。
试用后的感受我想要对加密字段进行匹配搜索,也就是使用可搜索加密来以加密状态提出查询并检查它是否有效,但由于后续遇到的错误而无法执行,时间也不够了,所以我暂时放弃了。我认为这可能是我的问题,所以我打算在有时间的时候再尝试一下。
与其他KMS的协作以及在字段上生成密钥的过程,数据插入等都(相对地)顺利进行,我觉得非常易用。
MongoDB的客户端目前只支持NodeJS,对于之前有使用经验的人来说,应该可以顺利进行验证。
我有NodeJS的经验,但从NodeJS使用MongoDB的经验来说,我只能验证过一两次,所以理解起来花了一些时间。
我觉得客户端的库、加密库等都是开源的,即使出错时,也可以通过阅读源代码进行调试,对开发者来说非常方便。
另外,由于官方的Git存储库中的程序出现了一些基本错误,所以我认为它还处于功能准备阶段。
实际上,通过仔细阅读代码,可以解决这个错误。
总结我已经将使用的代码上传到了GitHub上。
这次,我继续在之前的文章基础上追踪 MongoDB 6.0.0 及其后续版本中增加的“可搜索加密”功能的实际运用情况,并编写了教程代码。
对于我一直想要解决的密码领域的匹配搜索问题,很遗憾地我没能成功,但我认为可能是因为我理解不够,所以我打算再次尝试并更新文章。
这篇文章并没有详细说明功能,但在上篇文章中我们讨论了可搜索加密,因此非开发者的读者可以阅读那篇文章。
我个人很喜欢MongoDB这个服务,所以我打算继续关注它。
另外,在美国招募了与此类安全性相关的研究人员和开发者,如果您感兴趣的话,可以尝试与他们联系。顶尖开发者的两个推特账号是这样的。
Senny Kamara 先生 (Senny Kamara teacher)
Tarik Moataz さん可以在 Twitter 上找到,账号为 https://twitter.com/tarikmoataz。
所以,这回就到这里吧。
@kenmaro please provide the sentence you want me to paraphrase in Chinese.
MongoServerError: user is not allowed to do action [dropDatabase] on [Cluster0.]

MongoServerError: BSON field 'create.clusteredIndex' is the wrong type 'object', expected types '[bool, long, int, decimal, double']
有一个MongoDB Atlas版本的错误,当升级到6系列时,错误消失了。
连接错误
MongoServerSelectionError: connect ECONNREFUSED 127.0.0.1:27020
MongoServerSelectionError: connect ECONNREFUSED 127.0.0.1:27020
在MongoDB的Atlas版本中出现了错误,但是将它正确更新到6系列后,错误就消失了。
对于不熟悉MongoDB和NodeJS的人来说,需要进行简单的学习。
brew tap mongodb/brew
brew install mongodb-community
brew services start mongodb-community
brew install mongodb-atlas-cli
程序的解释用过
-
make_data_key.js
brew tap mongodb/brew
brew install mongodb-community
brew services start mongodb-community
brew install mongodb-atlas-cli
-
- make_data_key.js
- insert_encrypted_document.js
对于这个问题,我只需要用中文简单解释一下。
创建数据键.js .js)
是的,正如名字所示,
-
KMSのマスターキー
- KMSのマスターキー
-
- 暗号化したいフィールドのコンフィギュレーション
- から、フィールドを暗号化するための鍵を生成するプログラムです。
const eDB = "encryption";
const eKV = "__keyVault";
const keyVaultNamespace = `${eDB}.${eKV}`;
const secretDB = "Cluster0";
const secretCollection = "patients";
这段描述会生成在集合”encryption.__keyVault”中所需的密钥。
实际上,要存储的(加密的)数据表示为存储在 Cluster0.patients 集合中。
const clientEnc = new ClientEncryption(keyVaultClient, {
keyVaultNamespace: keyVaultNamespace,
kmsProviders: kmsProviders,
});
const dek1 = await clientEnc.createDataKey(provider, {
masterKey: masterKey,
keyAltNames: ["dataKey1"],
});
const dek2 = await clientEnc.createDataKey(provider, {
masterKey: masterKey,
keyAltNames: ["dataKey2"],
});
const dek3 = await clientEnc.createDataKey(provider, {
masterKey: masterKey,
keyAltNames: ["dataKey3"],
});
const dek4 = await clientEnc.createDataKey(provider, {
masterKey: masterKey,
keyAltNames: ["dataKey4"],
});
以此方式制作钥匙
const encryptedFieldsMap = {
[`${secretDB}.${secretCollection}`]: {
fields: [
{
keyId: dek1,
path: "phoneNumber",
bsonType: "string",
queries: { queryType: "equality" },
},
{
keyId: dek2,
path: "medications",
bsonType: "array",
},
{
keyId: dek3,
path: "patientRecord.ssn",
bsonType: "string",
queries: { queryType: "equality" },
},
{
keyId: dek4,
path: "patientRecord.billing",
bsonType: "object",
},
],
},
};
我将为要进行加密的字段分配各自的密钥。此外,在查询部分,通过指定相等性,明确表示要对该字段进行匹配搜索。这些是配置的一部分。
执行后,应该会生成如下的密钥。(使用MongoDB Compass进行确认。)

插入加密文档.js .js)接下来,关于这个程序,
实际上是要插入一条待加密的数据,然后对这条插入的数据进行处理。
-
鍵の存在を知らないクライアント(unencryptedClient)
- 鍵の存在を知らないクライアント(unencryptedClient)
- 鍵の存在を知っているクライアント(encryptedClient)
从两个客户端发出查询请求,并分别处理。
-
- 暗号化されているデータ
- 復号されたデータ
这是一个显示返回的程序。
详细说来,
await encryptedColl.insertOne({
firstName: "Jon",
lastName: "Doe",
patientId: 12345678,
address: "157 Electric Ave.",
phoneNumber: "012-3456-7890",
patientRecord: {
ssn: "987-65-4320",
billing: {
type: "Visa",
number: "4111111111111111",
},
},
medications: ["Atorvastatin", "Levothyroxine"],
});
通过插入一名患者的数据。
插入数据后,它被实际加密成这样。

-
- phoneNumber
-
- patientRecord.ssn
-
- patientRecord.billing
- medications
正在被加密处理。
此外,
await encryptedColl.findOne({ firstName: "Jon" })
await encryptedColl.findOne({ phoneNumber: "012-3456-7890" })
您可以在诸如此类的地方发送查询。
上方是针对未加密字段firstName的查询,
下方是针对已加密字段phoneNumber的查询。
查询的结果分别为


验证结果
根据验证结果,
-
AWSのKMSで作ったマスター鍵との連携
- AWSのKMSで作ったマスター鍵との連携
-
- 暗号化したいフィールドの指定、コンフィギュレーション
-
- データのインサート
-
- インサートされたデータが暗号化されていることの確認
- 暗号化されていないフィールドに対しての一致検索、結果が復号されていることの確認
在中国的母语中进行改述:
虽然我能够完成,但关键的
- 暗号化されているフィールドに対しての一致検索
当尝试执行时遇到的错误无法解决,结果只能暂停并终止了。
试用后的感受我想要对加密字段进行匹配搜索,也就是使用可搜索加密来以加密状态提出查询并检查它是否有效,但由于后续遇到的错误而无法执行,时间也不够了,所以我暂时放弃了。我认为这可能是我的问题,所以我打算在有时间的时候再尝试一下。
与其他KMS的协作以及在字段上生成密钥的过程,数据插入等都(相对地)顺利进行,我觉得非常易用。
MongoDB的客户端目前只支持NodeJS,对于之前有使用经验的人来说,应该可以顺利进行验证。
我有NodeJS的经验,但从NodeJS使用MongoDB的经验来说,我只能验证过一两次,所以理解起来花了一些时间。
我觉得客户端的库、加密库等都是开源的,即使出错时,也可以通过阅读源代码进行调试,对开发者来说非常方便。
另外,由于官方的Git存储库中的程序出现了一些基本错误,所以我认为它还处于功能准备阶段。
实际上,通过仔细阅读代码,可以解决这个错误。
总结我已经将使用的代码上传到了GitHub上。
这次,我继续在之前的文章基础上追踪 MongoDB 6.0.0 及其后续版本中增加的“可搜索加密”功能的实际运用情况,并编写了教程代码。
对于我一直想要解决的密码领域的匹配搜索问题,很遗憾地我没能成功,但我认为可能是因为我理解不够,所以我打算再次尝试并更新文章。
这篇文章并没有详细说明功能,但在上篇文章中我们讨论了可搜索加密,因此非开发者的读者可以阅读那篇文章。
我个人很喜欢MongoDB这个服务,所以我打算继续关注它。
另外,在美国招募了与此类安全性相关的研究人员和开发者,如果您感兴趣的话,可以尝试与他们联系。顶尖开发者的两个推特账号是这样的。
Senny Kamara 先生 (Senny Kamara teacher)
Tarik Moataz さん可以在 Twitter 上找到,账号为 https://twitter.com/tarikmoataz。
所以,这回就到这里吧。
@kenmaro please provide the sentence you want me to paraphrase in Chinese.