Authentication with Symbol

# Authentication with Symbolとは
Symbolブロックチェーン上のユーザーが持つ公開鍵・秘密鍵を用いることにより実現されるE2E認証プロトコルです。
このプロトコルを利用することにより従来のID Providerに依存することなく、ブロックチェーン上のIdentityを用いて認証を行うことができます。

これはブラウザ拡張機能 [SSS Extension (chrome web store)](https://chrome.google.com/webstore/detail/sss-extension/llildiojemakefgnhhkmiiffonembcan?hl=ja) を用いることで **簡単** にWebアプリケーションへと導入することが可能になります。

# SSS Extension
SSS ExtensionはSymbolブロックチェーンを用いたWebアプリケーション(dApps)と連携し動作するブラウザ拡張機能です。
SSS Extensionはユーザーが許可したdAppsへと以下の情報・機能を提供します。

- ユーザーの公開可能な情報
    - SSS上でのアカウントの設定名
    - ブロックチェーンアドレス
    - 公開鍵
    - ネットワーク情報
- トランザクションや認証情報をSSSへと転送する機能
- ユーザーへ署名を要求する機能

これらの機能を用いることによってdAppsはアプリケーション上で **秘密鍵** を管理することなくトランザクションへの署名を行うことができます。

## SSS Extension によって変わる安全性

従来のSymbol DappsはそれぞれのdAppsが暗号化した秘密鍵をローカルストレージ等に保存していました。N個のdAppsを利用する場合N箇所に暗号化秘密鍵があるためそれだけ危険度が増します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/269859/cf2d1bfa-ae3e-3c06-7547-84d8b96dfba9.png)

SSS Extensionを用いた場合暗号化秘密鍵をSSS Extensionのみで管理し、トランザクションの受け渡しを行うため使用するdAppsが増えても危険度は変わりません。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/269859/936825cc-a76f-d691-cc5a-17aea3859108.png)

## SSS Extension の安全性
じゃぁ、肝心なSSS Extensionは安全なのか？という話になると思います。

**絶対に安全** とは言えません。これは秘密鍵をどこかに入力する以上避けられません(入力しなくても絶対安全とは。。。)

少なくとも言えることは、ブラウザ上のローカルストレージよりは結構安全です。

ブラウザのローカルストレージに暗号化秘密鍵を保存する場合は以下のリスクがあります。
1. dApps開発者を信用する必要がある
    - 悪意を持って開発している人がいないとは限りません。(悪意のある)開発者が自身のdAppsに入力された秘密鍵やパスワードを隠れて保存している可能性はないとはいえない。
2. ブラウザ拡張機能による入力監視・ローカルストレージの閲覧
    - 便利だと入れているブラウザ拡張機能が、実は。。。なんてことされていても利用者は気が付きません。

これらの危険性に対してSSS Extensionは一定の耐性を持ちます。
1. dApps開発者が暗号化秘密鍵に触れない、SSS Extensionがそういったことしてないか、は信用する必要がありますね。この点はSSS Extensionはオープンソースでプログラムを公開するといった対応をしています。 https://github.com/SafelySignSymbol/SSS-Extension

2. ブラウザ拡張機能内では基本的に他のブラウザ拡張機能は作動しません。
:::note alert
F12等で開発者ツールを開き、開発者ツールを拡張するブラウザ拡張機能が起動した場合や、ユーザーが手動でブラウザ拡張機能を起動した場合等はこの限りではありません。
:::


可能な限り安全に使いたい！という場合は、Ledger Nanoを買ってきてください。SSS ExtensionはLedger Nanoをサポートしています。

ハードウェアウォレットは取りうる手段では一番安全だと思います。

# ほんだい
本題に移りましょう。

SSS Extensionはトランザクションへの署名だけでなく、メッセージの暗号化を行うことも可能です。

受信者の公開鍵と、送信者の秘密鍵を用いてメッセージを暗号化し、受信者は自分の秘密鍵と送信者の公開鍵を用いてメッセージを復号します。

これを認証機能としてラップした機能 `getActiveAccountToken` を提供しています。
https://docs.sss-symbol.com/ja/DevelopperGuide/Encription#getactiveaccounttoken

`getActiveAccountToken`を用いる場合、dAppsはサービス提供者の公開鍵をClient、秘密鍵をSeverに配置します。

以降以下のような表記を使用します

| 名前 | 表記 | 管理場所 |
|:-----------|:-----------|:------------|
| サービス提供者の公開鍵     | SP Pub       | Client          |
| サービス提供者の秘密鍵     | SP Pri       | Server          |
| ユーザーの公開鍵     | Alice Pub       | SSS Extension          |
| ユーザーの暗号化秘密鍵     | Alice E_Pri       | SSS Extension          |
| SSSのパスワード   | Alice Pass       | ユーザーの記憶         |
| ユーザーの秘密鍵     | Alice Pri       | SSS Extension + ユーザーの記憶から算出          |

そして `getActiveAccountToken` の第一引数に SP Pubを指定します。
ユーザーは認証を行う場合、パスワードを入力し、署名します。

すると、
以下の情報が含まれた認証トークンが SP PubとAlice Priによって暗号化されます。
- signerAddress : ユーザーのアドレス
- iat : トークンを生成した時間
- verifierAddress : SP Pubに紐づいたアドレス
- network : Symbolブロックチェーンのネットワーク情報

dAppsは生成された暗号化トークンをClientからServerへと送ります。ServerにSP Priがあるので、SP PriとAlice Pubを用いてトークンを復号することができます。

これにより、サービス提供者のサーバーとユーザーのブラウザで他者には復号することのできないE2Eで認証を行うことができます。

省略可能な第2引数、第3引数を用いてこのトークンをさらに複雑化することが可能です。

