By

Keybaseの暗号化 git を理解するためのポイント

はじめに

Keybase という会社が、最近、連続して興味深いサービスをリリースしました。

ひとつは、Keybase Teams という Slack もどきのグループチャットです。もうひとつは、encrypted git という暗号化された git です。

どちらも、end to end で暗号化されていて、サーバがクラックされても内容を読まれることがないということがウリになっています。

Keybase promises secrecy and integrity of file system data and metadata even in the case of total server compromise.

完全にサーバがやられちゃっても、ファイルが読まれたり壊れたりすることはありません。Keybase はそれを約束します

これが本当だったら、とてもありがたいですね。でも、秘密情報を預けていいものかは、慎重に見極めなければなりません。そこで、できる範囲で技術的なドキュメントを追いかけてみました。

私には、この手の技術を完全に検証することはとてもできませんが、何となく言いたいことはわかったので、以下のような点についてまとめてみました。

  • 普段の使い勝手はどうか?
  • どのように安全性を実現しているのか?
  • データ喪失や漏洩などのトラブルの可能性は?

結論としては、パスワードなどの秘匿すべき情報を共有するためのサービスとして、かなり有力なものではないかと考えています。

もちろん、通常のアカウントは個人で管理するのが原則ですが、サービスの利用形態によっては例外的に共有する必要のあるアカウントもあるので、秘密の情報を共有することはどうしても必要です。今は、USBメモリを使ってネットワークを経由しないでやりとりしているのですが、それがオンラインでできるとしたらとても便利になるし、トータルの安全性も高くなります。

Keybase git の使い勝手は普通の git と同じ

Keybase git は Keybase の GUI クライアント をインストールして、アカウントを作るとすぐ使えるようになっています。git のタブをクリックして、”New encrypted git repository..” という所をクリックして、repository 名を入力すると次のようにリポジトリの URL が表示されます。

git

この リポジトリ URL を使って、普通の git コマンドで操作します。

$ git clone keybase://private/essa/test
Cloning into 'test'...
Initializing Keybase... done.
Syncing with Keybase... done.
Counting: 204 bytes... done.
Cryptographic cloning: (100.00%) 204/204 bytes... done.
$ cd test
$ echo 'abc' >> test.txt
$ git add test.txt
$ git status
On branch master
Your branch is up-to-date with 'origin/master'.

Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

        modified:   test.txt

$ git commit -m 'test'
$ git push
Initializing Keybase... done.
Syncing with Keybase... done.
Counting and decrypting: 3 objects... done.
Preparing and encrypting: (100.00%) 3/3 objects... done.
Indexing hashes: (100.00%) 3/3 objects... done.
Indexing CRCs: (100.00%) 3/3 objects... done.
Indexing offsets: (100.00%) 3/3 objects... done.
To keybase://private/essa/test
   c3d22e4..37510f0  master -> master
$

git clonegit push の時に、二行見なれないメッセージが表示されるだけで、普通の git と同じです。

使い勝手は同じですが、このリポジトリは、他人には見ることができないリポジトリになっています。

Keybase filesystem

これは、git にもともとある、git-remote-helpers という仕組みを使って実装されており、ソースも公開されています

ソースを見てみると、Keybase filesystem (以下 KBFS )というものにリポジトリを格納しているようです。

KBFS を直接使う場合は、FUSE などの仕組みを利用して、ローカルのディレクトリにマウントして使用するのですが、暗号化 git の場合は、remote-helper が直接 KBFS のプロトコルでサーバと通信しているようです。

「サーバがクラックされても大丈夫」というのは、この KBFS のファイルシステムによって保証されているということらしいです。この KBFS の仕様は以下の文書に書かれています。

これは、数式が出てくる難解なドキュメントでしっかり理解できたわけではないですが、どうも次のようなことをやっているようです。

  1. ユーザがデバイスごとに鍵ペアを持ち、秘密鍵はデバイス内に保存して外部に一切出さない
  2. Top-Level Folder (TLFs) ごとに、ユニークな共通鍵を持ち、ファイルはこの共通鍵で暗号化される
  3. TLFs の共通鍵は、ユーザごとの公開鍵で暗号化されて、サーバに保存される
  4. ファイルやディレクトリは、Merkle tree という形式で管理され、一番上のハッシュに書き込みした人の署名を行うことで、完全性を保証する

そして、ポイントは、これらの暗号化処理や検証をクライアント側で行なうことです。

