暗号化

Ebeanは、特定のプロパティの透過的な暗号化/復号化をサポートしています。@Encryptedで暗号化したいプロパティをマークすると、これらのプロパティは必要に応じて自動的に暗号化および復号化されます。

暗号化/復号化は、クライアント/アプリケーション側またはデータベース側で実行できます。データベース暗号化を使用する場合、where句とorder by句の一部としてクエリでこれらのプロパティを使用できます。事実上、プロパティの暗号化はアプリケーションに対して完全に透過的です。

クライアント/アプリケーション側の暗号化/復号化を使用する場合は、where句でEQ(等しい)演算子のみを使用する必要があります。

クライアント/アプリケーション暗号化

クライアント/アプリケーション暗号化を使用する場合、プロパティはJava関数(io.ebean.config.Encryptorインターフェースの実装)によって暗号化/復号化されます。デフォルトの実装ではAES 128ビットベースの実装を使用しており、別の実装を使用するようにEbeanを構成することもできます。

クライアント/アプリケーション暗号化で暗号化されたプロパティは、where句でEQ(等しい)演算子でのみ使用する必要があります。他の演算子はクライアント側の暗号化されたプロパティで使用しないでください。

package io.ebean.config;

/**
 * Used for Java side encryption of properties when DB encryption is not used.
 *
 * By default this is used on non-varchar types such as Blobs.
 */
public interface Encryptor {

  /**
   * Encrypt the data using the key.
   */
  byte[] encrypt(byte[] data, EncryptKey key);

  /**
   * Decrypt the data using the key.
   */
  byte[] decrypt(byte[] data, EncryptKey key);

  /**
   * Encrypt the formatted string value using a key.
   */
  byte[] encryptString(String formattedValue, EncryptKey key);

  /**
   * Decrypt the data returning a formatted string value using a key.
   */
  String decryptString(byte[] data, EncryptKey key);

}

データベース暗号化

データベース側の暗号化/復号化を使用する場合、プロパティを暗号化および復号化するためにデータベースストアドプロシージャを使用します。たとえば、Postgresでは、Ebeanはpgp_sym_encrypt()およびpgp_sym_decrypt()を使用します。

データベース暗号化関数

各プラットフォームで使用されるデフォルトのDB暗号化復号化関数は次のとおりです。

  • Postgres、YugabyteDB - pgp_sym_decrypt(), pgp_sym_encrypt()
  • MySql, MariaDB - aes_encrypt(), aes_decrypt()
  • SQL Server - DecryptByPassPhrase(), EncryptByPassPhrase()
  • Oracle - dbms_cryptoが必要で、暗号化と復号化にカスタム関数を使用します
  • H2 - 'AES'オプション付きのencrypt()とdecrypt()

サポートされている型

以下は、データベース暗号化でサポートされている型です。データベース暗号化でサポートされていない型は、クライアント/アプリケーション暗号化を使用します。

  • Enum (VARCHARに基づく場合)
  • String (VARCHAR, CHAR, CLOB, LONGVARCHAR)
  • Date型 - LocalDate, Date, Joda LocalDate
  • Timestamp型 - Timestamp, Instant, OffsetDateTime, ZonedDateTime

重要: 次の型は現在サポートされていません

  • プリミティブ型
  • タイムスタンプ

EncryptKeyManager

プロパティが暗号化または復号化されるたびに、「キー」を使用する必要があります。Ebeanは内部的に、テーブルと列の名前が指定されたキーについてEncryptKeyManagerに要求します。

EncryptKeyManagerの実装を提供する必要があります。

package io.ebean.config;

/**
 * Determine keys used for encryption and decryption.
 */
@FunctionalInterface
public interface EncryptKeyManager {

  /**
   * Initialise the EncryptKeyManager.
   *
   * This gives the EncryptKeyManager the opportunity to get keys etc.
   */
  default void initialise() {}

  /**
   * Return the key used to encrypt and decrypt a property mapping to the given
   * table and column.
   */
  EncryptKey getEncryptKey(String tableName, String columnName);
}

@Encrypted

@Encryptedアノテーションを使用して暗号化するプロパティをマークします。デフォルトでは、プロパティはdbEncryption = trueになり、クライアント/アプリケーション側の暗号化ではfalseを明示的に設定します。

// use database side encryption
@Encrypted
String name;

// use client side encryption (not db functions)
@Encrypted(dbEncryption=false)
String description;

// Use @Encrypted annotation to mark the encrypted properties

@Entity
@Table(name="patient")
public class Patient {

  @Id
  long id;

  // database side encryption
  @Encrypted
  String name;

  // client side encryption
  @Lob
  @Encrypted(dbEncryption=false)
  String description;

  @Encrypted
  LocalDate dob;
  ...

制限事項

  • Javaクライアント暗号化を使用するプロパティは、WHERE句でEQ(等しい)演算子のみを使用する必要があります。
  • H2、Postgres、YugabyteDB、MySql、MariaDB、Sql Server、およびOracleで組み込まれたDB暗号化のサポート。
  • 位置指定(1,2,3...)パラメータで暗号化を使用することはできません。名前付きパラメータまたはCriteria APIを使用してクエリを定義する必要があります。

List<Patient> list =
  new QPatient()
    .name.eq("Rob")
    .findList();

次のPostgres SQLの結果になります。

select t0.id, pgp_sym_decrypt(t0.name,?)
from patient t0
where pgp_sym_decrypt(t0.name,?) = ?

構成

以下のようにebean.propertiesファイルでEncryptKeyManagerの実装を指定します。

ebean.encryptKeyManager=org.example.BasicEncyptKeyManager

DatabaseConfigを使用してプログラムで構成します。

DatabaseConfig config = DatabaseConfig();
...
EncryptKeyManager keyManager = ...;
config.setEncryptKeyManager(keyManager);
...
Database database = DatabaseFactory.create(config);

EncryptKeyManagerの例は次のとおりです。

package org.example.encrypt;

import io.ebean.config.EncryptKey;
import io.ebean.config.EncryptKeyManager;

public class BasicEncyptKeyManager implements EncryptKeyManager {

  public void initialise() {
    // can load keys or initialise source resources ...
  }

  public EncryptKey getEncryptKey(String tableName, String columnName) {
    // get the key for the given table and column
    String keyValue = ...;
    return new BasicEncryptKey(keyValue);
  }

}

内部

Ebeanは、暗号化されたプロパティが使用されていることを検出しています。プロパティのテーブルと列を使用してEncryptKeyManagerを呼び出し、暗号化キーを取得します。このキーは、プリペアドステートメントにバインド変数として追加されます。

キーはステートメントにバインド変数として追加されるため、他のパラメータの位置を効果的に変更できるため、「位置指定」パラメータで暗号化を使用することはできません。名前付きパラメータまたはCriteria APIを使用してクエリを作成できますが、位置指定(1,2,3,4..)パラメータは使用できません。