blob: 57c216badd511c1e915d942d30cf10ef89ed6268 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
|
#!/usr/bin/env bash
set -euo pipefail
WORKDIR="$(mktemp -d)"
cleanup() {
if [[ -d "$WORKDIR" ]]; then
find "$WORKDIR" -type f -exec shred -u -z {} \; 2>/dev/null || true
rm -rf "$WORKDIR"
fi
}
trap cleanup EXIT
usage() {
echo "Usage:"
echo " $0 export <filename> Export all GPG keys to an encrypted file"
echo " $0 import <filename> Decrypt and import keys from a backup file"
exit 1
}
do_export() {
local outfile="$1"
if [[ -e "$outfile" ]]; then
echo "!! Refusing to overwrite existing file: $outfile" >&2
exit 1
fi
echo "==> Exporting public keys..."
gpg --export --armor > "$WORKDIR/public-keys.asc"
echo "==> Exporting secret keys..."
gpg --export-secret-keys --armor > "$WORKDIR/secret-keys.asc"
echo "==> Exporting secret subkeys (if any)..."
gpg --export-secret-subkeys --armor > "$WORKDIR/secret-subkeys.asc" || true
echo "==> Exporting owner trust database..."
gpg --export-ownertrust > "$WORKDIR/ownertrust.txt"
echo "==> Exporting revocation certificates..."
mkdir -p "$WORKDIR/revocation-certs"
if [[ -d "$HOME/.gnupg/openpgp-revocs.d" ]]; then
cp "$HOME"/.gnupg/openpgp-revocs.d/*.rev "$WORKDIR/revocation-certs/" 2>/dev/null || true
fi
echo "==> Bundling everything into a single archive..."
tar -C "$WORKDIR" -cf "$WORKDIR/gpg-full-backup.tar" \
public-keys.asc \
secret-keys.asc \
secret-subkeys.asc \
ownertrust.txt \
revocation-certs
echo "==> Encrypting with GPG (AES256, SHA512, max S2K iteration count)..."
echo " You will be prompted for a passphrase — use a strong one."
gpg --symmetric \
--cipher-algo AES256 \
--digest-algo SHA512 \
--s2k-mode 3 \
--s2k-digest-algo SHA512 \
--s2k-count 65011712 \
--output "$outfile" \
"$WORKDIR/gpg-full-backup.tar"
echo "==> Verifying: attempting decryption to confirm it works..."
if gpg --decrypt "$outfile" > "$WORKDIR/verify.tar" 2>/dev/null; then
if cmp -s "$WORKDIR/gpg-full-backup.tar" "$WORKDIR/verify.tar"; then
echo "==> Verification succeeded: backup decrypts correctly."
else
echo "!! WARNING: decrypted content does not match original. Investigate before trusting this backup." >&2
exit 1
fi
else
echo "!! WARNING: decryption test failed." >&2
exit 1
fi
echo
echo "==> Done."
echo " Encrypted backup: $outfile"
echo " Store this file somewhere safe (offline media, encrypted drive)."
echo " The S2K iteration count only helps if your passphrase itself"
echo " has real entropy (e.g. a long diceware passphrase)."
}
do_import() {
local infile="$1"
if [[ ! -f "$infile" ]]; then
echo "!! File not found: $infile" >&2
exit 1
fi
echo "==> Decrypting $infile ..."
echo " You will be prompted for the backup's passphrase."
echo " Note: this may take a while due to the high S2K iteration count."
gpg --decrypt "$infile" > "$WORKDIR/gpg-full-backup.tar"
echo "==> Extracting archive..."
tar -C "$WORKDIR" -xf "$WORKDIR/gpg-full-backup.tar"
echo "==> Importing public keys..."
gpg --import "$WORKDIR/public-keys.asc"
echo "==> Importing secret keys..."
gpg --import "$WORKDIR/secret-keys.asc"
if [[ -s "$WORKDIR/secret-subkeys.asc" ]]; then
echo "==> Importing secret subkeys..."
gpg --import "$WORKDIR/secret-subkeys.asc" || true
fi
if [[ -f "$WORKDIR/ownertrust.txt" ]]; then
echo "==> Importing owner trust database..."
gpg --import-ownertrust "$WORKDIR/ownertrust.txt"
fi
if [[ -d "$WORKDIR/revocation-certs" ]] && [[ -n "$(ls -A "$WORKDIR/revocation-certs" 2>/dev/null)" ]]; then
echo "==> Restoring revocation certificates..."
mkdir -p "$HOME/.gnupg/openpgp-revocs.d"
cp "$WORKDIR"/revocation-certs/*.rev "$HOME/.gnupg/openpgp-revocs.d/" 2>/dev/null || true
fi
echo
echo "==> Done. Keys imported into your GPG keyring."
echo " Run 'gpg --list-secret-keys' to confirm."
}
# Main
if [[ $# -ne 2 ]]; then
usage
fi
command="$1"
filename="$2"
case "$command" in
export)
do_export "$filename"
;;
import)
do_import "$filename"
;;
*)
usage
;;
esac
|