## カスタムペイロードを含めたトークンの作成
これは第2引数にjsonをいれる指定することで任意の情報をトークンに含め暗号化することができます。
https://docs.sss-symbol.com/ja/DevelopperGuide/Encription#%E3%82%AB%E3%82%B9%E3%82%BF%E3%83%A0%E3%83%9A%E3%82%A4%E3%83%AD%E3%83%BC%E3%83%89

これによりdAppsはトークンの期限、dApps上でのIDやユーザーネーム等といった任意の情報をトークンへと含め、認証トークンを作成することができます。

## 暗号化ペイロードを含めたトークンの作成
これは第3引数にServer側でSP PriとAlice Pubで暗号化したペイロードを含めることによりさらに安全なE2E認証を行うことができます。
SSS Extensionは暗号化されたペイロードを復号し、復号したペイロードをトークンに含め暗号化を行います。
https://docs.sss-symbol.com/ja/DevelopperGuide/Encription#%E6%9A%97%E5%8F%B7%E5%8C%96%E3%83%9A%E3%82%A4%E3%83%AD%E3%83%BC%E3%83%89

Serverでランダムな文字列を暗号化しClientに送り、 `getActiveAccountToken` の第3引数に指定し、認証トークンを生成することで、認証トークン内に、Serverしか知り得ない情報が含まれるため、更に安全なE2E認証が実現できます。

# DEMO 
https://docs.sss-symbol.com/demo/auth


認証デモのページへとアクセスすると下図のようなページが表示されます。
画面左側がClient右側がServerの動作となっています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/269859/cef1aaf4-f3b4-2bbf-aeaf-79befa5934ab.png)


アクセス時に認証を行うキーペアが生成され、Verifier PublicKeyが表示されます。デモではアクセス時にキーペアを生成していますが、実際は固定のキーペアを設定し、ServerでSP Priを管理し、SP PubをClientに配置します。

:::note warn
公開鍵をClientにハードコーディングすることにより[中間者攻撃](https://ja.wikipedia.org/wiki/%E4%B8%AD%E9%96%93%E8%80%85%E6%94%BB%E6%92%83)への耐性が向上します。
:::

NEXTを押すとモーダルウィンドウに検証者(SP)の情報が表示されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/269859/b774a9f0-731f-fe18-c353-11b1b7b06904.png)

モーダルウィンドウの外側を押下しすると次のステップへと進みます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/269859/571549ac-b36d-d185-afc1-8741a5a32e6b.png)

認証トークンが生成できるようになります。GENERATEボタンを押下してください。

SSS Extensionが起動します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/269859/b3fde7d3-13f9-56f0-5e09-42ea8958f6a6.png)

プレビュー画面とClientの検証者アドレスが一致していることを確認し、署名します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/269859/132b85fe-2ba8-a719-201a-439f65e1ce4b.png)

E2E暗号化された認証トークンが生成されました。このトークンはユーザー(TDWCEYT44JD6QNLGPDWOSCGN6D7HNGW5V3AJHUQ)と検証者(TB3DK6OROCEBYTM3VQBCSDMYYIQV3QN6XL5KTGI)以外には復号できません。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/269859/9465f6e0-b1db-0976-efda-0abf8676ce65.png)

モーダルウィンドウを閉じるとStep3が表示されます。
VERIFYボタンを押下すると、検証者がServer上に保管してある秘密鍵とユーザーの公開鍵でトークンを復号します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/269859/9663e45d-d2eb-c4cb-07c4-3e771cffdad6.png)

復号されたトークンの内容が表示されました。
署名者アドレス、検証者アドレス、発行日時、ネットワークといった情報が表示正常に表示されているため、検証成功です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/269859/64a9d8cd-199b-c2e2-abb2-65d3bde3314b.png)

このようにして、dApps Server, dApps Client, SSS Extension を用いてE2E認証を行うことができます。



# 認証トークンのユースケース

## ログイン認証
まず第一にログイン機能ですね、トークンをE2E暗号化し、それが検証可能であることはつまり、そのアドレスに紐づく秘密鍵を所持していることを証明することができます。

## 既存SNS等とブロックチェーンアドレスの紐づけ
今回はメールアドレスを例に説明します。
ユーザーはdApps上で認証したいメールアドレスを入力します。
そして、Serverは数桁の認証コードを生成し、そのメールアドレスへ認証コードを添付したメールを送信します。
ユーザーはメールを受け取ると、認証コードを確認し、dAppsへと認証コードを入力します。
Clientは入力された認証コードをカスタムペイロードに含め、`getActiveAccountToken` で認証トークンを生成し、Serverへと送ります。
Serverはトークンを検証する際にカスタムペイロードの認証コードと、はじめに生成した認証コードを比較し、一致した場合、そのユーザーが入力したメールアドレスを所有していることを証明することができます。

DiscordやTwitterとSymbolアドレスを紐づけた台帳も作れます(だれかつくって)

## 一度きりの認証
ワンタイムパスをServerで生成し、暗号化ペイロードに含め、認証を行った際に認証トークン内のワンタイムパスを検証することで認証を行い、その後ワンタイムパスをServer上から破棄することで、一度きりの認証を行うことができます。

:::note warn
ワンタイムパスや有効期限をトークンに含めることにより[リプレイ攻撃](https://ja.wikipedia.org/wiki/%E5%8F%8D%E5%B0%84%E6%94%BB%E6%92%83)への耐性が向上します。
:::

# まとめ
SSS Extensionを用いたSymbolアカウントの認証機能の紹介でした。Symbolブロックチェーンのキーペアを使いE2E暗号化を用いた他者に解読できない認証システムとなっているので、ぜひご活用ください。