ユーザの秘密鍵やKBFS用の共通鍵は、クライアントのマシン内部で管理されていて、そのままサーバに送信されることはありません。サーバにあるのは、公開鍵と暗号化された共通鍵だけなので、仮にこれらを覗かれることがあったとしても、ユーザのデータを入手することはできないのです。

自分のローカルマシンの中にある秘密鍵がないと、誰にもアクセスできないというのは、セキュリティ的には安心ですが、そうなると逆にその秘密鍵を無くしたら大変ですね。つまり、自分のマシンにコーヒーをこぼしたりしたら、どうなってしまうのでしょうか?

この問題については、後で考察するとして、もう少し具体的に何が行なわれているか書いてみます。

たとえば、Alice と Bob がふたり専用のフォルダを作るとします。最初にAlice が作成の操作を行ないます。

この時に、Alice のクライアントは最初に、サーバから Bob の公開鍵をダウンロードします。そして、次の処理を行ないます。

  1. このフォルダ専用の共通鍵(Ks)を乱数から生成する
  2. 共通鍵(Ks)を Alice 自身の公開鍵で暗号化する
  3. 共通鍵(Ks)を Bob の公開鍵で暗号化する
  4. ファイルを共通鍵で暗号化する
  5. 2 3 4を Alice の秘密鍵で署名して、サーバに送信する

サーバに保存されるのは、Aliceの鍵で暗号化されたKsとBobの鍵で暗号化されたKsの二つの鍵です。この二つの鍵は、実質 public になっていて、誰にでもアクセスできますが、それぞれペアとなる秘密鍵がないと使えないので、実際に使えるのは、世界中でAlice と Bob の二人だけです。

Keybase のサーバやクライアントは、ユーザの便宜のために、いろいろなチェックをしながら動いていると思いますが、ファイルの安全性を最終的に保証するのは、この公開鍵暗号による共通鍵の管理です。クラッカーがクライアントプログラムを改変して、不正にファイルを入手しようとしても、Alice か Bob の秘密鍵を入手しない限りそれは不可能だということです。

メンバーの管理も、この「暗号化されたKs」の追加削除になります。後から、Charlie がメンバーになったら、Charlie用に彼の鍵で暗号化されたKs を追加します。もし、Bobがチームから抜けるとしたら、Bob用のKsを削除します。自分専用に暗号化された鍵がある=そのリポジトリへのアクセス権がある、ということになります。

ただ、追加はいいとして、削除は実際にはもっと複雑な処理が必要です。Bobは 、脱退前には共通鍵を使えています。仮に、この鍵を保存していたとしたら、脱退以降も同じようにアクセスできてしまいます。

そこで、メンバーの変更の時は、共通鍵を新しく生成するようになっているようです。そして、これは人数分だけ個別の暗号化する必要もあるので、人数に比例した重い処理になります。性能やレスポンスにも影響するためだと思いますが、このあたりの処理はかなり複雑になっていて、私には追いきれませんでした。

これらの処理を行う、クライアント側のソースは、github に公開されていて、上記の仕様と実装を検証することは誰にでもできるようになっています。(サーバ側のソースはないようですが、暗号の処理はクライアント側で行なうので、検証のためには不要と思われます)

個人のアイデンティティとデバイスキーの分離

そして、Keybase 上のアカウントのアイデンティティをどう管理するかというと、アカウントにスマートフォンを登録しておくと、このスマホでもアカウントの管理ができるようになっています。

さきほど書いた「パソコンにコーヒーかけたら全部ダメになるのか?」という問題に対して、これは、なかなかうまい落とし所ですが、よく考えると不思議な所があります。

スマホに専用アプリをインストールして、それを自分のアカウントに登録しておくと、パソコンをダメにした時に、新しいパソコンを元のアカウントに接続できて、そのパソコンに秘密データを復元できます。これは普通のパスワードによるアカウント管理ならあたり前のことですが、ローカルの秘密鍵を使った暗号化をしているのに、これができちゃうのは何かおかしいですよね。

だって、「暗号化されたファイルは、Keybase の社員にも復元できなくて、そのためにはユーザのマシンの秘密鍵が絶対に必要」で、その秘密鍵がコーヒーこぼしてダメになったのに、ファイルを復元できてしまう、それって矛盾してないですか?

