個人情報保護するWebBluetoothでCOCOA信号チェッカー作った話

by daisuke-nogami | February 25, 2021
tips | #android #dena #javascript

こんにちは。COO室の野上と申します。

普段は、全社改革テーマ事務局などの、各種の全社課題への取り組みをしているビジネス職ですが、その一環としてDeNAの新型コロナウイルス感染症対策本部の業務にも取り組む中で、新型コロナウイルス接触確認アプリ(COCOA) の普及促進の一環として、Web Bluetooth技術を使った知見をお伝えしたく、Blog記事を執筆させていただきました。

なお、ビジネス職ではありますが、もともとはビッグデータ分析系に取り組んでおり、分析用データの基礎集計を仕込むなどのエンジニア的な業務もしていましたので、「初心者がコードを動かしてみた」よりは深めの内容をお話しできていると思います。

今回の記事でお話しすること

今回の記事では、接触確認アプリ「COCOA」動作チェッカー(githubレポジトリ)のリリースにあわせて、

  • COCOA動作チェッカーのバックエンドで動いている、Bluetooth Low Energy(BLE)信号を確認するWeb Bluetoothの使い方
  • 接触確認アプリCOCOAのプライバシー保護の仕組みを踏まえた、COCOA動作状況チェッカーでのプライバシー保護の取り組み

をお話しさせていただきます。

なぜCOCOA動作チェッカーをWebで作ることにしたのか

私は2020年2月時点では、リスクマネジメント観点を中心に全社課題に取り組んでいたたまめ、社内の新型コロナウイルス対策本部立ち上げ時にメンバーとして招集されました。 このときに、対策本部長の三宅の影響から、自社内の課題への取り組みだけではなく、社会全体にも貢献する取り組みをしたいと考えていました。

できれば、民間だけではなく行政にもよい貢献がしたいですね。本部長の三宅は、古巣である厚労省をもっとDeNAのアセットで支えられるのではないかと考えています。こちらも、派手ではなくても、しっかり成果を出す変化を生み出していきたいです。 初出: あえて決め過ぎない。DeNAが取り組む「働きやすい体制づくり」

そして、個人的にも、新型コロナウイルスの脅威を克服する技術として、デジタル技術を用いたコンタクト・トレーシング(感染者と接触した人を割り出して検査などをすることで、感染の広がりを抑制する)に強い期待を持っていました。

しばらくして、対策本部長の三宅が厚生労働省参与に就任し、COCOA関連も担当するようになったことで、普及の啓発をするために、「COCOAインストール済みチェッカー」を作れないか?と思いつきました。少し調べて見ると、Bluetoothを使う技術が幾つかある中で、Chromeで扱うのが1番手っ取り早そうだ、ということで挑戦したら、案外あっさりと信号を検知できたのです。

当時のSlackでの会話

当時のSlackでの会話

その後、横浜スタジアムの技術実証の場でCOCOAの普及促進と普及率測定を行ったときに、COCOAインストール者への配布インセンティブ数と、検知されたCOCOA端末数に大きなズレがあることで、インストールして下さった方の2~3割がBluetoothをオフにしていて信号が飛んでいない(協力の意思があるのに活かされないのはもったいない!)ことが発見され、「信号が発信されているかを確認する」チェッカーを開発することにしたのです。

なお、横浜スタジアムでのCOCOA普及率測定の取り組みは、DeNA TechCon2021 にて、横浜スタジアム技術実証・COCOA インストール率のリアルタイム可視化 IoT システム発表されますので、ご関心のある方はこちらのセッションもご覧頂けますと幸いです。

何を計れば、COCOAの信号の有無が分かるのか

それでは、スマートフォンでCOCOAの信号が受信できるか、どうやって把握すれば良いのでしょうか。

COCOAや、Google/Appleの接触通知API(以下、Exposure API)を利用する各国のコンタクト・トレーシング・アプリでは、Bluetooth Low Energy(以下、BLE)の信号を用いて、接触記録を残しています。 具体的には、Advertising信号を用いて、接触記録に用いる符号を送受信しています。

その信号の仕様は一般に公開されています。

Exposure Notifications: Helping fight COVID-19

Advertising Payloadの説明部分

Advertising Payloadの説明部分

BLEのAdvertising信号では、どのようなサービスに用いる信号なのかを示す、Service UUIDというカラムがあり、COCOA(Exposure API)では、 0xFD6F というUUIDを使っています。

そのため、スマートフォンでBLEのAdvertising信号を 0xFD6F だけを通すようにフィルタして受信してやれば、COCOA(Exposure API)の信号を確認することができるわけです。

Web Bluetoothの使い方

それでは、早速Web Bluetoothで、COCOA(Exposure API)の信号を受信してみましょう。

処理は単純で、周囲の信号スキャンを開始する部分と、発見したときの処理を行うEventListenerを定義するだけです。 Web Bluetoothの関連するドキュメントも2つだけで、単に信号を受信するだけなら、ドキュメントのごく一部だけを読めば使えてしまいます。

最低限のコードはこれだけです!

navigator.bluetooth.requestLEScan({
  filters: [
    { services: [0xFD6F]}
  ], keepRepeatedDevices: false
}).then(() => {
  navigator.bluetooth.addEventListener('advertisementreceived', event => {
    console.log(event.device.id + '\t' + event.rssi);
  });
})

なお、Web Bluetoothは、Chromeの”Experimental Web Platform features”とされているため、試すときには chrome://flags/#enable-experimental-web-platform-features からEnabledに設定を変更しておいてくださいね。

設定変更済みのChromeのdeveloper toolsのconsoleでも、このコードを入れると、しっかり動きます。

