客户端加密
从 v 4.2开始, MongoDB 支持客户端加密。 除了提供其他 MongoDB 加密功能外,客户端加密还允许管理员和开发人员加密特定数据字段。
通过字段级加密,开发者可以在客户端加密字段,无需任何服务器端配置或指令。 客户端字段级加密支持的工作负载中,应用程序必须保证包括服务器管理员在内的未经授权方无法读取加密数据。
注意
本指南使用 Observable
隐式,如快速入门入门知识中所述。
安装
在项目中开始使用字段级加密的推荐方法是使用依赖项管理系统。 除驱动程序外,字段级加密还需要其他软件包。
注意
有关如何安装 Scala 驱动程序的说明,请参阅安装指南。
libmongocrypt
有一个单独的 JAR 文件,其中包含libmongocrypt
绑定。
如果您使用的是 Maven 要管理您的软件包,请将以下条目添加到您的pom.xml
依赖项列表中:
<dependencies> <dependency> <groupId>org.mongodb</groupId> <artifactId>mongodb-crypt</artifactId> <version>1.2.1</version> </dependency> </dependencies>
如果您使用 Gradle 要管理您的包,请将以下条目添加到您的依赖项列表中:
dependencies { implementation 'org.mongodb:mongodb-crypt:1.2.1' }
mongocryptd 配置
libmongocrypt
绑定要求mongocryptd
守护进程/进程正在运行。 可以通过在extraOptions
设置中设置mongocryptdURI
,在AutoEncryptionSettings
类中配置特定的守护进程/进程 URI。
示例
自动加密和解密
以下示例是一个示例应用,它假设已在MongoDB中创建密钥和模式。 该示例使用本地密钥,但您也可以使用Amazon Web Services / Azure / GCP KMS 。 encryptedField
字段中的数据在插入时自动加密,在客户端端使用查找时自动解密。
代码示例来自 ClientSideEncryptionSimpleTour.scala 驾驶员源代码Github 存储库中的文件。
import java.security.SecureRandom import org.mongodb.scala.{AutoEncryptionSettings, Document, MongoClient, MongoClientSettings} import tour.Helpers._ import scala.collection.JavaConverters._ object ClientSideEncryptionSimpleTour { def main(args: Array[String]): Unit = { val localMasterKey = new Array[Byte](96) new SecureRandom().nextBytes(localMasterKey) val kmsProviders = Map("local" -> Map[String, AnyRef]("key" -> localMasterKey).asJava).asJava val keyVaultNamespace = "admin.datakeys" val autoEncryptionSettings = AutoEncryptionSettings.builder() .keyVaultNamespace(keyVaultNamespace).kmsProviders(kmsProviders).build() val clientSettings = MongoClientSettings.builder() .autoEncryptionSettings(autoEncryptionSettings).build() val mongoClient = MongoClient(clientSettings) val collection = mongoClient.getDatabase("test").getCollection("coll") collection.drop().headResult() collection.insertOne(Document("encryptedField" -> "123456789")).headResult() collection.find().first().printHeadResult() // release resources mongoClient.close() } }
注意
自动加密是企业独有的功能。
指定数据加密密钥和加密字段
以下示例展示了如何配置AutoEncryptionSettings
实例以创建新密钥并设立JSON schema映射。
代码示例来自 ClientSideEncryptionAutoEncryptionSettingsTour.scala 驾驶员源代码Github 存储库中的文件。
import java.security.SecureRandom import java.util.Base64 import scala.collection.JavaConverters._ import org.mongodb.scala._ import org.mongodb.scala.bson.BsonDocument import org.mongodb.scala.model.vault.DataKeyOptions import org.mongodb.scala.vault.ClientEncryptions import tour.Helpers._ ... val keyVaultNamespace = "admin.datakeys" val clientEncryptionSettings = ClientEncryptionSettings.builder() .keyVaultMongoClientSettings( MongoClientSettings.builder().applyConnectionString(ConnectionString("mongodb://localhost")).build()) .keyVaultNamespace(keyVaultNamespace).kmsProviders(kmsProviders).build() val clientEncryption = ClientEncryptions.create(clientEncryptionSettings) val dataKey = clientEncryption.createDataKey("local", DataKeyOptions()).headResult() val base64DataKeyId = Base64.getEncoder.encodeToString(dataKey.getData) val dbName = "test" val collName = "coll" val autoEncryptionSettings = AutoEncryptionSettings.builder() .keyVaultNamespace(keyVaultNamespace) .kmsProviders(kmsProviders) .schemaMap(Map(s"$dbName.$collName" -> BsonDocument( s"""{ properties: { encryptedField: { encrypt: { keyId: [{ "$$binary": { "base64": "$base64DataKeyId", "subType": "04" } }], bsonType: "string", algorithm: "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" } } }, bsonType: "object" }""")).asJava) .build()
显式加密和解密
显式加密和解密是MongoDB Community的一项功能,不使用 mongocryptd
进程。 显式加密由ClientEncryption
类提供。
代码示例来自 ClientSideEncryptionExplicitEncryptionAndDecryptionTour.scala 驾驶员源代码Github 存储库中的文件。
// This would have to be the same master key as was used to create the encryption key val localMasterKey = new Array[Byte](96) new SecureRandom().nextBytes(localMasterKey) val kmsProviders = Map("local" -> Map[String, AnyRef]("key" -> localMasterKey).asJava).asJava val keyVaultNamespace = new MongoNamespace("encryption.testKeyVault") val clientSettings = MongoClientSettings.builder().build() val mongoClient = MongoClient(clientSettings) // Set up the key vault for this example val keyVaultCollection = mongoClient.getDatabase(keyVaultNamespace.getDatabaseName) .getCollection(keyVaultNamespace.getCollectionName) keyVaultCollection.drop().headResult() // Ensure that two data keys cannot share the same keyAltName. keyVaultCollection.createIndex(Indexes.ascending("keyAltNames"), new IndexOptions().unique(true) .partialFilterExpression(Filters.exists("keyAltNames"))) val collection = mongoClient.getDatabase("test").getCollection("coll") collection.drop().headResult() // Create the ClientEncryption instance val clientEncryptionSettings = ClientEncryptionSettings .builder() .keyVaultMongoClientSettings( MongoClientSettings.builder() .applyConnectionString(ConnectionString("mongodb://localhost")).build() ) .keyVaultNamespace(keyVaultNamespace.getFullName) .kmsProviders(kmsProviders) .build() val clientEncryption = ClientEncryptions.create(clientEncryptionSettings) val dataKeyId = clientEncryption.createDataKey("local", DataKeyOptions()).headResult() // Explicitly encrypt a field val encryptedFieldValue = clientEncryption.encrypt(BsonString("123456789"), EncryptOptions("AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic").keyId(dataKeyId)) .headResult() collection.insertOne(Document("encryptedField" -> encryptedFieldValue)).headResult() val doc = collection.find.first().headResult() println(doc.toJson()) // Explicitly decrypt the field println( clientEncryption.decrypt(doc.get[BsonBinary]("encryptedField").get).headResult() )
显式加密和自动解密
虽然自动加密需要MongoDB 4.2企业版或MongoDB 4.2 Atlas 集群,支持所有用户自动解密。 要配置自动解密而不自动加密,设立bypassAutoEncryption(true)
。
代码示例来自 ClientSideEncryptionExplicitEncryptionOnlyTour.scala 驾驶员源代码Github 存储库中的文件。
... val clientSettings = MongoClientSettings.builder() .autoEncryptionSettings(AutoEncryptionSettings.builder() .keyVaultNamespace(keyVaultNamespace.getFullName) .kmsProviders(kmsProviders) .bypassAutoEncryption(true) .build()) .build() val mongoClient = MongoClient(clientSettings) ... // Explicitly encrypt a field val encryptedFieldValue = clientEncryption.encrypt(BsonString("123456789"), EncryptOptions("AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic").keyId(dataKeyId)) .headResult() collection.insertOne(Document("encryptedField" -> encryptedFieldValue)).headResult() val doc = collection.find.first().headResult() println(doc.toJson())