公開されている場所にバックアップファイルを置いても平気になる方法

# こんなこ いるかな？

この投稿はこのようなかた向けです。
- バックアップを取りたいかた。
- 取ったバックアップが人目にさらされるかた。
- 人目についても問題が無いようにしたいかた。

## まずは方針

方針をこのように立てました。
- バックアップしたファイルを他人に読ませない。
- バックアップはリストアのみに使うので何時でも取り出す必要はない。
- 多少時間がかかるのはこの際目をつぶる。

## このソリューションを提供します

私がとった方法です。
- できれば圧縮したいのでtar.gz化しておく。
- GnuPGを使って暗号化する。
- メイン機はWindowsなのでWSLを使う。

## いちから説明

GnuPG(The GNU Privacy Guard)はPGPの方式に則った暗号化ツールです。これを使います。
前提条件としてWSLが入っていることとします。

### GnuPG を使う方法

まずは秘密鍵と公開鍵を作ります。

```bash
$ gpg --expert --full-gen-key
gpg (GnuPG) 2.2.19; Copyright (C) 2019 Free Software Foundation, Inc.
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

ご希望の鍵の種類を選択してください:
   (1) RSA と RSA (デフォルト)
   (2) DSA と Elgamal
   (3) DSA (署名のみ)
   (4) RSA (署名のみ)
   (7) DSA (機能をあなた自身で設定)
   (8) RSA (機能をあなた自身で設定)
   (9) ECC と ECC
  (10) ECC (署名のみ)
  (11) ECC (機能をあなた自身で設定)
  (13) 既存の鍵
  (14) カードに存在する鍵
あなたの選択は?
```
問答無用で「9」を選択します。
```bash
ご希望の楕円曲線を選択してください:
   (1) Curve 25519
   (3) NIST P-256
   (4) NIST P-384
   (5) NIST P-521
   (6) Brainpool P-256
   (7) Brainpool P-384
   (8) Brainpool P-512
   (9) secp256k1
あなたの選択は?
```
これも即答で「1」です。
```bash
鍵の有効期限を指定してください。
         0 = 鍵は無期限
      <n>  = 鍵は n 日間で期限切れ
      <n>w = 鍵は n 週間で期限切れ
      <n>m = 鍵は n か月間で期限切れ
      <n>y = 鍵は n 年間で期限切れ
鍵の有効期間は? (0)
```
今回は「0」で行きます。ごめんよう。
```bash
鍵は無期限です
これで正しいですか? (y/N)
```
「y」ですね。
```bash
GnuPGはあなたの鍵を識別するためにユーザIDを構成する必要があります。

本名: TestUser
電子メール・アドレス: hoge@example.com
コメント:
次のユーザIDを選択しました:
    "TestUser <hoge@example.com>"

名前(N)、コメント(C)、電子メール(E)の変更、またはOK(O)か終了(Q)?
```
OKですので「O」を押します。

![pgp_passphrase.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/494348/bf3deb38-caef-1b96-e7f0-ee845a358fe1.png)

このようにパスフレーズを作成して入力するように促されますので、パスフレーズを入力してください。

```bash
たくさんのランダム・バイトの生成が必要です。キーボードを打つ、マウスを動か
す、ディスクにアクセスするなどの他の操作を素数生成の間に行うことで、乱数生
成器に十分なエントロピーを供給する機会を与えることができます。
gpg: /home/xxxxxxxxxx/.gnupg/trustdb.gpg: 信用データベースができました
gpg: 鍵BB0DE9CD184B71D7を究極的に信用するよう記録しました
gpg: ディレクトリ'/home/xxxxxxxxxx/.gnupg/openpgp-revocs.d'が作成されました
gpg: 失効証明書を '/home/xxxxxxxxxx/.gnupg/openpgp-revocs.d/FAC5E0A8FDE951B9B924DBB8BB0DE9CD184B71D7.rev' に保管しました。
公開鍵と秘密鍵を作成し、署名しました。

pub   ed25519 2023-08-31 [SC]
      FAC5E0A8FDE951B9B924DBB8BB0DE9CD184B71D7
uid                      TestUser <hoge@example.com>
sub   cv25519 2023-08-31 [E]

```
これでカギを作成できました。試してみましょう。
```bash
touch test.txt
echo qawsedrftgyhujikolp > test.txt
```
まずはテキストを作って、暗号化してみましょう
```bash
$ gpg -e -r TestUser -a test.txt
gpg: 信用データベースの検査
gpg: marginals needed: 3  completes needed: 1  trust model: pgp
gpg: 深さ: 0  有効性:   1  署名:   0  信用: 0-, 0q, 0n, 0m, 0f, 1u
```

すると、`test.txt.asc`ができます。

