Skip to content

gitで署名・中身の暗号化をする

   
4562文字(約7分)

モチベーション

gitは差分確認に便利であり、githubなどにプライベートリポジトリを借りてpushしておけばバックアップにもなる。しかし、クラウドを使うことを考えると、流出してしまったときに中身がばれてしまうとか、commitの偽造とか個人で使うのに気にしてもしょうがないことがどうしても気になる。
というわけで、commitには署名をして本人証明をつけ、pushする中身は暗号化することでこれらの問題を回避するための手段をまとめる。windows環境の話。
なお、git-ageで暗号化した場合、差分は暗号化した状態でしか見えないソフトと復号した状態で見えるソフトがあった。コマンドラインやVSCodeのdiffはちゃんと見えるので問題なしとする、差分確認ができないと結構困る。

動作確認バージョン

ソフト バージョン
git git version 2.54.0.windows.1
gpg gpg (GnuPG) 2.5.19
git-age v0.3.0 Commit: 902ac4673272ef513381d6b77783fb83f0bdcc0d

gitのインストール手順は既知とし省略。

署名

Gpg4winが有名なようなのでこれを使わせてもらう。

インストール

1winget install GnuPG.Gpg4win
2gpg --full-generate-key
  • 鍵種別は基本的にデフォルトのECC(署名+暗号化)・楕円曲線Curve25519でよい
  • 期限は切ったほうが望ましいが個人利用である以上0にする、切れる運用はだるすぎる。更新してもよいが、パブリックリポジトリを運用するときにでも考えよう

生成した署名鍵の確認

1>gpg --list-secret-keys --keyid-format=long
2[keyboxd]
3---------
4sec   ed25519/ああああ 2026-05-23 [SC]
5      いいいい
6uid                 [  究極  ] ユーザー名 <メールアドレス>
7ssb   cv25519/うううう 2026-05-23 [E]
8      ええええ
  • sec:親鍵
  • ssb:子鍵
  • 「ああああ」はシリアル番号、「いいいい」はフィンガープリントなので公開しても構わない。
  • 右側のカッコ内の記号が鍵の役割を示している。
    • S: Data Sign(データへの署名)
    • C: Key Certify(鍵への署名)
    • E: Encrypt(暗号化)
    • らしい。
  • 運用としては署名用に子鍵を作るのがよさそうだが、完全に個人用なのでそこまで考えないことにする。

秘密鍵が見たい場合は
gpg --export-secret-keys --armor
で出力できる。

本手順において重要なのは次の2点。

  • secのいいいいがキーID。
  • uidのメールアドレスはgitの署名との一致が必要

秘密鍵を生成したら公開鍵を確認する。これをgithubなどに登録することで、検証してくれる。

1>gpg --armor --export ああああ
2-----BEGIN PGP PUBLIC KEY BLOCK-----
3なにかでる
4-----END PGP PUBLIC KEY BLOCK-----

gpgのパスも必要になるので確認する。

1> where gpg
2C:\Program Files\GnuPG\bin\gpg.exe

gitリポジトリへの設定

git configに以下を追加する。グローバル設定嫌い系人間のため一応globalには設定せず、.gitごとに設定している。

1git config user.name ユーザー名
2git config user.email メールアドレス
3git config user.signingkey いいいい
4git config commit.gpgsign true
5git config gpg.program "C:\Program Files\GnuPG\bin\gpg.exe"

これでcommitすると、そのcommitに対して署名ができる。

暗号化

暗号化はageがよいっぽい(根拠なし)のでageを使う。しかしageは暗号化するソフトであり、gitとの連携はしない。そのためgit-ageでgit commitを暗号化してもらう。

git-ageのインストール

これはgo言語で実装しているらしいが、installの章を読むとwingetがあったためgoのインストールは不要だった。

なおgitでcommit後に暗号化したいと生成AIに聞くとjolheiser/gitageが勧められたが、wingetに登録しているのはprskr/git-ageしかない、っぽい。どちらが良いかまで調べることはしていないため、wingetで入れられるほうにしておく。

1> winget install git-age

git側に何か設定が必要かと思ったのだが、gitはgit ageのようにスペースの後に知らないコマンドがあった場合、パスを探索する。その結果git-ageという名前の実行ファイルが見つかればこれを自動的にサブコマンドとして認識するとのこと。勉強になる。
git_commands(公式)

ということで次のようにgit-ageを入れただけなのに認識してくれる、便利。

1>git age version
2v0.3.0
3Commit: 902ac4673272ef513381d6b77783fb83f0bdcc0d
4Built at 2026-04-15T19:22:10Z
5You are using the latest version 🎉

git-ageの最終構成

1C:\Users\<UserName>\AppData\Local\git-age/
2 |- keys.txt            ←git-ageの公開鍵・秘密鍵
3
4/gitリポジトリ
5 |- .git
6  |- config             ←ageを使う設定の追加
7 |- .agerecipients      ←暗号化する公開鍵の設定
8 |- .gitattribute       ←git-ageの対象にする拡張子の設定

gitリポジトリのage設定

1>git age init

.agerecipientsができる、これに登録した公開鍵で暗号化するっぽい。またC:\Users\<UserName>\AppData\Local\git-age\keys.txtに公開鍵・秘密鍵が生成される。

その後、ageでの暗号化対象をgitに伝える必要がある。.gitattributesに次の記述(マークダウンの例)を入れることでageに流し込んでくれる。これによりgit commit時に暗号化されているのでpushするだけでよい。

1*.md filter=age diff=age -text

以上でローカルでは平文だがオリジンでは暗号化が可能となった。push先(今回はgithub)を確認すると確かに暗号化されていた。

その後pullした際に復号できるようにgit configに次の設定を追加する

1git config filter.age.smudge "git-age smudge %f"
2git config filter.age.clean "git-age clean %f"
3git config diff.age.textconv cat

別デバイスとの連携

ここまでで暗号化はできたが、この状態だと暗号化したデバイスでしか復号できない。なぜなら復号するための秘密鍵は暗号化したデバイスにしかなく、秘密鍵をデバイスの外に出すことはあまり推奨されないため。
そのため別のデバイスで見たい場合、暗号化する公開鍵を追加する。これにより、原文を各公開鍵で暗号化してくれるみたい。ファイルサイズは倍になるが、致し方ない。

別のデバイス側にも上記手順でgit-ageをインストールし、git age gen keyを打つ。
※生成AIに聞くとgit age gen-keyを勧められたが、「-(ハイフン)」がないのが正しい。git age --helpで調べると出てくる。なお公式のREADMEが間違ってる、コマンド変えたのかな。
※ヘルプを見る際はgit age --helpだとgit経由になるためかでなかった。git-age --helpが本名なのでこれで出てくる。

その後、生成した公開鍵をもとのデバイスに渡す。公開鍵はC:\Users\<UserName>\AppData\Local\git-age.keys.txtにあるのでこのpublic key側を渡す。AGE-SECRET-KEY部分は秘密鍵なので外に出してはいけない。

受領したら元のデバイスで次のコマンドで公開鍵を登録する。これにより既存のファイルもすべて再度暗号化してくる、らしい。

1git age add-recipient <public key>

また別のデバイス側でpullした場合、configの状態は引き継がないためセットアップ時に実行した次のコマンドは再度必要。

1git config filter.age.smudge "git-age smudge %f"
2git config filter.age.clean "git-age clean %f"
3git config diff.age.textconv cat

設定後、次のコマンドでgit-ageを反映して中のデータを復号してくれる。

1git checkout-index -f -u -a
comments powered by Disqus