Couchbase 字段级加密
Couchbase 支持 字段级加密。本节文档介绍如何在 Spring Data Couchbase 中使用它。
需求
- Spring Data Couchbase 5.0.0-RC1 或更高版本。
概述
带 com.couchbase.client.java.encryption.annotation.Encrypted
注解标注的字段(@Encrypted
)将在写入时自动加密,在读取时自动解密。可以通过指定 @Encrypted(migration = Encrypted.Migration.FROM_UNENCRYPTED)
将未加密的字段迁移为加密字段
开始使用与配置
依赖项
字段级加密可通过依赖项获得(请参见 Field Level Encryption)
<groupId>com.couchbase.client</groupId>
<artifactId>couchbase-encryption</artifactId>
HashiCorp Vault Transit 集成需要 Spring Vault
<groupId>org.springframework.vault</groupId>
<artifactId>spring-vault-core</artifactId>
提供 CryptoManager
需要通过重写 cryptoManager()
方法在 AbstractCouchbaseConfiguration
中提供一个 CryptoManager
。这个 CryptoManager
将被 Spring Data Couchbase 使用,也会被从 CouchbaseClientFactory
直接调用的 Couchbase Java SDK 调用。
@Override
protected CryptoManager cryptoManager() {
KeyStore javaKeyStore = KeyStore.getInstance("MyKeyStoreType");
FileInputStream fis = new java.io.FileInputStream("keyStoreName");
char[] password = { 'a', 'b', 'c' };
javaKeyStore.load(fis, password);
Keyring keyring = new KeyStoreKeyring(javaKeyStore, keyName -> "swordfish");
// AES-256 authenticated with HMAC SHA-512. Requires a 64-byte key.
AeadAes256CbcHmacSha512Provider provider = AeadAes256CbcHmacSha512Provider.builder().keyring(keyring).build();
CryptoManager cryptoManager = DefaultCryptoManager.builder().decrypter(provider.decrypter())
.defaultEncrypter(provider.encrypterForKey("myKey")).build();
return cryptoManager;
}
定义字段为加密字段。
-
@Encrypted 定义一个加密字段。
-
@Encrypted(migration = Encrypted.Migration.FROM_UNENCRYPTED) 定义一个字段,当读取时可能是加密的,也可能不是。写入时该字段会被加密。
-
@Encrypted(encrypter = "<encrypterAlias>") 指定用于加密的加密器别名。请注意,这不是算法,而是在将加密器添加到 CryptoManager 时指定的名称。
示例
示例 1. AbstractCouchbaseConfiguration
@Configuration
@EnableCouchbaseRepositories("<parent-dir-of-repository-interfaces>")
@EnableReactiveCouchbaseRepositories("<parent-dir-of-repository-interfaces>")
static class Config extends AbstractCouchbaseConfiguration {
// Usual Setup
@Override public String getConnectionString() { /* ... */ }
@Override public String getUserName() { /* ... */ }
@Override public String getPassword() { /* ... */ }
@Override public String getBucketName() { /* ... */ }
/* provide a cryptoManager */
@Override
protected CryptoManager cryptoManager() {
KeyStore javaKeyStore = KeyStore.getInstance("MyKeyStoreType");
FileInputStream fis = new java.io.FileInputStream("keyStoreName");
char[] password = { 'a', 'b', 'c' };
javaKeyStore.load(fis, password);
Keyring keyring = new KeyStoreKeyring(javaKeyStore, keyName -> "swordfish");
// AES-256 authenticated with HMAC SHA-512. Requires a 64-byte key.
AeadAes256CbcHmacSha512Provider provider = AeadAes256CbcHmacSha512Provider.builder().keyring(keyring).build();
CryptoManager cryptoManager = DefaultCryptoManager.builder().decrypter(provider.decrypter())
.defaultEncrypter(provider.encrypterForKey("myKey")).build();
return cryptoManager;
}
}
示例 2. 文档中的注释
@Document
public class AddressWithEncStreet extends Address {
private @Encrypted String encStreet;
.
.
示例 3. 代码中的使用
AddressWithEncStreet address = new AddressWithEncStreet(); // plaintext address with encrypted street
address.setCity("Santa Clara");
address.setEncStreet("Olcott Street");
addressEncryptedRepository.save(address);
示例 4. 结果文档
{
"_class": "AddressWithEncStreet",
"city": "Santa Clara",
"encrypted$encStreet": {
"alg": "AEAD_AES_256_CBC_HMAC_SHA512",
"ciphertext": "A/tJALmtixTxqj77ZUcUgMklIt3372DKD7l5FvbCzHNJMplbgQEv0RgSbxIfiRNr+uW2H7cokkcCW/F5YnQoXA==",
"kid": "myKey"
}
}