Google謹製暗号ライブラリ「Tink」を使ってみた

#

#Tinkって？
https://github.com/google/tink
Introductionを読みますと
これは、安全に使用できるシンプルなAPIを実装した暗号ライブラリの様です。
既に数多くのGoogle製品に利用されており
言語は、Java,C++,Objcetive-Cに対応
(なぜ、Swiftは非対応なのと思ってしまった)
今後、Goとjavascriptに対応予定
https://github.com/google/tink/blob/master/docs/ROADMAP.md

iOSKeyChainは未対応と書いてあるので、まずAndroidで試してみました。

#Androidに導入する方法
https://github.com/google/tink/blob/master/docs/JAVA-HOWTO.md
ここを参考に実装します。
使用IDEは、AndroidStudio 3.1.4です。

##Gradle
app配下のbuild.gradleに以下を追加

```gradle
implementation 'com.google.crypto.tink:tink-android:1.2.0'
```

HOWTOには、dependenciesでしたがwarningが出たのでimplementationにしました。

##ソースコード

```java
String plain = "5000兆円ほしい";
HybridConfig.register();
KeysetHandle privateKeysetHandle = KeysetHandle.generateNew(HybridKeyTemplates.ECIES_P256_HKDF_HMAC_SHA256_AES128_GCM);
KeysetHandle publicKeysetHandle = privateKeysetHandle.getPublicKeysetHandle();

HybridEncrypt hybridEncrypt = HybridEncryptFactory.getPrimitive(publicKeysetHandle);

byte[] contextInfo = "abcdefghijklmnop".getBytes();

byte[] cipherText = hybridEncrypt.encrypt(plain.getBytes(), contextInfo);

HybridDecrypt hybridDecrypt = HybridDecryptFactory.getPrimitive(privateKeysetHandle);

String plainTxt = new String(hybridDecrypt.decrypt(cipherText, contextInfo));

Log.d("tinkTest","平文："+plain+"\n復号文："+plainTxt);
```

##実行結果

```text
平文:5000兆円ほしい
復号文:5000兆円ほしい
```

##パラメータなどで調べたこと①
>ECIES_P256_HKDF_HMAC_SHA256_AES128_GCM

http://google.github.io/tink/javadoc/tink/1.1.1/com/google/crypto/tink/hybrid/HybridKeyTemplates.html

```text

    ECIES_P256_HKDF_HMAC_SHA256_AES128_GCM

    public static final KeyTemplate ECIES_P256_HKDF_HMAC_SHA256_AES128_GCM

    A KeyTemplate that generates new instances of EciesAeadHkdfPrivateKey with the following parameters:
        KEM: ECDH over NIST P-256
        DEM: AES128-GCM
        KDF: HKDF-HMAC-SHA256 with an empty salt 

    Unlike other key templates that use AES-GCM, the instances of HybridDecrypt generated by this key template has no limitation on Android KitKat (API level 19). They might not work in older versions though.
```
http://imatch0603.xsrv.jp/cryptography/blog/2016/03/hybrid-encryption.html
https://sehermitage.web.fc2.com/cmath/kdf_enc.html
KEM=鍵カプセル化メカニズム
DEM=データカプセル化メカニズム
KDF=鍵導出関数

##パラメータなどで調べたこと②
>HybridEncrypt

http://google.github.io/tink/javadoc/tink/1.1.1/com/google/crypto/tink/HybridEncrypt.html

```text
Hybrid Encryption combines the efficiency of symmetric encryption with the convenience of public-key encryption: to encrypt a message a fresh symmetric key is generated and used to encrypt the actual plaintext data, while the recipient’s public key is used to encrypt the symmetric key only, and the final ciphertext consists of the symmetric ciphertext and the encrypted symmetric key. 
```
ハイブリッド暗号の説明

```text
WARNING

Hybrid Encryption does not provide authenticity, that is the recipient of an encrypted message does not know the identity of the sender. Similar to general public-key encryption schemes the security goal of Hybrid Encryption is to provide privacy only. In other words, Hybrid Encryption is secure if and only if the recipient can accept anonymous messages or can rely on other mechanisms to authenticate the sender. 
```
ハイブリッド暗号では、信頼性(真偽?)は保障しないという説明。
送信元を別の技術で担保するか、匿名扱いならsecureだよとあります。
(署名などをすればよいかな)

```text
the ciphertext allows for checking the integrity of contextInfo 
(but there are no guarantees wrt. the secrecy or authenticity of contextInfo).
```
contextInfoの完全性は保障するけど、「contextInfoの秘密性や真正性は保証されていません」(google翻訳)
恐らく、機密性と可用性ですかね。
contextInfoの値と暗号データが流出すると、全てが漏れるからcontextInfoは暗号などして保持してねっていうメッセージでしょうか。

#最後に
ニュース記事(https://www.infoq.com/jp/news/2018/10/google-tink-cryto-ios-android)
でこちらを見つけましたが、試した記事なかったので試していました。
暗号に関しては、知らない知識・用語があり勉強になってよかったです。
正直、英語と暗号知識が欠如しているので誤訳や記載ミスがあるかもしれません。
その際はご指摘頂ければ幸いです。
(勉強します)

また、暗号に関してはサンプルソースそのまま書くのは大変危険です。
用法容量守って正しくお使いください。

#追記
AES-GCMの初期化ベクトルは96ビット以上推奨の様です
(https://www.cryptrec.go.jp/list/cryptrec-ls-0001-2012r4.pdf)
後、contextInfoを今回固定にしていますけど
実際に利用しようとするのであればランダム文字列にすることを推奨します。