客户端字段级加密 (Client-Side Field Level Encryption)
4.2 版本中的新增功能。
官方 MongoDB 4.2 + 兼容驱动程序提供客户端字段级加密框架。 应用程序可以在通过线路将数据传输到服务器之前对文档中的字段进行加密。 只有能够访问正确加密密钥的应用程序才能解密和读取受保护的数据。 删除加密密钥会导致使用该密钥加密的所有数据永久不可读。
示例,执行身份验证的MongoDB 集群使用TLS加密来保护传输中的数据。 该集群还使用MongoDB加密存储引擎来保护磁盘上的数据。 考虑以下场景:
员工对集群及其托管具有管理访问权限。 作为正常职责的一部分,员工的访问权限级别允许他们查看解密状态的高敏感数据。
第三方提供商托管MongoDB 集群。 提供商存在主机或数据库级安全漏洞,未经授权的各方会访问权限解密状态的数据。
第三方数据分析公司可以访问权限包括隐私、个人或机密信息的数据。 第三方公司将解密的数据加载到不安全的数据存储卷中,未经授权的各方可以访问权限该数据存储卷。
在每种情况下,对MongoDB 集群或托管具有特权访问权限权限的用户都可以绕过加密并读取私有、特权或机密数据。 在将数据写入服务器之前,使用客户端字段级加密来保护数据,可以降低在事件网络或磁盘加密时暴露数据的风险。
请考虑以下文档:
{ "name" : "John Doe", "address" : { "street" : "1234 Main Street", "city" : "MongoDBVille", "zip" : 99999 }, "phone" : "949-555-1212", "ssn" : "123-45-6789" }
通过客户端字段级加密,应用程序可以专门加密 ssn
和phone
等敏感信息。 加密字段存储为具有binary data
子类型6 的 { } :
{ "name" : "John Doe", "address" : { "street" : "1234 Main Street", "city" : "MongoDBVille", "zip" : 99999 }, "phone" : BinData(6,"U2FsdGVkX1+CGIDGUnGgtS46+c7R5u17SwPDEmzyCbA="), "ssn" : BinData(6,"AaloEw285E3AnfjP+r8ph2YCvMI1+rWzpZK97tV6iz0jx") }
有关支持客户端字段级加密的官方4.2 + 兼容驱动程序的完整列表,请参阅驱动程序兼容性表。
有关使用部分MongoDB 4.2 + 兼容驱动程序配置字段级加密的端到端过程,请参阅《客户端字段级加密指南》。
支持的加密方法
MongoDB支持两种使用官方MongoDB 4.2 + 兼容驱动程序进行客户端字段级加密的方法:
- 对字段进行显式(手动)加密
官方MongoDB 4.2+ 兼容驱动程序、
mongosh
和MongoDB 4。2 或更高版本的旧版mongo
shell支持使用特定数据加密密钥和加密算法对字段进行显式加密或解密。应用程序必须修改与构造读取和写入操作相关的任何代码,以包含通过驱动程序加密库的加密/解密逻辑。 应用程序负责根据每个操作选择适当的数据加密密钥进行加密/解密。
有关更多信息,请参阅显式(手动)客户端字段级加密。
- 字段自动加密
注意
Enterprise 版功能
字段级加密的自动功能仅在 MongoDB Enterprise 4.2 或更高版本以及 MongoDB Atlas 4.2 或更高版本集群中可用。
官方MongoDB 4.2+ 兼容驱动程序、
mongosh
和MongoDB 4。2 或更高版本的旧版mongo
shell支持在写入操作中自动加密字段。应用程序必须创建一个数据库连接对象(例如
MongoClient
)替换为自动加密配置设置。 配置设置必须包含使用JSON schema 4草案 标准语法 的严格子集的自动加密规则 和特定于加密的模式关键字。应用程序不必修改与读/写入操作相关的代码。 有关自动加密规则的完整文档,请参阅自动自动加密规则。有关详细信息,请参阅自动客户端字段级加密。
MongoDB 4.2+ 兼容驱动程序、 mongosh
和MongoDB 4.2 或更高版本的旧版mongo
shell会自动解密使用客户端字段级加密创建的Binary
子类型 6 对象。 有关自动解密的更多信息,请参阅自动字段解密。
重要
MongoDB客户端字段级加密仅支持加密文档中的单个字段。 要加密整个文档,必须加密文档中的每个单独字段。
加密组件
下图说明了驾驶员和每个加密组件之间的关系:
libmongocrypt
是 Apache 许可的开源 官方MongoDB4 使用的核心加密库。2 +兼容的驱动程序、mongosh
和MongoDB 4。2 或更高版本的旧版mongo
shell ,用于支持客户端字段级加密。 某些驱动程序可能需要特定的集成步骤来安装或链接库。 请参阅驾驶员文档以获取更完整的信息。自动加密共享库支持自动客户端字段级加密,并且仅适用于MongoDB Enterprise。 自动加密共享库不执行加密功能。 共享库是
mongocryptd
的首选替代方案,并且不需要生成新进程。 仍支持mongocryptd
。密钥保管库是一个MongoDB集合,其中存储用于加密值的所有数据加密密钥。 数据加密密钥本身在存储到集合之前使用客户主密钥(集合扫描 ) 进行加密。 密钥保管库可能位于与存储加密数据不同的MongoDB 集群上。
KMS ( KMS )存储用于加密数据加密密钥的客户主密钥(集合扫描 )。 MongoDB支持以下KMS提供程序:
存储加密数据的MongoDB 集群还可以实施客户端字段级加密。 有关更多信息,请参阅实施字段级加密模式。
加密算法
MongoDB客户端字段级加密使用 encrypt-then-MAC 方法并结合确定性或随机初始化向量来加密字段值。 MongoDB 仅 支持 AEAD 256具有 HMAC-SHA-512 MAC 的 AES- -CBC加密算法。
确定性加密
确定性加密算法可确保每次执行算法时,给定的输入值始终加密为相同的输出值。 虽然确定性加密为读取操作提供了更好的支持,但关联关联基数较低的加密数据容易受到频率分析恢复的影响。
对于不在读取操作中使用的敏感字段,应用程序可以使用随机加密来提高保护,防止通过频率分析恢复数据。
随机加密
随机加密算法可确保每次执行算法时,给定的输入值始终加密为不同的输出值。 虽然随机加密为数据机密性提供了最强有力的保证,但它也阻止了对任何必须对加密字段进行操作以评估查询的读取操作的支持。
随机加密还支持加密整个对象或数组。 示例,考虑以下文档:
{ "personal_information" : { "ssn" : "123-45-6789", "credit_score" : 750, "credit_cards" : [ "1234-5678-9012-3456", "9876-5432-1098-7654"] }, "phone_numbers" : [ "(212) 555-0153" ] }
使用随机加密算法加密 personal_information
和 phone_numbers
字段会加密整个对象。虽然这可以保护嵌套在这些字段下的所有字段,但它也会阻止对这些嵌套字段进行查询。
对于在读取操作中使用的敏感字段,应用程序必须使用确定性加密来改进对加密字段的读取支持。
自动字段解密
BinData
blob元数据包括数据加密密钥_id
和用于加密二进制数据的加密算法。 4.2+ 兼容驱动程序、 mongosh
和MongoDB 4。2 或更高版本的旧版mongo
shell使用此元数据来尝试对BinData
子类型 6 对象进行自动解密。 自动解密进程的工作原理如下:
检查
BinData
blob元数据中用于加密该值的数据加密密钥和加密算法。检查当前数据库连接中配置的密钥保管库中的指定数据加密密钥。 如果密钥保管库不包含指定的密钥,则自动解密将失败,并且驾驶员会返回
BinData
blob。检查用于加密密钥材料的客户主密钥 (CMK) 的数据加密密钥元数据。
对于Amazon Web Services KMS 、 Azure Key Vault或Google Cloud Platform KMS ,将数据加密密钥发送给 KMS 提供商进行解密。 如果 CMK 不存在,或者连接配置未授予对 CMK 的访问权限,则解密失败,并且驱动程序会返回
BinData
blob。对于本地管理的密钥,检索本地密钥并对数据加密密钥进行解密。 如果未使用数据库配置中指定的本地密钥来加密数据加密密钥,则解密将失败,驾驶员将返回
BinData
blob。使用解密的数据加密密钥和适当的算法对
BinData
值进行解密。
有权访问 MongoDB Server 的应用程序如果无权访问所需的主密钥和数据加密密钥,则无法解密BinData
值。
有关为客户端字段级加密配置数据库连接的更多信息,请参阅Mongo()
构造函数或遵循首选驱动程序客户端构造方法的文档。
执行字段级加密模式
从MongoDB 4.2开始,服务器支持使用模式验证来实施对集合中的特定字段进行加密。 使用自动加密规则关键字和$jsonSchema
验证对象来指示哪些字段需要加密。 如果指定字段不是Binary (BinData)
子类型6对象,服务器会拒绝对该集合的任何写入操作。
例如,以下collMod
命令会修改hr.employees
集合以包含validator
。 $jsonSchema
验证对象包含客户端字段级加密关键字,以表明:
db.getSiblingDB("hr").runCommand( { "collMod" : "employees", "validator" : { "$jsonSchema" : { "bsonType" : "object", "properties" : { "taxid" : { "encrypt" : { "keyId" : [UUID("e114f7ad-ad7a-4a68-81a7-ebcb9ea0953a")], "algorithm" : "AEAD_AES_256_CBC_HMAC_SHA_512-Random", } }, "taxid-short" : { "encrypt" : { "keyId" : [UUID("33408ee9-e499-43f9-89fe-5f8533870617")], "algorithm" : "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic", "bsonType" : "string" } } } } } } )
执行显式(手动)字段级加密的客户端 必须encrypt
taxid
taxid-short
在发出写入操作 之前$jsonSchema
使用与远程 相同的设置 至少 和 字段。
执行自动客户端字段级加密的客户端具有特定行为,具体取决于数据库连接配置:
注意
客户端字段级自动加密仅适用于MongoDB Enterprise 4.2或更高版本。
如果连接
ClientSideFieldLevelEncryptionOptions
schemaMap
对象包含指定集合的密钥,则客户端使用该对象执行自动字段级加密并忽略远程模式。 本地规则必须至少加密taxid
和taxid-short
字段。如果连接
ClientSideFieldLevelEncryptionOptions
schemaMap
对象不包含指定集合的密钥,客户端会下载该集合的服务器端远程模式,并使用它来执行自动字段级加密。此配置要求客户端相信服务器具有关于自动字段级加密的有效模式。 客户端仅使用远程模式执行字段级自动加密,而不会执行模式中指定的任何其他验证规则。
由于MongoDB 服务器无法解密或内省加密字段的内容,因此无法验证客户端是否使用了指定的加密选项来加密给定字段。 这允许两个客户端针对特定字段使用不同的 keyID 或加密算法插入加密数据。 虽然某些工作负载可能需要独立的字段级加密实施,但跨客户端对字段的加密选项实施不一致可能会导致针对加密字段的查询出现错误或意外行为。
示例,客户端A
使用随机加密对PII
字段进行加密,而客户端B
使用确定性加密对PII
字段进行加密。 随机加密算法始终返回不同的唯一值,而确定性算法始终返回相同的值。 期望该字段具有确定性加密数据的查询会返回不一致的结果,因为服务器无法匹配任何随机加密字段。
驱动程序兼容性表
MongoDB 4.2客户端字段级加密仅适用于以下官方4.2 + 兼容驾驶员版本:
驱动 | 支持的版本 | 快速入门/教程 |
---|---|---|
| ||
| ||
| ||
| ||
| ||
| ||
| ||
| ||
| ||
|
有关语法和实施示例,请参阅驱动程序参考文档。