此版本仍处于开发阶段,尚未被视为稳定版本。如需使用最新稳定版本,请采用 Spring Data Couchbase 6.0.4spring-doc.cadn.net.cn

Couchbase 字段级加密

Couchbase 支持 字段级加密。本节介绍如何在 Spring Data Couchbase 中使用它。spring-doc.cadn.net.cn

要求

概述

使用 com.couchbase.client.java.encryption.annotation.Encrypted (@Encrypted) 注解的字段将在写入时自动加密,并在读取时自动解密。未加密的字段可以通过指定 @Encrypted(migration = Encrypted.Migration.FROM_UNENCRYPTED) 迁移为加密状态。spring-doc.cadn.net.cn

入门与配置

依赖项

字段级加密功能可通过以下依赖项使用(请参阅 字段级加密spring-doc.cadn.net.cn

    <groupId>com.couchbase.client</groupId>
    <artifactId>couchbase-encryption</artifactId>

HashiCorp Vault Transit 集成需要 Spring Vaultspring-doc.cadn.net.cn

    <groupId>org.springframework.vault</groupId>
    <artifactId>spring-vault-core</artifactId>

提供 CryptoManager

需要通过重写 AbstractCouchbaseConfiguration 中的 cryptoManager() 方法来提供 CryptoManager。该 CryptoManager 将由 Spring Data Couchbase 以及从 CouchbaseClientFactory 发出的 Couchbase Java SDK 直接调用所使用。spring-doc.cadn.net.cn

@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;
}

定义字段为加密。

  1. @Encrypted 定义一个字段为加密状态。spring-doc.cadn.net.cn

  2. @Encrypted(migration = Encrypted.Migration.FROM_UNENCRYPTED) 定义了一个字段,该字段在读取时可能已加密也可能未加密。写入时将被加密。spring-doc.cadn.net.cn

  3. @Encrypted(encrypter = "<encrypterAlias>") 指定用于加密的加密器别名。注意,这不是算法名称,而是在将加密器添加到 CryptoManager 时指定的名称。spring-doc.cadn.net.cn

例举

示例 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"
   }
}