これが疑問で、ドキュメントをあちこち追いかけたのですが、この答は、「スマホを登録した時に、そのスマホ用に暗号化されたKs が作られて、サーバに保存されている」ということです。つまり、Alice と Bob のチームに Charlier が参加した時と似たようなことを、スマホの登録時にやっているようです。(ユーザの管理とは実際にはそのユーザが所有するデバイスの管理である)

スマホのアプリを登録すると、そのスマホ内で鍵ペアが生成されて、その公開鍵がサーバに送られます。単にこの鍵をそのまま保存するだけではなくて、この時点で、この人がアクセスできるフォルダ等のリソースひとつひとつに、全部、そのスマホの専用の鍵が作られるのです。だから、スマホの登録は、既存の登録済のパソコンかスマホを使う必要があります。既存の秘密鍵を持ったマシン、共通鍵の暗号を読めるマシンが一台必要なのです。新しいスマホ用にKsを暗号化するという処理は、古いマシンが自分の秘密鍵を使って、ローカルに行なうからです。

これは、なかなか実用的かつ安全だと思います。

つまり、ユーザ単位の秘密鍵があって、安全性を高めるためにそれをサーバに置かないとしたら、どうしてもその鍵をバックアップしたり別のデバイスに移動する必要があって、そこがセキュリティ的な穴になりがちです。

それに対し、デバイスがそれぞれ独自の秘密鍵を持つようにして、アカウントにそれを登録するようにしておけば、秘密鍵はデバイスから取り出す必要はないし、デバイスの登録削除もアカウントのアイデンティティを保ったままで行なうことができます。

その代わり、公開鍵の署名や検証が複雑になり、デバイスの登録削除の時に、リポジトリごとの共通鍵(を暗号化したもの)を間違いなく管理する必要があります。ここは概念としては単純ですが、実装は大変なので、バグなどが残っている可能性も高いと見るべきだと思います。

想定すべきトラブル対策

もし、このサービスによって実データを管理するとしたら、以下の点については、特に留意すべきだと思います。

  1. サーバ側ストレージのダウン
  2. パソコン、スマホの故障
  3. スマホの盗難
  4. メンバー管理に伴うリスク

まず、まだ実績の少ない若い企業のサービスなので、全面的にこれに頼るのは危険だと思います。必ず、ユーザ側でバックアップを持つべきです。ただ、これは git のリポジトリですから、最新版を pull してローカルマシンに保持しておけばそれがバックアップになります。

次に秘密鍵がユーザ側にしかなくて、これが無いとデータを復元できないことに注意すべきでしょう。パソコン一台だけで使用するのは危険です。スマホを最低一台は自分のアカウントに登録しておくべきだと思います。

普通の用途であれば、パソコン一台と自分がふだん持ち歩いているスマホを一台登録しておけば、どちらが故障してももう片方から復元できます。念の為に、古いスマホをもう一台登録しておけば、ほぼ完璧でしょう。

ただ、これで紛失や水没からデータの復元はできますが、スマホを盗難された場合には、データを盗まれる可能性があります。指紋認証などでロックしておけば一応大丈夫ですが、本格的な犯罪者なら、スマホを分解して、中のSSDから直接秘密鍵を取り出されてしまう危険性があります。

これが許容できない場合は、専用のスマホを購入して、それを登録してから金庫にしまっておくような運用を考慮すべきだと思います。Keybase のシステムでは、秘密鍵が外に出ることはないので、物理的な鍵と同様に、スマホを鍵としてセキュリティの要件に見当った厳重な管理を行えばいいのです。

あるいは、paper key という、紙として管理、保存できるキーもあります。これをバックアップにすることもできます(というか推奨されています)

次にリポジトリに対するアクセス権の変更やデバイスの登録、削除は、かなり複雑な処理になることを意識すべきだと思います。つまり、普通のシステムではアクセス権の変更は単純なデータベースの更新処理ですが、Keybase では、共通鍵の作り直しなど、かなり面倒な処理が発生するということです。

理論的には安全だと思いますが、エッジケースではバグによるトラブルがあり得るという想定で、慎重に確認しながら使用すべきだと思います。

あと、Crypto spec の 6.3 Decommisioning a Device にちょっと気になる記述がありました。

Don’t bother to reencrypt old blocks, so leave the old decryption materials around (except for the compromised key)

これは、デバイス無効化の処理に関する記述ですが、おそらくメンバーが抜けた時も同じだと思います。

