GPG でファイルやフォルダを暗号化する方法

# クイックリファレンス
```shell
# フォルダを圧縮
zip -r foo.zip foo

# 暗号化
gpg -e -o /tmp/encrypted.zip.gpg -r you@example.com foo.zip

# 復号
gpg -d -o /tmp/decrypted.zip /tmp/encrypted.zip.gpg
```

| ロングオプション | ショートオプション | 説明 |
| --- | --- | --- |
| `--armor` | `-a` | バイナリではなくアスキーデータで出力します |
| `--encrypt` | `-e` | ファイルを暗号化します |
| `--output PATH` | `-o PATH` | 暗号化されたファイルの出力先を指定します |
| `--recipient KEY` | `-r KEY` | 使用する秘密鍵を選択します |

| | バイナリデータ | アスキーデータ |
| :---: | --- | --- |
| **利点** | • ファイルサイズが元のファイルと変わらない | • テキストエディタで開ける<br>• 差分表示ができる |
| **欠点** | • テキストエディタでは開けない<br>• 差分表示ができない | • ファイルサイズが膨らむ |
| **拡張子** | `.gpg` | `.asc` |



# はじめに
前回は OpenSSL を使ってファイルを暗号化する方法について紹介しました。

[OpenSSL でファイルを暗号化する方法](https://zenn.dev/noraworld/articles/file-encryption)

しかし `openssl` コマンドによる暗号化だとオプションが複雑だったり、ファイルサイズが大きい場合に正しく暗号化できなかったりするデメリットがあります。

そこで今回は GPG を利用してファイル・フォルダを暗号化する方法について解説します。



# 前提
* `gpg` コマンドはインストール済みであること
* GPG キー（秘密鍵）は生成済みであること



# フォルダを圧縮
フォルダを直接的に暗号化することはできませんので、まずはフォルダを圧縮して ZIP ファイルにまとめます。フォルダではなくファイルを暗号化する場合はこの手順はスキップしてください。

カレントディレクトリにある `foo` というフォルダを圧縮するには以下のコマンドを実行します。

```shell
zip -r foo.zip foo
```

* 上記の例では同ディレクトリに ZIP ファイル `foo.zip` が生成されるはずです
* **フォルダを圧縮する際は `-r` を付け忘れないように注意しましょう**
    * 付け忘れると空 ZIP ファイルになります
* 絶対パスを指定すると展開したときにそのようなディレクトリ構造になってしまいます
* 圧縮前のフォルダ名は維持されます

ここではコマンドラインで圧縮する方法を紹介しましたが、実際には OS のファイル管理アプリ（Mac なら Finder、Windows なら Explorer）のほうが間違いがなくて良いかもしれません。



# 暗号化
ファイルを暗号化するには以下のコマンドを実行します。

```shell
gpg --encrypt --recipient you@example.com foo.zip
```

* 上記の例では同ディレクトリに暗号化されたファイル `foo.zip.gpg` が生成されるはずです
* 暗号化には `--encrypt` または `-e` オプションをつけます
* `--recipient` または `-r` オプションを使用して、利用する秘密鍵に登録したメールアドレスを指定する必要があります
    * このオプションを省略した場合は実行時にインタラクティブ形式で求められます

## アスキーデータで保存
バイナリデータではなくアスキーデータ（テキストエディタで開ける形式）として保存したい場合は以下のように `--armor` または `-a` オプションを付与します。

```shell
gpg --armor --encrypt --recipient you@example.com foo.zip
```

* 上記の例では同ディレクトリに暗号化されたファイル `foo.zip.asc` が生成されるはずです
* このファイルはテキストエディタで開くことができます
    * ただしファイルサイズによっては開くと重くなりますのでご注意ください

### バイナリデータとアスキーデータの違い
両者とも復号すれば全く同じファイルが生成されるため、基本的にはどちらでも良いと思います。主な違いは以下のとおりです。

| | バイナリデータ | アスキーデータ |
| :---: | --- | --- |
| **利点** | • ファイルサイズが元のファイルと変わらない | • テキストエディタで開ける<br>• 差分表示ができる |
| **欠点** | • テキストエディタでは開けない<br>• 差分表示ができない | • ファイルサイズが膨らむ [^size] |
| **拡張子** | `.gpg` | `.asc` |

[^size]: 筆者の環境で 1.37 GB の ZIP ファイルをこの方法で暗号化したところ 1.85 GB になりました。

## 出力先を変更
デフォルトでは、暗号化されたファイルの出力先は暗号化前のファイルと同じディレクトリです。出力先を変更する場合は `--output` または `-o` オプションを指定します。

```shell
gpg --encrypt --output /tmp/encrypted.zip.gpg --recipient you@example.com foo.zip
```

* 上記の例では `/tmp/encrypted.zip.gpg` が生成されるはずです
* **ファイル名まで含めて指定してください**
    * ディレクトリ名で終わるとそのディレクトリが暗号化ファイルになってしまうのでご注意ください

## よく使用するオプション一覧
上記で説明したよく使用するオプションの一覧を以下にまとめます。

| ロングオプション | ショートオプション | 説明 |
| --- | --- | --- |
| `--armor` | `-a` | バイナリではなくアスキーデータで出力します |
| `--encrypt` | `-e` | ファイルを暗号化します |
| `--output PATH` | `-o PATH` | 暗号化されたファイルの出力先を指定します |
| `--recipient KEY` | `-r KEY` | 使用する秘密鍵を選択します |



# 復号
暗号化したファイルを復号するには以下のコマンドを実行します。

```shell
gpg foo.zip.gpg
```

* 上記の例では同ディレクトリに復号されたファイル `foo.zip` が生成されるはずです
* 暗号化のとき同様に `--output` または `-o` オプションが利用可能です
* 復号には `--decrypt` または `-d` オプションを明示的に指定することもできます
    * ただし通常は勝手に推測してくれるので省略可能です
    * このオプションを指定した場合は `--output` または `-o` オプションを指定しないと、ファイルではなくターミナルに標準出力されてしまうのでご注意ください（下記コマンド参照）

```shell
gpg --decrypt --output /tmp/decrypted.zip foo.zip.gpg
```



# 参考
* [GPGコマンドで暗号化・復号](https://qiita.com/r_saiki/items/fb0bbbaa861e93f65ce9)
* [GnuPGでファイルを暗号化・復号する手順](https://laboradian.com/encrypt-with-gpg/)