ところでこのコードでは何をコンソール出力しているのでしょうか。 EventListenerが受け取るeventの中にデータ一式が入っています。その定義を確認してみましょう。

ここでは2つの情報をタブ区切りで出力しています。

event.device.id + '\t' + event.rssi

device.id が、デバイスのユニークなID、 rssi が、受信した信号の強度を示しています。 ちなみに、 event.txPower というカラムには、送信する電波の出力もはいっています。 じゃあ、txPowerとRSSIから距離を計算すれば一件落着。

…というわけにはいかなかったのです。

電波というものを扱う難しさ…機種によって出力も感度もマチマチ!

この考え方に基づいて、横浜スタジアムでの技術実証のときに簡易チェッカーを作りました。

このプログラムと現地で使う端末25台を横浜スタジアムまで運び帰宅すると、

「iPhoneの電波、2m離れても検知してしまいます…」

という連絡が。念のため閾値を調節するボタンを付けておいたので調節すればよいか、と前日に確認するも、iPhoneに合わせて閾値を高めると、他の機種では検知出来なくなってしまう。そのときは時間が取れなかったので「お客様が2mくらいの距離に接近した時点で検知音が鳴ってもよい」と割り切りましたが、これでは困る。

後になって気づきましたが、これは実はGoogleもガチで悩んでいる問題で、機種別の電波強度・感度のデータを大規模に収集して公開していました。

Exposure Notifications BLE calibration calculation

しかし、COCOA(Exposure API)の信号には、機種の情報が含まれていません。 加えていうなら、測定をするときに、プライバシーに関わる情報を触ることも避けたい。

そこで、COCOAチェッカーでは、検知出来た周囲の端末全ての電波強度の変化を把握することで、電波強度が強まる(=チェッカーに近づく端末がある)ときに「信号を検知しました」と表示するようにしました。 ただし、端末ごとの変化をみると、遠くにある端末が近づいても「検知しました」と判定してしまいます。そこで、「周囲の端末で最も強い強度の電波よりも、一定以上強い電波を検知した」ときを、検知タイミングとすることにしたのです。

検知条件の模式グラフ

そして、近づいてきたかどうかの閾値は、これは理論通り5dBと設定しました。 チェッカー側の端末と近い距離であれば、10cm程度の移動でも5dB程度電波強度が変化するためです。

距離ごとの理論上のRSSIとその差分

この仕組みを採用することで、多数の人が行き来し数十台のCOCOA(Exposure API)信号が検知されるような場所(例えば、駅のコンコースのような場所)に設置したとしても、かなり正確に端末の接近を検知することができるようになりました。

Web Bluetoothは、送信元のMACアドレスを隠してくれる

ちなみに、端末を区別する、といっても、Web Bluetoothは信号のMACアドレスも隠蔽してくれるため、プログラム側でMACアドレスを収集するようなプライバシー侵害もできないようになっています。

そして、 event.device.id に入っている文字列は、これはMACアドレスのハッシュですらなく、完全にランダムな値が入っているのです! Chromeのソースコードをみると、crypto::RandBytes() で生成されたランダムなデータを base::Base64Encode() で可読テキストに変換しているのです。

ブラウザ側で、このランダムな値(のbase64変換文字列)とMACアドレスの対応表は持っているので、同じ端末が同じ event.device.id になりますが、スクリプト側からはどうあがいてもMACアドレスに変換することはできません。

ということで、event.device.id を使うだけで、完全に匿名化された、10分間は変化しないユニークな端末IDを得ることができるのです。 測定をするときに、プライバシーに関わる情報を触ることも避けたい私にとっては好都合です!

なお、COCOA(Exposure API)側でも、ランダム化MACアドレスに対応したOSでは、必ずMACアドレスをランダム化していて、20分以内に変化をさせるようになっており、MACアドレスによる個人の特定への配慮はなされています。

まとめ

  • Web Bluetoothは簡単にBluetooth Low Energyを取り扱える
  • Web Bluetoothは多くのプライバシー情報を自動的に隠蔽してくれる
  • COCOAも、余分な情報を外に出さないので、プライバシーを守りつつ接触確認をすることができる

先日、Android版の不具合の発表がありましたが、接触確認が効果を生むためには、人と接触のある多くの方の利用が不可欠です。新型コロナウイルス感染症の拡大防止のため、新型コロナウイルス接触確認アプリ(COCOA) のインストールと利用も、よろしくお願いいたします。

余談 : 「なんでハマスタの外の京浜東北線の車内の信号が届くの…?」

横浜スタジアムでの技術実証のとき、Bluetoothの信号は恐ろしく遠くまで飛ぶことに気づかされた話です。

事前に、球場外の電波がどの程度球場内に飛び込むか、無人の横浜スタジアムの客席の様々なところで、手元のAndroidスマホで計測プログラムを動かしながら計測していました。

そして、客席最上段にあるスカイバーカウンターにあがったとき、急に計測プログラムが20台くらいの微弱な信号を検知しました。 ええ、なんだ…?と思って外を見下ろすと、京浜東北線の電車が走り去って行くのがみえました。直線距離でおそらく30mくらいあるかと思いますが、数百人が乗車する列車の窓際に立っている人たちのスマホから、信号がここまで届いたのです。電波での接触確認が難しいのだな、と感じさせられた瞬間でした。

…という課題に、普及率測定チームではどのように対処したのかも、DeNA TechCon2021 にて、横浜スタジアム技術実証・COCOA インストール率のリアルタイム可視化 IoT システム発表されますので、ご関心のある方はこちらのセッションもご覧頂けますと幸いです。