git-crypt を使って秘密情報を版管理する
よく訓練されたアップル信者、都元です。やばい、ブログの書き方忘れてるwwwwww
…気を取り直して。git-cryptという git plugin ツールはご存知でしょうか? 要するに、DBのパスワードやOAuthのシークレットなど、版管理はしたいけれどGitHub等にpublishするには抵抗がある情報を、 シームレスに暗号化して管理することによってリポジトリ内で版管理可能にするものです。
GNU Privacy Guard
git-cryptでは、GNU Privacy Guard という暗号化ソフトウェアを使います *1。GPGとかGnuPGと略されたりします *2。
さて、git-cryptを使い始める前にGnuPGのセットアップが必要です。本稿では macOS に gpg (GnuPG) 2.2.3 をセットアップ する前提で解説します。homebrewは上手いこと導入しておいてください。
GnuPGのインストール
まず、初めてGnuPGを利用する方は、GnuPG本体および macOS 上でGnuPGを利用するためのパッケージをインストールします。 その後に、インストールした gpg-agent の設定ファイルを配置します。
$ brew install gnupg pinentry-mac gpg-agent $ echo "pinentry-program /usr/local/bin/pinentry-mac" >>~/.gnupg/gpg-agent.conf
キーペア生成とエクスポート、そして公開鍵の共有
続いて、今回は公開鍵暗号を使うために、自分のキーペアを生成します。GnuPGでは個々人をメールアドレスで認識するため、鍵の生成には名前とメールアドレスが必要です。
alice$ gpg --generate-key gpg (GnuPG) 2.2.3; Copyright (C) 2017 Free Software Foundation, Inc. (略) Real name: Alice Email address: alice@example.com You selected this USER-ID: "Alice <alice@example.com>" Change (N)ame, (E)mail, or (O)kay/(Q)uit? O
途中、パスフレーズを登録するダイアログが2回現れますので、入力してください。
(略) gpg: key XXXXXXXXXXXXXXXX marked as ultimately trusted gpg: revocation certificate stored as '/Users/alice/.gnupg/openpgp-revocs.d/AAAAAAAAAAAAAAAAAAAAAAAAXXXXXXXXXXXXXXXX.rev' public and secret key created and signed. pub rsa2048 2017-12-05 [SC] [expires: 2019-12-05] AAAAAAAAAAAAAAAAAAAAAAAAXXXXXXXXXXXXXXXX uid Alice <alice@example.com> sub rsa2048 2017-12-05 [E] [expires: 2019-12-05]
これでキーの生成は完了です。続いて公開鍵をファイルにエクスポートしておきます。
alice$ gpg --output alice.gpg --export alice@example.com
同じ操作を、秘密情報を共有するメンバー各自で行います。
... bob$ gpg --output bob.gpg --export bob@example.com
他者の公開鍵のインポート
生成した公開鍵ファイルを相互に交換します。本来の公開鍵交換は「なりすまし」を疑って、 信用に足る経路を経た交換を工夫したり、fingerprint と呼ばれるデータを検証する必要がありますが、まぁ今回は正しく鍵交換できていると仮定します。
受け取った他者の公開鍵は、下記のようにインポートできます。
alice$ gpg --import bob.gpg
GnuPGでは、公開鍵はこのままでは信用したことにならず、インポートした鍵を信頼する手続きを行います。
alice$ gpg --sign-key bob@example.com
ここまでで alice@example.com
および bob@example.com
という二者が相互に公開鍵の交換および信頼の手続きを終えているものとします。
さて、ここまでで、メンバー間で公開鍵による暗号および署名が利用できるようになりました。 個別のファイルに対して暗号化・復号化・署名・検証をコマンドで実行できますが、本稿の趣旨ではないので割愛します。
git-crypt
さて、GnuPGの準備が整ったので、git-crypt の説明にはいっていきます。
まずAlice側でgitリポジトリを作り、暗号化しなくても構わないファイルを配置しておきます。(既存のリポジトリでも構いません)
alice$ mkdir hello-git-crypt alice$ cd hello-git-crypt alice$ git init alice$ echo 'Hello, world!' >public-info.txt alice$ git add . alice$ git commit -m 'initial commit'
git-cryptのインストールと、リポジトリに対するメンバーの公開鍵登録
続いて、メンバー各自で git-crypt のインストールを行います。
$ brew install git-crypt
続いてAliceはこの git リポジトリで git-crypt を有効化し、秘密情報にアクセスできるメンバーを登録します。
git crypt init
は初回のみでかまいませんが、git crypt add-gpg-user
はメンバーが増えるたびに行います。
alice$ git crypt init alice$ git crypt add-gpg-user alice@example.com [master c410435] Add 1 git-crypt collaborator 2 files changed, 3 insertions(+) create mode 100644 .git-crypt/.gitattributes create mode 100644 .git-crypt/keys/default/0/AAAAAAAAAAAAAAAAAAAAAAAAXXXXXXXXXXXXXXXX.gpg alice$ git crypt add-gpg-user bob@example.com [master 4cdb9ab] Add 1 git-crypt collaborator 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 .git-crypt/keys/default/0/BBBBBBBBBBBBBBBBBBBBBBBBYYYYYYYYYYYYYYYY.gpg
add-gpg-user
ではリポジトリの .git-crypt/keys/default/0/
ディレクトリ内に公開鍵を配置して、コミットしています。
秘密情報ファイルの配置
秘密情報ファイルを作成し、それと同時に .gitattributes
というファイルを作成します。
このファイルで「private-info.txt は暗号化して管理すべき」という指示をしています。
これら2つのファイルをコミットします。
alice$ echo 'Hello, git-crypt!' >private-info.txt alice$ echo 'private-info.txt filter=git-crypt diff=git-crypt' >>.gitattributes alice$ git add . alice$ git commit -m 'Add secret info'
さて、どうなっているでしょうか。
alice$ cat private-info.txt Hello, git-crypt! alice$ git diff HEAD~ diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..332bdf2 --- /dev/null +++ b/.gitattributes @@ -0,0 +1 @@ +private-info.txt filter=git-crypt diff=git-crypt diff --git a/private-info.txt b/private-info.txt new file mode 100644 index 0000000..00ae0dd --- /dev/null +++ b/private-info.txt @@ -0,0 +1 @@ +Hello, git-crypt!
おや、catしてみても、diffを見ても、暗号化しているようには見えません。 しかし実は、aliceによる秘密情報ファイルの操作は、自動的・暗黙的に暗号化して行われるようになっているのです。
他者による秘密情報ファイルの参照
では、このリポジトリを alice が push して、それを bob が clone した場合…。
bob$ git clone https://.../hello-git-crypt.git bob$ cd hello-git-crypt bob$ cat public-info.txt Hello, world! bob$ cat private-info.txt GITCRYPT(以下、文字化け)
private-info.txt だけが暗号化されてます。
しかし、以下のコマンドを入力するとパスフレーズ入力のダイアログが現れ、これに正しく応答すると…。
bob$ git crypt unlock (パスフレーズダイアログに応答) bob$ cat private-info.txt Hello, git-crypt!
はい、この通り。以降はaliceと同じように、特に意識することなく秘密情報ファイルは暗号文としてコミットされ、そしてローカル内では平文の状態で操作ができます。
ちなみに、あまり使うことは無いかもしれませんが、下記のコマンドにより、ローカル内でも暗号文状態に戻せます。
bob$ git crypt lock bob$ cat private-info.txt GITCRYPT(以下、文字化け)
おまけ
生成した GnuPG の公開鍵および秘密鍵は下記のようにエクスポートできます。バックアップ等でご利用ください。
alice$ gpg --output alice.gpg --export alice@example.com alice$ gpg --output alice_secret.gpg --export-secret-key alice@example.com
またこれらのコマンドに --armor
オプションを追加すると、テキストファイル形式でエクスポートできます。
GitHub にはGnuPGの公開鍵を登録する機能があり、テキスト形式の公開鍵をクリップボード経由で登録しておくと便利です。
alice$ gpg --armor --export alice@example.com | pbcopy alice$ open https://github.com/settings/gpg/new
GitHubに登録したSSH公開鍵は https://github.com/<username>.keys
でアクセスできることは有名ですが、
上記で登録したGnuPGの公開鍵は https://github.com/<username>.gpg
でアクセス可能です。
鍵交換に上手く活用できそうですね。