0
0

More than 1 year has passed since last update.

Couchbase Server Java SDK解説: フィールドレベルの暗号化

Last updated at Posted at 2021-09-06

Couchbase Server Java SDKを使用して、JSONドキュメントの特定のフィールドを暗号化および復号化することができます。

CouchbaseのJava SDK暗号化ライブラリは、独自の暗号化コンポーネントを実装するためのフレームワークを提供します。

ライブラリ

フィールドレベルの暗号化機能は、エンタープライズサブスクリプションライセンス契約により、提供されるオプションのライブラリとして提供されています。

暗号化ライブラリを使用するには、プロジェクト構成ファイルに明示的に含める必要があります。
Mavenのdependency(依存関係)セクションを例示します。

<dependency>
    <groupId>com.couchbase.client</groupId>
    <artifactId>couchbase-encryption</artifactId>
    <version>${version}</version>
</dependency>

使用法

構成

フィールドレベルの暗号化を有効にするには、ClusterEnvironmentCryptoManagerを指定します。

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();

ClusterEnvironment env = ClusterEnvironment.builder().cryptoManager(cryptoManager).build();

Cluster cluster = Cluster.connect("localhost",
    ClusterOptions.clusterOptions("username", "password").environment(env));

データバインディングの例

データクラスの暗号化するフィールドに、@Encryptedアノーテーションを付けます。

public class Employee {
  @Encrypted
  private boolean replicant;

  // alternatively you could annotate the getter or setter
  public boolean isReplicant() {
    return replicant;
  }

  public void setReplicant(boolean replicant) {
    this.replicant = replicant;
  }
}

Employeeレコードを作成してCouchbaseに保存してみます。

Employee employee = new Employee();
employee.setReplicant(true);
collection.upsert("employee:1234", employee); // encrypts the "replicant" field

JsonObjectのフィールドが暗号化されていることを確認するために、ドキュメントとして取得します。

JsonObject encrypted = collection.get("employee:1234").contentAsObject(); // does not decrypt anything

System.out.println(encrypted);

contentAsObject()メソッドでは、何も復号化しないため、出力は次のようになります。

{
  "encrypted$replicant": {
    "alg": "AEAD_AES_256_CBC_HMAC_SHA512",
    "ciphertext": "xwcxyUyZ.....",
    "kid": "myKey"
  }
}

次に、データバインディングを使用してデータを読み取ります。

Employee readItBack = collection.get("employee:1234").contentAs(Employee.class); // decrypts the "replicant" field

System.out.println(readItBack.isReplicant());

最後の行ではtrueが出力されます。

操作モード

2つの操作モードが利用可能です:

  • Jacksonデータバインディング中の透過的な暗号化/復号化

  • JsonObjectCryptoを使用した手動フィールド編集

カスタムObjectMapperの使用

データバインディング中に暗号化/復号化を有効にするコードは、EncryptionModuleというJacksonモジュールとしてパッケージ化されています。

ドキュメントをシリアル化するときに独自にカスタマイズしたObjectMapperを提供する場合は、ObjectMapperに、カスタマイズを行ったCryptoManagerを用いて初期化したEncryptionModuleクラスをObjectMapperに登録します。

フィールドレベルの暗号化をサポートする独自の(ObjectMapperに基づく)カスタムJSONシリアライザーを使用するようにクラスター環境を構成する方法を紹介します。

// CryptoManager cryptoManager = createMyCryptoManager();
KeyStore javaKeyStore = KeyStore.getInstance("MyKeyStoreType");
FileInputStream fis = new java.io.FileInputStream("keyStoreName");
char[] ksPassword = { 'a', 'b', 'c' };
javaKeyStore.load(fis, ksPassword);
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();

ObjectMapper mapper = new ObjectMapper();
mapper.registerModule(new JsonValueModule()); // for JsonObject
mapper.registerModule(new EncryptionModule(cryptoManager));

// Here you can register more modules, add mixins, enable features, etc.

ClusterEnvironment env = ClusterEnvironment.builder().cryptoManager(cryptoManager)
    .jsonSerializer(JacksonJsonSerializer.create(mapper)).build();

Cluster cluster = Cluster.connect(connectionString,
    ClusterOptions.clusterOptions(username, password).environment(env));

JsonObjectCrypto

復号化するフィールドをさらに制御する必要がある場合、またはCouchbaseのJsonObjectツリーモデルを使用することを望む場合、JsonObjectCryptoインスタンスを使用して、JsonObjectの暗号化されたフィールド値を読み書きできます。

JsonObject document = JsonObject.create();
JsonObjectCrypto crypto = document.crypto(collection);

crypto.put("locationOfBuriedTreasure", "Between palm trees");

// This displays the encrypted form of the field
System.out.println(document);

collection.upsert("treasureMap", document);

JsonObject readItBack = collection.get("treasureMap").contentAsObject();
JsonObjectCrypto readItBackCrypto = crypto.withObject(readItBack);
System.out.println(readItBackCrypto.getString("locationOfBuriedTreasure"));

暗号化キーの作成

このライブラリに含まれているAEAD_AES_256_CBC_HMAC_SHA512アルゴリズムは、64バイト長の暗号化キーを使用します。

以下は、暗号化キーを含むJavaキーストアファイルを作成する方法を示す例です。

KeyStore keyStore = KeyStore.getInstance("JCEKS");
keyStore.load(null); // initialize new empty key store

// Generate 64 random bytes
SecureRandom random = new SecureRandom();
byte[] keyBytes = new byte[64];
random.nextBytes(keyBytes);

// Add a new key called "my-key" to the key store
KeyStoreKeyring.setSecretKey(keyStore, "my-key", keyBytes, "protection-password".toCharArray());

// Write the key store to disk
try (OutputStream os = new FileOutputStream("MyKeystoreFile.jceks")) {
  keyStore.store(os, "integrity-password".toCharArray());
}

上記で作成したファイル(MyKeystoreFile.jceks)を使用して、フィールドレベル暗号化で使用するためのキーストアを作成する方法は次のとおりです。

KeyStore keyStore = KeyStore.getInstance("JCEKS");
try (InputStream is = new FileInputStream("MyKeystoreFile.jceks")) {
  keyStore.load(is, "integrity-password".toCharArray());
}

KeyStoreKeyring keyring = new KeyStoreKeyring(keyStore, keyName -> "protection-password");

参考情報

Field Level Encryption from the Java SDK

Field Level Encryption

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0