JK・おっさんプロトコル

`JK`と`おっさん`の間で、個人情報を一切漏らすことなく円滑なコミュニケーションが行えるように工夫したプロトコルです。現在は次の二つのプロトコルがありますが、ニーズに合わせてもっと色々考えたいと思っています。

# 高校生判定プロトコル

## 登場人物

ここには次のような登場人物がいると仮定します。

<dl>
  <dt>JK</dt>
  <dd>自分が<strong>高校生</strong>であることを証明したいが名前や住所、所属する学校などは保護したい</dd>

  <dt>おっさん</dt>
  <dd>ある人間について、その人間の性別や年齢といった個人情報はどうでもいいが、<strong>高校生</strong>であるということは確定させたい</dd>
</dl>

このような仮定があるので、例えば`JK`が、`JK`の所属する学校の発行する学生証を用いて`おっさん`に身分を示すということは、学校名などといった個人情報が流出するので使うことはできません。

## 概要

次のような構成になります。

1. `おっさん`は自分が **信頼できる** カラオケ・理髪店・映画館をいくつかピックアップして、そのリストを`JK`へ渡す
2. `JK`は（1）で受け取ったリストの中から **信頼できる** お店を一つ選択する（もし信頼できるお店がリストにない場合は、`おっさん`がお店のリストを作り直す）
3. `おっさん`と`JK`は（2）で指定したお店で待合せをして、`JK`はそのお店を **高校生の価格** で利用する（その際に学生証などを提示するが、`おっさん`は少し離れた場所に待機してもらい、学生証が店員にしか見えないようにする）
4. `JK`はお店を高校生の価格で利用したことを示す証拠（レシートなど）を`おっさん`に提示する
5. `おっさん`は（4）の証拠を確認する（レシートの日付けなど）

この方法では、お店を`おっさん`と`JK`の両方が信頼しているので、お店を篭絡して`おっさん`が個人情報を取得するなどということはないといえます。
つまり、`JK`と`おっさん`はお互いを信用する（個人情報を渡す）かわりに、お店を信用することにしたということです。

# 現金支払いプロトコル

## 登場人物

ここには次のような登場人物がいると仮定します。

<dl>
  <dt>JK</dt>
  <dd><code>おっさん</code>といちゃいちゃしてもよいから<strong>現金</strong>が欲しい

  <dt>おっさん</dt>
  <dd><code>JK</code>といちゃいちゃできたら<strong>現金</strong>を渡してもよい</dd>
</dl>

## 既存のプロトコル

既存のプロトコルでは、次のような問題があります。

### 現金前払い

現金前払いとは次のようなプロトコルです。

1. `おっさん`が`JK`へ予め **現金** を渡す
2. `おっさん`と`JK`がいちゃいちゃする

ですが、このプロトコルでは`おっさん`が現金を`JK`へ渡した後、`JK`はいちゃいちゃする前に何らかの手段で現金を持って逃走する可能性があり、`おっさん`にとって不利です。

### 現金後払い

現金後払いとは次のようなプロトコルです。

1. `おっさん`と`JK`がいちゃいちゃする
2. `おっさん`が`JK`へ **現金** を渡す

しかし、この方法ではいちゃいちゃした後、`おっさん`が現金を払わない可能性があり、`JK`にとって不利です。

このように既存の方法では、現金の先払い後払いによって、悪意のある振る舞いをするとどちらかが有利になるという方法しかありませんでした。

## 新しいプロトコル

紙幣を破壊するので、次のようなルールが必要になります。

### 紙幣が破損した場合の交換基準

次のようなルールに基づいて、破損した紙幣を銀行などが交換してくれるものとします。

