Play2.5 + mariadb + EbeanでDB暗号化

# DB暗号化の種類
- カラム暗号化
カラムごとに暗号化
Ebeanではこちらしかできない様子

- テーブル暗号化
テーブルごとに暗号化
この機能はmariadbに標準で付いているが、恐らくPlayやEbeanからは操作できない

- DBのあるHDDそのものを暗号化
！？

# 全コード
https://github.com/skliber/encryptdb

# 事前の設定
## conf/application.conf
一部抜粋

```application.conf
db {
  # You can declare as many datasources as you want.
  # By convention, the default datasource is named `default`

  # https://www.playframework.com/documentation/latest/Developing-with-the-H2-Database
  default.driver = org.mariadb.jdbc.Driver
  default.url = "jdbc:mariadb://localhost:3306/playdb"
  default.username = play
  default.password = "play"

  # You can turn on SQL logging for any datasource
  # https://www.playframework.com/documentation/latest/Highlights25#Logging-SQL-statements
  #default.logSql=true
}

ebean {
  default = ["models.entity.*"]
}
```

## build.sbt
```build.sbt
name := """encryptdb"""

version := "1.0-SNAPSHOT"

lazy val root = (project in file(".")).enablePlugins(PlayJava, PlayEbean)

scalaVersion := "2.11.7"

libraryDependencies ++= Seq(
  javaJdbc,
  cache,
  javaWs,
  "org.mariadb.jdbc" % "mariadb-java-client" % "1.4.4"
)
```

## project/plugins.sbt
以下を追記
```
addSbtPlugin("com.typesafe.sbt" % "sbt-play-ebean" % "3.0.0")
```
## conf/ebean.properties
新規作成して以下を書き、後述のBasicEncryptKeyManagerの場所を指定する

```
encryptKeyManager = models.security.BasicEncryptKeyManager
```

encryptKeyManager = "models.security.BasicEncryptKeyManager"
とダブルクォートで囲うと動かないので注意

# 暗号化の準備

## models.entity

@Encryptedをつけたカラムが暗号化される

```java:User.java
package models.entity;

import com.avaje.ebean.annotation.Encrypted;

import javax.persistence.Entity;

/**
 * ユーザー情報
 *
 * @author
 *
 */
@Entity
public class User extends BaseEntity {

    /* ユーザー名 */
    @Encrypted
    public String name;

    /* メールアドレス */
    @Encrypted
    public String mail;

    /* パスワード */
    @Encrypted
    public String password;

    public static Finder<Long, User> finder = new Finder<Long, User>(User.class);

}
```

## models.security

### BasicEncryptKeyManager

```java:BasicEncryptKeyManager
package models.security;


import com.avaje.ebean.config.EncryptKey;
import com.avaje.ebean.config.EncryptKeyManager;

public class BasicEncryptKeyManager implements EncryptKeyManager {

    @Override
    public EncryptKey getEncryptKey(String tableName, String columnName) {
        return new CustomEncryptKey(tableName, columnName);
    }

    @Override
    public void initialise() {
        // Do nothing (yet)
    }

}
```

### CustomEncryptKey

```java:CustomEncryptKey
package models.security;

import com.avaje.ebean.config.EncryptKey;

public class CustomEncryptKey implements EncryptKey {

    private String tableName;

    private String columnName;

    public CustomEncryptKey(String tableName, String columnName) {
        this.tableName = tableName;
        this.columnName = columnName;
    }

    @Override
    public String getStringValue() {
        return play.Configuration.root().getString("application.secret") + "::" + this.tableName
                + "::" + this.columnName;
    }
}
```

# 確認
上記までで準備は終了

mariadbに付いてきたHeidiSQLで確認してみる

## HeidiSQL
![db.gif](https://qiita-image-store.s3.amazonaws.com/0/77685/80cf121a-328c-9d9a-3b6f-25ed9ad02bbb.gif)


見えない！

# 参考
https://www.playframework.com/documentation/2.5.x/JavaEbean
https://archive-avaje-org.github.io/ebean/encryption.html
http://stackoverflow.com/questions/15800453/play-framework-2-1-java-ebean-encrypted-annotation-errors