【秘密計算】マルチパーティ計算のOSSを使って雰囲気を掴んでみよう！

# はじめに
こんにちは、株式会社Acompanyの近藤です。
普段は秘密計算という技術を用いて「プライバシー保護とデータ分析を両立させる」ことを目指して活動しています。

本記事は[OPTIMIND x Acompany Advent Calendar 2021](https://qiita.com/advent-calendar/2021/optimind_acompany)の17日目の記事となります。

今回は、MPC型の秘密計算OSSを使用して雰囲気を掴むまでの記事をアドカレに突っ込んでみました。

**この記事を読んであなたが得られること。**

- MPC型の秘密計算の雰囲気がわかる
- ブラウザだけで秘密計算を動かすところまで体験できる

それではいってみましょう。

# 概要
マルチパーティ計算(MPC)のOSSの一つである、[JIFF](https://github.com/multiparty/jiff)を使用します。

##### 達成事項
- 投票集計をMPCで実行できる
- バブルソートをMPCで実行できる
- 線形回帰分析をMPCで実行できる
- (オプション)いろいろなデモを実行できる

# JIFFの概略
- JavaScript Implementation of Federated Functionalities の略称
- ボストン大学で開発されたJavaScript のMPC ライブラリ
- Node.js でもブラウザでも動くのが特徴
- 簡単にMPCを体験するのに適している

### JIFFのシステム構成
JIFFは一般的なMPCの構成ではなく、中央に完全に信頼された管理用のサーバを設置する構成になっています。
その管理サーバに対して、参加者である各ユーザが接続して計算を実行します。
下図のLogistics Server が管理サーバにあたります。

主に以下の機能を担っています。

- メッセージのやりとり
- 生存確認
- 鍵管理

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/390000/22e4c5c1-6f86-5267-d046-3e363c2a499a.png)

覚えておいていただきたいのが、大まかなJIFFの実行手順です。

1. 中央のサーバを起動する
2. ユーザを接続する
3. 秘密計算を実行する

先にサーバを起動する必要がある点が特に重要です。

# ハンズオン手順
1. Node.js をインストールする
2. JIFF のリポジトリをクローンする
3. 必要なモジュールをインストールする
4. 秘密計算のデモを体験する
 1. 足し算
 2. 秘密投票
 3. バブルソート
 4. 線形回帰分析
 5. (オプション)自由にその他のデモを触ってみる

## 1. Node.js をインストールする
Node.js の環境がある人はスキップしてOKです。
もし、後の工程でうまく行かない場合はバージョンの問題である可能性が高いため、こちらからLTS版をインストールしてみてください。

Node.js がインストールされていない方は、以下の公式サイトからLTS版をインストールしてください。

https://nodejs.org/ja/

## 2. JIFF のリポジトリをクローンする
ターミナルで以下のコマンドを入力してJIFFのリポジトリをクローンします。

```bash
$ git clone https://github.com/multiparty/jiff.git
```

## 3. 必要なモジュールをインストールする
以下のコマンドを実行して必要なモジュールをインストールします。

```bash
$ cd jiff
$ npm install
```

## 4. 秘密計算のデモを体験する
ここからは実際にJIFFを動かしてMPCを体験します。
デモ用のプログラムが用意されており、そちらを実行することでMPCを用いた秘密計算を体験します。

### 4-1. 足し算
まずは最も簡単なMPCである足し算を動かしてみます。
2人のユーザが提供した数字の足し算をMPCで実行します。
結果はそれぞれのユーザに返却されます。

以下のコマンドを実行して中央の管理サーバを起動します。

```
$ node index.js demos/sum/server

このように表示されたらOK
Direct your browser to http://localhost:8080/demos/<demo-name>/client.html.
To run a server-based party: node demos/<demo-name>/party <input
listening on *:8080
```

次に、ユーザとして参加するためにはブラウザとNode.js の2つの方法がありますが、まずはブラウザで参加してみましょう。

#### ブラウザで参加する場合
以下のURLを別のタブで開いてください。

http://localhost:8080/demos/sum/client.html

このような画面が表示されるはずです。
<img width="518" alt="スクリーンショット 2020-07-30 17.56.50.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/390000/15e66524-6327-654d-7133-4c2575dada9c.png">

これがMPCを実行するユーザとして参加した状態になります。
つまり、このブラウザのタブ1つが1人のユーザを表しています。

今回は簡単のために2人のユーザでMPCを行うため、上記のURLをもう一つ新しいタブで開いてください。

次に以下の手順で計算を実行します。

1. 2つのブラウザの画面のConnect をクリックする
2. Sum ボタン横のテキストボックスに0 - 100 の範囲の数字を一つ入力する
3. 2つのブラウザのSum ボタンを押す
4. 少し待つと結果が表示される

おめでとうございます！
これでJIFFを用いてMPCを動かすことに成功しました！

#### Node.js で参加する場合
以下のコマンドを2つのターミナルで実行してください。

```
$ node demos/sum/party.js 10
``` 

すると、以下のような結果が表示されます。

```
Command line arguments: <input> [<party count> [<computation_id> [<party id>]]]]
Connected! undefined
20
```

ここで、20 と表示されているのが計算結果です。
今回の場合は、コマンドの引数に10 をそれぞれしているので、その足し算の結果である20 が表示されているということです。

おめでとうございます！
これで、Node.js を用いてMPCが実行できました！

以上が基本的なJIFFの使い方になります。
こちらにまとめます。

1. `node index.js demos/sum/server` で管理サーバーを起動
2. ユーザとして参加する
 3. ブラウザの場合はhttp://localhost:8080/demos/sum/client.html にアクセスする
 4. Node.js の場合は `node demos/sum/party.js 引数`で参加する
3. 計算結果を得る 


### 4-2. 秘密投票
3人の参加者が、それぞれ自分の投票を秘密にしたまま結果を得るデモです。
基本的には足し算と同じ手順をふむことでデモを動かせますので、以下詳細な説明は割愛します。

以下を用いて実行してみましょう。

```
$ node index.js demos/vote/server
```

#### ブラウザ
3つ起動しましょう。

http://localhost:8080/demos/vote/client.html


<img width="530" alt="スクリーンショット 2020-07-30 18.21.31.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/390000/7a7b056b-6603-7d74-e966-defd5e105d2e.png">


#### Node.js
こちらも3つ起動しましょう。

```
$ node demos/vote/party.js "[1,0,0,0]"
```
[]は4つの選択肢のうち投票する先だけ1 にします。
上記の例だと、1番目に投票しています。


### 4-3. バブルソート
2人のユーザが同じ長さの配列を入力します。
その配列の要素毎の和をとったものをバブルソートでソートします。

以下を実行します。

```
$ node index.js demos/array-bubble-sort/server
```

#### ブラウザ
ブラウザでも実行できますが、非常に遅いです。
30分程度かかってしまうので、推奨しません。

http://localhost:8080/demos/array-bubble-sort/client.html

#### Node.js
```
$ node demos/array-bubble-sort/party.js "[4,2,5,1]"
```

### 4-4. 線形回帰分析
線形回帰分析を実行します。
各ユーザが提供した点群に対して最もフィットする1次関数を返します。
具体的には以下の式の係数a と切片b を求めます。

y = ax + b

ブラウザで実行すると以下のような結果が得られます。
<img width="302" alt="スクリーンショット 2020-07-30 17.42.29.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/390000/5111e1b7-1c8a-60c9-8373-ac7b068b446d.png">


以下を実行します。

```
$ node index.js demos/graphs-simple-squares/server
```

#### ブラウザ
ブラウザでも実行できますが、非常に遅いです。
30分程度かかってしまいます。

http://localhost:8080/demos/graphs-simple-squares/client.html

#### Node.js
```
$ node demos/graphs-simple-squares/party.js "[-4, -3.5, 0, 0.5, 3, 3.5]"
```
引数はこのように指定します。
"[x1, y1, x2, y2, ...]"
x, y が点の座標を表しています。


### 4-5. (オプション)自由にその他のデモを触ってみる
時間が余った場合は、好きなデモを実行してみると理解が深まります。

どんなデモがあるかはこちらを参考に探してみてください。（ただし、英語です...）
https://github.com/multiparty/jiff/tree/master/demos

実行方法は以下です。

```
$ node index.js demos/デモのフォルダ名/server
```

#### ブラウザ
http://localhost:8080/demos/デモのフォルダ名/client.html

#### Node.js
```
$ node demos/デモのフォルダ名/party.js 引数
```
引数が配列の場合は`"[引数1,引数2,...]"`で記述します。


# まとめ
- マルチパーティ計算(MPC)のOSSである、JIFFを使った
- 投票、バブルソート、線形回帰分析をMPCで行った
- (人によっては)その他いろいろなデモを実行できた

# Happy Hacking :sunglasses: !

# 参考
- 公式
 - https://github.com/multiparty/jiff
 - https://multiparty.org/jiff/docs/jsdoc/