コロナウィルスが広まり始めてから、自分の専門性を生かして何かできないかと考えていた。
Bluetooth Low Energyを使ったスマートフォンアプリを配布し、誰と誰が近くにいたか履歴をとっておいて、後にアプリのユーザーの中から感染が確認されたら、そのユーザーが近くにいた他のユーザーに警告する、
というアイディアがあることを知ったのは 鐵人三國誌 だったか。
これは得意領域やん、と思い飛びつき、
コロナのおかげで自分も時間が多少できたので(!?)
そこからシンガポール/TraceTogetherやヨーロッパ/Decentralized Privacy-Preserving Proximity Tracingで検討/実装されているアプリ Projects using personal data to combat SARS-CoV-2 をリサーチをしつつ、プライバシーを保護して、どうBLEを使えばBackgroundでしか使わないだろうこのアプリ間の通信が可能で、Androidも共存できて、小さく初めてすぐにリリースできて、アプリユーザーが増えてもサーバ負荷が軽そうな仕組みを考えていた。
そして昨日 Privacy-Preserving Contact Tracing を発見するまで一週間ばかり。
Apple, Googleが5月に出すならそれを待とう、という空気だと思うので、この一週間ばりばり書いていたコードを公開して 供養したい 。
BLE-Proximity / BLE-Proximity implements contact tracing on iOS, to prevent COVID-19 transmissions.
このプロジェクトは何もなければフリーズしますが、何か良い利用方法があれば協力したいです。右の連絡先にご連絡ください。
考えていたアプリの仕組みは(英語で)レポジトリのREADMEに書いたがここでは日本語で。
要約すると、
- UInt64のランダムな数をアプリ内で生成してuserIdとする
- Bluetooth Low Energyでこれを交換する
- 定期的にuserIdは更新し、アプリ内に自分のuserIdの履歴を保存する
- BLEで受け取った相手のuserId(peerIdとする)も履歴を保存する
- 履歴は4週間まで保存し古いものは捨てる
- COVID-19 positiveになった人は、自分のuserIdの履歴を、同意の後、(ここはTODOだったが)医者の電子署名(ができる国だったらよかったな〜)など信頼性を保証しつつサーバへ保存
- サーバではpositiveだった人のuserIdの履歴を公開
- アプリはpositive userIdリストをダウンロードして、アプリ内のpeerIdの履歴にマッチするものが無いか探す
という感じ。
サーバ側の開発が軽い、プライバシー面が安心(サーバに送る情報がpositiveでなければ何もない, BLEを通して送るuserIdもランダムだし更新する)、という意味で筋が良いと考えていた。
そしてこのアプリの機能が広く多くの人に使ってもらえることを考えると、LINEやメルカリなど多くのユーザーがダウンロードしているアプリのアップデートとして使ってもらうのが最高だろう(もちろん自分の意思でオプトインしてね)。ということを考えてFrameworkとアプリを分けてFramework側にこの機能を実装していた。
https://www.apple.com/covid19/contacttracing から辿れるApple, Googleのドラフト技術資料を見ると大きな違いは、
1. BLEではAdvertisingにデータをのっける
そりゃできたらそうするわ!
iOSではAdvertising dataにアプリが(GATT ServiceのUUID以外の)任意のデータをのせられる公開APIは無い。
First, in May, both companies will release APIs that enable interoperability between Android and iOS devices using apps from public health authorities. These official apps will be available for users to download via their respective app stores.
これ英語が意味不明なのだが、”both companies will release APIs” なのか “download via their respective app stores” なのかどっちなのか。
Advertising dataをアプリからいじれてそれが非公開APIとしてiOS13.xからできるようになり、その後公開されていくとしたら熱いがそれは無いかなあ…
これができないので、BLE-Proximityでは、read characteristic, write characteristicを用意し、BLEでuserIdを読み書きできるようにした。AdvertisingしているiOSアプリをScanで見つけられてread/writeできない、ほど一時的に近くにいる場合は無視してよいでしょう。それにread, write characteristicを両方持っていれば、BackgroundでAdvertiseしているiOSアプリを2つ考えた時に、それぞれのアプリが相手のAdvertiseをScanして発見しなくてよい(片方だけでよい)ので発見率が上がるはず。
iBeaconを使えば、というオプションもあった。
iOSアプリでiBeaconのふりをすることは可能だが、バックグラウンドでは継続してiBeaconとしてAdvertiseできない & iBeaconのAdvertiseにアプリからのせられる情報はMajorとMinorの合計32bitで、それだとuserId空間が足りない。
という理由から却下した。このアプリをForegroundで使うことは考えにくいので、iOSアプリ間で、バックグラウンドで通信できないのはきつい。
もちろんiBeaconでなくてもBackgroundのAdvertiseはForegroundに比べ見つかりにくいので..ではあるが
2. userIdの生成が違う
Apple, Googleのドキュメントでは、userIdに相当するものは Tracing Key –> Daily Tracing Key –> Rolling Proximity Identifier と生成され最後のが交換される。 positiveな人がいたらその人のDaily Tracing Keyに相当するものがサーバにアップされる。
こうすると、サーバ上にアップする情報は、Daily Tracing Key x その人がウィルスを持っていた期間の日数になり、Rolling Proximity Identifierはもっと頻繁に変更できる。
BluetoothのMACアドレスの更新と同期するというのもなるほど。BluetoothのMACアドレスの更新タイミングってiOSアプリで公開APIから知れるんだっけ?
なるほどHKDF便利やん…
ということで、何かを作ってみると他の人が作ったものがいかによくできているか痛感できてさらに勉強になる、という良い例であったのと、
プラットフォーム側にたつのは自由度が高く楽しいだろうなあ、
このアイディアもっと早くに思いつけていたら違ったはずだ、がんばれ。
とまとめてしまいとする。