（引用：[https://www.boj.or.jp/about/services/bn/sonsyo.htm/](https://www.boj.or.jp/about/services/bn/sonsyo.htm/)）

> - 面積が3分の2以上の場合は全額として引換え
> - 面積が5分の2以上、3分の2未満の場合は半額として引換え
> - 面積が5分の2未満の場合は銀行券としての価値は無く失効

### プロトコル

次のように実行します。

1. `おっさん`は用意した **現金** （紙幣のみ）を`JK`へ見せて、本物かどうか確認してもらう
2. 次のように、現金（紙幣）をカッターナイフなどで **三等分** に切断する
![yen.png](https://qiita-image-store.s3.amazonaws.com/0/10815/1c161610-0207-2ee5-d7d6-9258bb954787.png)
3. 三等分にした現金の **B** の部分をライターなどで燃やして **破棄** する
4. 三等分にした現金のうち **A** の部分を`JK`へ渡し、 **C** の部分を`おっさん`が持つ
5. いちゃいちゃする
6. `おっさん`は持っている **C** の部分を`JK`へ渡す
7. `JK`は後日、銀行へ行き、切断された紙幣 **A** と **C** を新品の現金に交換してもらう

ここで$\frac{1}{3}$になった現金（紙幣）について考えます。$\frac{1}{3} \fallingdotseq 0.3$ですが、切断された現金が価値を持つには$\frac{2}{5} = 0.4$以上必要になります。つまり、切断された現金 **A** や **C** はそのままの状態ではゴミということになります。こうすると、`JK`は切断された現金 **A** を持って逃げても無駄ということになります。また、`おっさん`も切断された現金 **C** を持っていても意味がありません。

# FAQ

もともと後輩に説明するために作ったこのページが、僕の予想に反してたくさんの方にご閲覧いただき、はてなブックマークやTwitterなどでいくつかのコメントをいただきました。その中で多いものなどをここで取り上げて僕の意見などを述べさせていただくことにします。

## 限定公開にも関わらず、ソーシャルブックマークで拡散してしまったが良いのか？

この記事はもともと後輩に説明するための記事ですが、特に隠すつもりはないので僕としてはOKだと思っています。限定公開としたのは、この記事が直ちに技術へ直結する内容を含んでいないという気持ちから、Qiitaにとってもしかしたら相応わしくないかなと思ったからです。

## これらのプロトコルに技術的なオチはないのか？

これらのプロトコルには技術的に考える余地があると考えています。二つのプロトコルに分けて、それぞれ述べます。

### 高校生判定プロトコルの技術的なオチ

何人かの方々が指摘なさっているように、このプロトコルは **OAuth** や **認証局** がモデルになっています。技術分野の方々にとって、これらの技術を解説する必要はないかもしれないですが、僕なりに一応解説します。
例としてTwitterによる認証を考えます。するとプロトコルの登場人物などを次のように読み替えることができます。

- `JK` → Webサイトの利用者
- `おっさん` → 利用するWebサイト
- 信頼できるお店 → Twitter
- レシート → トークン

メールアドレスなどの個人情報を渡して利用したいWebサイトがあるが、そのWebサイトに個人情報を渡すほどの信頼がないとき、Twitterなど信頼できる第三者に認証してもらい、Twitterが認証したという証拠をWebサイトにトークンという形で提示します。
このプロトコルを考える前から、僕はOAuthや認証局といった技術について知っていたので、これらの技術はこのプロトコルを考えるにあたって参考にしました。

また、一部ではこのプロトコルが **ゼロ知識証明** なのではないかという指摘がありますが、それは違うのではないかと僕は思います。ゼロ知識証明は具体的に色々な方法がありますが、どれも二者間で行うものであって、このプロトコルのように信頼できる第三者が登場することはないと思います。

### 現金支払いプロトコルの技術的なオチ

こちらについては、 **閾値暗号** というものを参考にしました。閾値暗号についてはWebにあまり文献がなく、また僕自身の理解もそれほどないのですが、参考程度に書いておきます。
直感的な議論をすると、鍵と鍵穴が$n$個ある南京錠があるとします。複数の鍵と鍵穴が錠を開けたり閉めたりする際に必要な南京錠は世の中にあると思いますが、そういう場合たいてい$n$個すべての鍵が必要になります。これに対して、$n$個の中からどんな組み合せでもよい$k\, (<n)$個の鍵があれば鍵を開けたり閉めたりできる、というのが閾値暗号の特徴です。
これがあると何がよいのかというと、例えばたくさんの人数で暗号通信をしていて、参加者の皆が暗号鍵を持っているという状況を考えます。そこで、ネットワークのエラーなどが発生し参加者の中の一人が切断されたとすると、全ての鍵が必要な暗号を使っている場合、もう暗号を復活させたりする手段がなくなってしまいます。閾値暗号を使えば、少なくとも$k$人生き残っていれば暗号通信を継続することができます。一方で、もし$k$人がグルになってしまうと、暗号を解読することができるので、そういう対策が別途必要になるという側面も持ちます。
このように、$k$のようなある閾値があれば暗号を解読するなどできる（価値が生まれる）一方で、閾値を下回ると途端に価値がなくなってしまうものを探した結果、日本銀行が発行する紙幣は$k$が$\frac{2}{3}$以上の時に全ての価値を持ち、$k$が$\frac{2}{5}$を下回ると価値を失うという大変素晴しい性質を持つことに気がつき、今回利用させてもらいました。

## 紙幣を切断するのは違法ではないのか？

Wikipediaの[貨幣損傷等取締法](http://ja.wikipedia.org/wiki/%E8%B2%A8%E5%B9%A3%E6%90%8D%E5%82%B7%E7%AD%89%E5%8F%96%E7%B7%A0%E6%B3%95)には次のような記述があるので問題はないと判断しました。

> 日本銀行券（いわゆる紙幣）は本法の対象外である。貨幣の場合とは異なり、2008年現在、日本銀行券を損傷することそれ自体を罰する法律はない。

## おっさんもJKも相手を損させる手段があるのではないか？

その通りです。それは次のような方法を使えば可能です。

<dl>
  <dt><code>JK</code>が<code>おっさん</code>を損させたい場合</dt>
  <dd>切断された現金 <strong>A</strong> を持って逃げる</dd>
  <dt><code>おっさん</code>が<code>JK</code>を損させたい場合</dt>
  <dd>切断された現金 <strong>C</strong> を渡さない</dd>
</dl>

これの解決は今後の課題です。

## 紙幣を三等分にするのは難しいのではないか？

実はこのプロトコルでは紙幣を正確に三等分する必要はありません。切断された紙幣には次のような関係が成り立てばよいです。

- 切断された紙幣 **A**、 **B**、**C** を全て足すと、それは$1$（元の紙幣）である
- 切断された紙幣 **A** と **C** は両方とも$\frac{2}{5}$未満である（紙幣としての価値を消滅させるため）
- 切断された紙幣 **A** と **C** を足すと、面積が$\frac{2}{3}$以上になる（`JK`が銀行で交換してもらうため）

これを考えると、切断された紙幣 **A** と **C** が満すべき条件は、$\frac{1}{3}$以上$\frac{2}{5}$未満ということになります。つまり多少 **B** が小さくなっても問題はありません。

## 登場人物はアリスとボブでよかったのではないか？

次のJavaScriptで記事の中の`JK`と`おっさん`を全て`アリス`と`ボブ`に変換できます。

```js
$('*').each( function() {
  var txt = $(this).html();
  $(this).html(txt.replace(/JK/g, 'アリス').replace(/おっさん/g, 'ボブ'));
} );
```