```bash
$ cat test.txt.asc
-----BEGIN PGP MESSAGE-----

hF4DdHvQnbQBrSUSAQdAdCe1IHN8+ZMnvu9+gT4WSQUJh5Z2rWNsmzG7Iion034w
U+vHP/tgUfKgtBbx7GJ98q2qGa2RH9EPqPuMKuKRgACwyjuFWkiDe8uChos3ZOEb
0lcBqepGL0ZTipSG8Hey/gHpx3EC9wZhL+axVR93F+2KXa1I/vc3yoIh2oB/QCgS
TD8MO2DL8SSkJqd8gHHAJukfG2DsK4DXQc0xw0tFGRLuc+gjD4O1vv4=
=lNGW
-----END PGP MESSAGE-----
```
これでなに書いてあるかわからなくなりましたね。では復号化してみましょう。
```bash
$ gpg -o test.txt.dec -d test.txt.asc
gpg: 256-ビットECDH鍵, ID 747BD09DB401AD25, 日付2023-08-31に暗号化されました
      "TestUser <hoge@example.com>"
```

先ほどと同じようにパスフレーズを聞かれるので、入力しましょう。

```bash
$ cat test.txt.dec
qawsedrftgyhujikolp
```

元に戻りましたね。これで暗号化と復号化はできました。

### ここからが本番WSL＋GPGを使ったバックアップソリューション

結構簡単です。のでシェルスクリプトでちゃちゃっと書いちゃいましょう。

```bash:encrypted-backup.sh
#!/bin/bash

DATE=$(date '+%Y%m%d-%H%M%S')

TEMP=$(mktemp)
echo 'Test signing'

touch ${TEMP}
gpg -s -u TestUser ${TEMP}

if [ $? -ne 0 ] ; then
        rm ${TEMP}
        exit 254
fi
rm ${TEMP} ${TEMP}.gpg

tar -czvf - /mnt/c/Users/TestUser(ここはあなたのユーザ名を入れます)/Documents | gpg -o /tmp/Documents-${DATE}.tar.gz.gpg -se -r TestUser -u TestUser
```
少し変更した点は、暗号化に加えて署名で改ざんされたら気がつくように`-e -> -se`にしたところと、-a(--armor)でASCIIにする必要がなくなったのでそれを消しました。
あと、気が付いたのですが、署名は圧縮した最後にやるのですが、ここで失敗すると今までの圧縮したファイルが使えなくなってしまうで、署名を試しに一回やるってことを実施しています。

そして、`$ chmod 755 ./encrypted-backup.sh`をして、

あとは、署名時にパスフレーズを求められるので、

https://wiki.archlinux.jp/index.php/GnuPG

↑の情報を参考にしてgpg-agentの設定を以下のようにしました。

```:~/.gnupg/gpg-agent.conf
pinentry-program  /usr/bin/pinentry-curses

max-cache-ttl 60480000
default-cache-ttl 60480000
```

で、gpg-agentを一度再起動します。(1回のみでOK)
```bash
$ gpg-connect-agent reloadagent /bye
```

そのあと、
```bash
$ ./encrypted-backup.sh
```
として圧縮が終わったとことでパスフレーズの入力が促された場合、それを実施すれば…、/tmpに`Documents-20230831-112413.tar.gz.gpg`みたいなファイルができます。
これでバックアップはできました。

ついでなので、~/.bashrcを次の通り追加しています。

```bash:~/.bashrc
TEMP=$(mktemp)
export GPG_TTY=$(tty)
alias gpg-add-normal="touch ${TEMP}; gpg -r TestUser -u TestUser -se ${TEMP};if [ $? -eq 0 ]; then rm ${TEMP}.gpg; fi ;rm ${TEMP}"
gpg-add-normal
```

### リストア方法

リストアはこれとは逆をすればよいので、

```bash
$ cd /tmp/
$ gpg -o Documents-20230831-112413.tar.gz -d Documents-20230831-112413.tar.gz.gpg
$ tar xzvf Documents-20230831-112413.tar.gz
```
とすればバックアップしたファイルが手に入るようになります。

### 問題点
問題は、圧縮とか展開するのにHDD容量がいることや時間がかかることでしょうか。

:::note alert
公開されている場所のバックアップファイルは他人に消される可能性があることをお忘れなく。
:::

### おまけ：鍵のバックアップとリストア

このとき、自分の鍵ペアーをどこかに保存しておかないとなくしたらえらいこっちゃになるので、バックアップをしておきます。



まずは公開鍵のエクスポートから。
```bash
$ gpg --output public.key(ここは適当なものに) --armor --export user-id
```
インポートは、

```bash
$ gpg --import public.key
```

次に秘密鍵のエクスポート
```bash
$ gpg --export-secret-keys -o private.key --armor user-id
```

インポートはさっきの公開鍵と同じで、

```bash
$ gpg --import private.key
```
となります。

秘密鍵は絶対に他人に渡るようなことがないように厳重に保管しましょう。

おっと、忘れていました。インポートしたままだと信頼性がないので信用させる必要があります。

```bash
$ gpg --edit-key 'TestUser'
...メッセージと鍵が表示されます。...

gpg> trust

他のユーザの鍵を正しく検証するために、このユーザの信用度を決めてください
(パスポートを見せてもらったり、他から得たフィンガープリントを検査したり、などなど)

  1 = 知らない、または何とも言えない
  2 = 信用し ない
  3 = まぁまぁ信用する
  4 = 充分に信用する
  5 = 究極的に信用する
  m = メーン・メニューに戻る

あなたの決定は? 5
本当にこの鍵を究極的に信用しますか? (y/N) y
```
が必要です。


終わり。