アクセス権を削除する時に、共通鍵は作り直すけど、古い鍵で暗号化されたファイルは更新されないようです。ということは、退社した社員は、自分が在籍していた時に作られたファイルを、退社後も読むことができるということになります。正規のクライアントでは拒否されるかもしれませんが、ここについて鍵ペアによる保護は期待できないと言っているように思えます。

これは、見方によって当然の仕様です。そのやめた社員は、ファイルも共通鍵もダウロードできるので、それを自分のマシンに保存しておくことを考慮にいれるべきです。古いファイルを新しい鍵で再暗号化してもあまり意味がありません。しかし、アカウントを削除しても古いファイルは読める、というのは普通のアクセス制御とは違う考え方なので、これに注意する必要があると思います。

私が何か読み間違えているのかもしれませんが、ここが複雑な処理になることは間違いないので、実際の運用では、メンバーを削除した場合は、その人がアクセス可能だったデータは全部作り直して最初からやり直す方がいいような気がします。

公共的なインフラとなり得る信頼の輪?

このように見ていくと、KBFSのポイントは「データを共通鍵で暗号化して、その共通鍵をアイデンティティの保証された公開鍵で暗号化することで、特定の人だけにアクセスを許す」ということです。

つまり、考え方としてはSSLやPGPと同じですね。

そうなると残された問題も同じで、「ちょっと待て、その公開鍵は本物か?」です。

つまり、公開鍵の身元保証をどう行なうかです。公開鍵が本物ならば、あとは全部プログラムが自動的にやることなので、実装がレビュー可能であって、充分レビューされていると期待できるなら問題ありません。

SSLではトップダウンで、PGPではボトムアップで、それぞれ公開鍵の身元を裏付ける体系を持っています。

そして、この公開鍵の身元保証という問題について、Keybase は両者をミックスした独自の方法を考えており、そこについてかなり壮大な構想を持っているような気がします。

この記事の主題は、チーム内での情報共有なので、そこはまだ深く調べていませんが、Keybaseの体系は、一方では Keybase をルートとしたトップダウンであって、一方では、follow関係の網の目によって、直接知らない人をボトムアップに保証できるようになっているように思えます。

特にfollow関係は、個人の秘密鍵によって信頼の連鎖を築いているので、Keybaseという会社への信頼とは無関係の公共物となり得ます。そして、これをベースとして企業の鍵の信頼性を担保するようなことも可能だと思われます。つまり、社員が全員で会社の信頼を裏書きして、社員の信頼度の総和=会社の信頼度とする。これが高いサイトは、SSL のルートからトップダウンに保証されるより信頼度が高くなって、その情報はKeybase社が配信していても、Keybase社には偽造できないものになります。

ということは、Keybase のアカウントは、SSL の証明書のような機能と、twitter の公認アカウントのような機能を同時に果たせる公共的なインフラとなるわけです。

Keybase のサービスの具体的な用途は、少くとも当初は、グラノベッターの言う強い絆の範疇が中心だと思いますが、それが弱い絆に延長されていった時に、このサービスの本当の価値が見えてくるのかもしれません。

まとめ

最初にあげた疑問の答えは次のようになります。

  • 普段の使い勝手はどうか?
    • → push/pull の時に透過的にremote-helper として実行されるので、通常の git とほぼ同じ
  • どのように安全性を実現しているのか?
    • リポジトリごとの共通鍵をアクセス権を持つメンバーのデバイスキーで暗号化して保存
    • 暗号化の処理は、ユーザのクライアントの中で行なわれる
    • アクセス権の管理はユーザ(デバイス)単位で暗号化した鍵の追加、削除によって行なわれる
  • データ喪失や漏洩などのトラブルの可能性は?
    • 秘密鍵がないと復旧できないので、複数のデバイスを登録しておくことが必要
    • 登録したスマホを盗難されると全データにアクセスされるので、それを物理的な「鍵」として要件に合わせて厳重に管理することが必要
    • メンバーやデバイスの削除処理は複雑なので、充分に検証しながら運用すべき
  • 公開鍵を認証する「信頼の輪」のシステムは、公共的インフラとなり得るので、今後、大化けする可能性がある

Keybaseの暗号化gitは、「中の人にも覗かれない安全なファイルサーバ」と「デバイスの紛失からの復旧手段を妥当なコストで用意する」の二点を両立している点で大変ユニークで、安全かつ実用的なサービスだと思いました。

一緒にユニークな決済サービスを作ってくれる Rails エンジニアを募集中です!
多国籍なメンバーと一緒に仕事をしてみませんか?詳細はこちらのリンクです:D