client-side-field-level-encryption"> client-side-field-level-encryption"> 集成 MongoDB 客户端字段级加密

客户端字段级加密,简称 CSFLE,是一种在 MongoDB 中以加密格式存储数据的工具。例如,您不是以纯文本字符串形式存储 name 属性,CSFLE 表示 MongoDB 会将您的文档存储为带有 name 的加密缓冲区。对于无法解密数据的客户端,生成的文档将类似于以下内容。

{
  "_id" : ObjectId("647a3207661e3a3a1bc3e614"),
  "name" : BinData(6,"ASrIv7XfokKwiCUJEjckOdgCG+u6IqavcOWX8hINz29MLvcKDZ4nnjCnPFZG+0ftVxMdWgzu6Vdh7ys1uIK1WiaPN0SqpmmtL2rPoqT9gfhADpGDmI60+vm0bJepXNY1Gv0="),
  "__v" : 0
}

您可以在 MongoDB CSFLE 文档关于 CSFLE 在 Node.js 中的这篇博文 中了解更多关于 CSFLE 的信息。

请注意,Mongoose 目前**没有**任何特定于 Mongoose 的 CSFLE API。Mongoose 将所有与 CSFLE 相关的工作委托给 MongoDB Node.js 驱动程序,因此 autoEncryption 选项 用于 mongoose.connect()mongoose.createConnection() 是您放置所有与 CSFLE 相关的配置的位置。Mongoose 模式目前不支持 CSFLE 配置。

使用 Mongoose 设置字段级加密

首先,您需要安装 mongodb-client-encryption npm 包。这是 MongoDB 用于设置加密密钥的官方软件包。

npm install mongodb-client-encryption

您还需要确保已安装 mongocryptd。mongocryptd 是与 MongoDB 服务器不同的进程,您需要运行它才能使用字段级加密。您可以自己运行 mongocryptd,也可以确保它在系统 PATH 上,MongoDB Node.js 驱动程序将为您运行它。 您可以在此处阅读有关 mongocryptd 的更多信息

设置并运行 mongocryptd 后,首先需要创建新的加密密钥,如下所示。请记住,以下示例只是一个简单的示例,可帮助您入门。以下示例中的加密密钥不安全;MongoDB 建议使用 KMS

const { ClientEncryption } = require('mongodb-client-encryption');
const mongoose = require('mongoose');
const { Binary } = require('mongodb');

run().catch(err => console.log(err));

async function run() {
  /* Step 1: Connect to MongoDB and insert a key */

  // Create a very basic key. You're responsible for making
  // your key secure, don't use this in prod :)
  const arr = [];
  for (let i = 0; i < 96; ++i) {
    arr.push(i);
  }
  const key = Buffer.from(arr);

  const keyVaultNamespace = 'client.encryption';
  const kmsProviders = { local: { key } };

  const uri = 'mongodb://127.0.0.1:27017/mongoose_test';
  const conn = await mongoose.createConnection(uri, {
    autoEncryption: {
      keyVaultNamespace,
      kmsProviders
    }
  }).asPromise();
  const encryption = new ClientEncryption(conn.client, {
    keyVaultNamespace,
    kmsProviders,
  });

  const _key = await encryption.createDataKey('local');
}

获得加密密钥后,您可以使用具有 schemaMap 的独立 Mongoose 连接来创建连接,该连接使用 JSON 模式语法定义哪些字段被加密,如下所示。

/* Step 2: connect using schema map and new key */
await mongoose.connect('mongodb://127.0.0.1:27017/mongoose_test', {
  // Configure auto encryption
  autoEncryption: {
    keyVaultNamespace,
    kmsProviders,
    schemaMap: {
      'mongoose_test.tests': {
        bsonType: 'object',
        encryptMetadata: {
          keyId: [_key]
        },
        properties: {
          name: {
            encrypt: {
              bsonType: 'string',
              algorithm: 'AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic'
            }
          }
        }
      }
    }
  }
});

使用上述连接,如果您创建名为“Test”并使用“tests”集合的模型,则所有文档的 name 属性都将被加密。

// 'super secret' will be stored as 'BinData' in the database,
// if you query using the `mongo` shell.
const Model = mongoose.model('Test', mongoose.Schema({ name: String }));
await Model.create({ name: 'super secret' });