{"componentChunkName":"component---src-templates-post-js","path":"/secure-sheet/","result":{"data":{"site":{"siteMetadata":{"title":"techblog.o0i.es"}},"markdownRemark":{"frontmatter":{"date":"2019-06-18T00:00:00.000Z","title":"セキュアな席替えがしたい","tags":[""]},"excerpt":"前期中間試験が終わってから、…","html":"<p>前期中間試験が終わってから、3年生になって初めての席替えをすることとなった。昨年までとは異なり、担任の意向で学生主体となって席替えを行い、その結果を担任に報告するという形になった。</p>\n<p>当然それぞれが「おれはここに座りたい」「誰々と隣がいい」などと言えばまとまらないので、誰かがうまいこと進める必要が出てくる<small>(そういう制約条件が運良く矛盾しなかった場合はProlog, z3などを利用してすべて満たすような席の組み合わせを発見できるが、そうして「自分の要望が通る！」となれば結局要望が互いに矛盾するまで増えそう)</small>。そういうときに便利なのがクラス委員長。2ヶ月前にノリで手を挙げてしまったツケが回ってきている。</p>\n<p>まず、昨年までの担任が使用していた席替えの方法を振り返る。</p>\n<ol>\n<li>\n<p>座席に番号をランダムに割り振った表を作成する(以下「番号/座席表」)。これは秘密にしておく。</p>\n<pre><code>9, 37, 17, 39, 24, 18\n15, 28, 11, 33, 13, 27\n0, 26, 31, 16, 40, 3\n22, 14, 6, 1, 41, 34\n38, 32, 8, 2, 19, 23\n30, 29, 10, 35, 20, 21\n7, 42, 36, 4, 25, 12\n</code></pre>\n</li>\n<li>\n<p>番号と、それに対応する名前の記入欄を設けた紙を作成する(以下「番号/名前表」)。このとき黒板に近い座席に対応する番号には印をつけておく(<code>▲</code>)。</p>\n<pre><code>1 | \n2 | \n3▲ |\n...\n</code></pre>\n</li>\n<li>\n<p>担任はその「番号/名前表」を学生に渡し、学生は適当な番号に名前を記入する。視力に不安のある学生は印のついている欄を選択する。</p>\n<pre><code>1 | hoge\n2 | piyo\n3▲ | huga\n...\n18▲ | foo\n...\n</code></pre>\n</li>\n<li>全員の記入が完了したあと、「番号/名前表」「番号/座席表」を参照して、学生の名前と座席の対応を公表する。上の例でいえば<code>foo</code>さんは<code>18</code>番を選んだので一列目の端の席になる。</li>\n<li>学生間での交渉と席の交換を経て、最終的な座席を確定する。</li>\n</ol>\n<p>席替えの公平性を担保する上でのポイントは、担任教員という独立した第三者の関与になる。教員はそもそも座席を持たないので「窓側の席がいいなあ」と考えることはない。また学生が「後ろ側の席にしてくれよ」と教員に圧力を書けることもない。これは教員と学生が対等な関係にない上に、学生間で席を交渉するほうが簡単だから。学生に番号に記入させることで目が悪い人への配慮もできている。</p>\n<p>対して今回の席替えでは学生が主体であるためそういった独立した第三者が存在しない。上のやり方を踏襲する場合、2つの表を作成するのはクラス委員長である自分の役目となる。学生が名前を書き込んだ後にこっそり「名前/番号表」を書き換えられるので、自分は人に挟まれていない端っ子の席を恣意的に選び、隣あうと騒がしくなる人々を引き離し、いつも授業中にMinecraftをプレイしている彼を教卓の前に配置できる。逆に、自分が他の学生に恣意的な配置を強制させられるケースも考えられるが、結論からいえば今回の席替えではそれは発生せず、またそのような力関係の前には正直成すすべがないのでこの記事では考慮しない。</p>\n<p>もちろんこのような行為は公平性にそぐわないので実行に移すことはなかった。しかし次期委員長がそうであるとは限らないし、また自分も不正を行わないという裏付けがないために同級生に疑われているかもしれない。</p>\n<h1>手法</h1>\n<p>そこで、「悪いことやってませんよ」というのを証明するために以下のような手順で席替えを行うことにした。</p>\n<ol>\n<li>「番号/座席表」を作成する。そして<strong>表のデータのハッシュ値を公開する。</strong></li>\n<li>「番号/名前表」を作成する。このとき黒板に近い座席に対応する番号には印をつけておく。</li>\n<li>委員長はその「番号/名前表」を学生に渡し、学生は適当な番号に名前を記入する。視力に不安のある学生は印のついている欄を選択する。委員長の名前は他の人にランダムな場所に書いてもらう(「番号/座席表」を作成するときに見ているため)。</li>\n<li>全員の記入が完了したあと、「番号/名前表」「番号/座席表」を参照して、名前と座席の対応と<strong>「番号/座席表」を公開する。</strong></li>\n<li>学生間での交渉と席の交換を経て、最終的な座席を確定する。</li>\n</ol>\n<p>(暗号学的・理想的な)ハッシュ関数とは値を入れるとそれに対応するハッシュ値を返すもので、値が1バイトでも異なれば異なるハッシュ値を得ることができる(同じ値からしか同じハッシュ値は得られない)。そしてハッシュ値からはもとの値を求めることができない性質がある。\nハッシュ関数のアルゴリズムにはSHA256、表のデータ形式にはCSVを利用した。</p>\n<p>こうすることで委員長は名前と座席の対応を知った後に座席を操作できなくなる。ハッシュ値が変化して、先に公表していたものと合致しなくなるからだ。もちろん席替えはランダムに行いたいので「番号/座席表」そのものは記入前は公開できない。</p>\n<p>ただハッシュ値をどこかのサーバにアップロードして公表するだけでは、あとからこっそり書き換えられるので信頼性に欠ける。そこで <strong>タイムスタンプ</strong> (その時間に公表してそこから書き換えられていないことの証明)としてツイート・LINEへの投稿を利用した。あとから投稿を編集できるFacebookやブログでは、編集日時が表示されない限りこの方法で完全性は保証できない。</p>\n<blockquote class=\"twitter-tweet\" data-lang=\"ja\"><p lang=\"ja\" dir=\"ltr\">新しい番号表のSHA256ハッシュは 8d38b0ecba6fffa9687e892a20d86d17372fb0e71670f739c93709097ca929a0 です</p>&mdash; sei0o (@sei0o) <a href=\"https://twitter.com/sei0o/status/1139153860314902529?ref_src=twsrc%5Etfw\">2019年6月13日</a></blockquote>\n<script async src=\"https://platform.twitter.com/widgets.js\" charset=\"utf-8\"></script>\n<p>公開した「番号/座席表」は以下の通り。</p>\n<pre><code class=\"language-bash\">$ cat after_zenki_chukan_2.csv\n9, 37, 17, 39, 24, 18\n15, 28, 11, 33, 13, 27\n0, 26, 31, 16, 40, 3\n22, 14, 6, 1, 41, 34\n38, 32, 8, 2, 19, 23\n30, 29, 10, 35, 20, 21\n7, 42, 36, 4, 25, 12\n5\n$ sha256sum after_zenki_chukan_2.csv\n8d38b0ecba6fffa9687e892a20d86d17372fb0e71670f739c93709097ca929a0  after_zenki_chukan_2.csv\n</code></pre>\n<p>この表自体はRubyでサクッと生成した。</p>\n<pre><code class=\"language-ruby\">PEOPLE = 43\nputs (0...PEOPLE).to_a.shuffle.each_slice(6).map {|row| row.join(\", \") }.join(\"\\n\")\n</code></pre>\n<h1>他のやり方</h1>\n<p>思いついたけれど採用しなかった方法と、他の人に教えてもらった方法も記しておく。</p>\n<ul>\n<li>日常的にクラスで利用しているLINEグループのあみだくじ機能を利用してランダムに番号を割り振る→なぜか他のクラスの学生がグループにいて訳がわからなくなる</li>\n<li>\n<p>クラス委員長以外の誰かが「番号/座席表」を作成しハッシュ値を公開したあとで、クラス委員長が「番号/名前表」をランダムに作成する方法</p>\n<ul>\n<li>いちいち名前を書き込んでもらう必要はなくなる</li>\n<li>この場合視力が低い人のことは別に考える必要がある</li>\n</ul>\n</li>\n<li>(やり方ではないが)「そもそも委員長に仕事やらせてる時点でみんな信用してる前提だし、いざ座席表ができればそれに従うしかないんだよ」という説。スターリンもそんなこと言ってたな。委員長じゃなくて書記長だけど。</li>\n</ul>\n<p>ところで、まだアップロードされたハッシュ値を使って座席表が操作されていないことを確認した人はいないようだった。個人的にはこういうどうでもいい場面であえて技術を使ってみる、みたいなの好きなんだけどなー。脆弱な部分があれば教えてください。</p>\n<h1>コメント</h1>\n<p>当時Qrunchでもらったコメント</p>\n<p>developer-kikikaikai さん： 突き詰めると電子署名とか欲しくなりそう</p>\n<p>筆者: コメントありがとうございます！ たしかに委員長本人が表を作ったか検証するためには署名が必要になりますね。Twitter・LINEへの投稿がタイムスタンプ以外にも本人の投稿であることを証明する役割を果たしている…といえるかもしれません(こじつけっぽい)。blockchainにも取引の一部として任意のメッセージを書き込めたはずなので、それを使う手もあるなと思いつきました。</p>"}},"pageContext":{"slug":"/secure-sheet/"}},"staticQueryHashes":["3868140423"]}