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
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
|
#!/usr/bin/env bash
# vim:syntax=sh:ts=4
# Small helper to import new keyrings to /etc/apt/keyrings, i.e. to replace
# "apt-key add" by something that does adhere to the new standard.
# This requires ln-initfunctions, see:
# - https://git.lirion.de/lirion-initfunctions/
# - https://packages.lirion.de/deb/pool/utils/l/ln-initfunctions/
# - https://packages.lirion.de/rpm/all/Packages/
# - https://packages.lirion.de/arch/
# shellcheck disable=SC1091
source '/usr/lib/lirion/ln-initfunctions' || exit 1
DEFKS='keyserver.ubuntu.com'
KRDIR='/etc/apt/keyrings'
GPGBIN='/usr/bin/gpg'
# being more defensive here - there are still a number of raging old systems
# running out there like SUSE's SLE 12 - /bin should be linked on any others,
# so let's use the old path for the time being:
SUDOBIN='/bin/sudo'
# TOUCHBIN='/bin/touch'
INSTBIN='/bin/install'
RMBIN='/bin/rm'
function hayulp {
printf '\033[1mUSAGE:\033[0m \033[3m%b\033[0m -i KEYID -k KEYRING_SHORT [ -s KEYSERVER ]\n' "$(basename "$0")"
printf '\n'
printf 'Import GPG keys from GPG key servers.\n'
printf '\n'
printf 'This is meant as a helper replacing "apt-key add" which does not adhere to current standards.\n'
printf 'Effectively, it uses gpg --recv-keys and keyring imports to place files in /etc/apt/keyrings.\n'
printf 'Mind you if your IT dept. in 2025 still does not offer a GPG route, you have to use other means.\n'
printf '\n'
(
printf -- '--help,\n'
printf -- '-h;This help\n;\n'
printf -- '--key-id,\n'
printf -- '-i;ID of key to be fetched from the public and imported\n;\n'
printf -- '--keyring-short,\n'
printf -- '-k;Name of the keyring file to save, without directory or\n'
printf ';file extension (/etc/apt/keyrings/my-moniker.gpg becomes my-moniker)\n;\n'
printf -- '--keyserver,\n'
printf -- '-s;HKPS key server to use (Default: %b)\n' "$DEFKS"
) | column -ts\;
}
if [ -z "$1" ]; then
hayulp
printf '\n\033[1m\033[3mNo option given, aborting!\033[0m\n' >&2
exit 101
fi
declare KID KRING KSRV
while [[ $# -gt 0 ]]; do
case "$1" in
'-h'|'--help')
hayulp
exit 0
;;
'-i'|'--key-id')
shift
KID="$1"
shift
;;
'-k'|'--keyring-short')
shift
KRING="$1"
shift
;;
'-s'|'--keyserver')
shift
KSRV="$1"
shift
;;
*)
hayulp
printf '\n\033[1m\033[3mNot a valid option: "%b"\033[0m\n' "$1" >&2
exit 102
;;
esac
done
if [ -z "$KID" ]; then
hayulp
printf '\n\033[1;3mNo key ID specified, aborting.\033[0m\n' >&2
exit 103
fi
if [ -z "$KRING" ]; then
hayulp
printf '\n\033[3;1mNo keyring shortname specified, aborting.\033[0m\n' >&2
exit 104
fi
if printf '%b' "$KRING" | grep '/' > /dev/null; then
hayulp
printf '\n\033[3;1mDo not specify the full path for the keyring file.\033[0m\n' >&2
exit 105
elif printf '%b' "$KRING" | grep -P '\.gpg$' > /dev/null; then
hayulp
printf '\n\033[3;1mOnly specify the file name without .gpg extension.\033[0m\n' >&2
exit 106
fi
if ! printf '%b' "$KID" | grep -P '^([0-9A-Fa-f]{8}){1,2}$|^[0-9A-Fa-f]{40}$' > /dev/null; then
hayulp
printf '\n\033[3;1mNot a valid key ID: "%b"\033[0m\n' "$KID" >&2
exit 107
fi
if [ -z "$KSRV" ]; then
KSRV="$DEFKS"
else
KSRV="$(printf '%b' "$KSRV" | sed 's#^[a-z]\+://##')"
fi
lnbegin "Using keyserver: $KSRV"; lninfo
KID="$(printf '%b' "$KID" | tr '[:lower:]' '[:upper:]')"
lnbegin "Creating temporary keyring file"
if KRTMP="$(mktemp -p /tmp apt-keyring.XXXXXX 2>/dev/null)"; then
lnok
else
lnfail
exit 110
fi
lnbegin "Importing key ID \"$KID\" to temporary file"
if myout="$("$GPGBIN" --no-default-keyring --keyserver "$KSRV" --keyring "$KRTMP" --recv-keys "$KID" 2>&1)"; then
lnok
else
lnfail
printf '\n%b\n' "$myout" >&2
exit 111
fi
lnbegin "Importing new/updated key to ${KRING}.gpg"
# Ensure the file exists prior to importing - otherwise the result may not be the desired
# OpenPGP v4 keyring. If it does exist before, even if empty, that will be the case.
if [ ! -e "${KRDIR}/${KRING}.gpg" ]; then
if myout="$("$SUDOBIN" "$INSTBIN" -oroot -groot -vm0644 /dev/null "${KRDIR}/${KRING}.gpg" 2>&1)"; then
lnprog 'file created'
else
lnfail "file cannot be created"
printf '\n%b\n' "$myout" >&2
exit 112
fi
fi
# Actual import to the target file:
if myout="$("$SUDOBIN" "$GPGBIN" --no-default-keyring --keyring "${KRDIR}/${KRING}.gpg" --import "$KRTMP" 2>&1)"; then
lnok
else
lnfail "import failed"
printf '\n%b\n' "$myout" >&2
exit 113
fi
lnbegin "Removing GPG temporary file"
if myout="$("$SUDOBIN" "$RMBIN" -f "${KRDIR}/${KRING}.gpg~" 2>&1)"; then
lnok
else
lnfail "removal failed"
printf '\n%b\n' "$myout" >&2
exit 120
fi
lnbegin "Removing temporary keyring"
if myout="$("$RMBIN" -f "$KRTMP" "${KRTMP}~" 2>/dev/null)"; then
lnok
else
lnfail
printf '\n%b\n' "$myout" >&2
exit 121
fi
printf '\033[3mListing keyring content:\033[0m\n'
"$GPGBIN" --no-default-keyring --keyring "${KRDIR}/${KRING}.gpg" --list-keys
|