-
Notifications
You must be signed in to change notification settings - Fork 0
/
sign.sh
executable file
·169 lines (123 loc) · 4.61 KB
/
sign.sh
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
#!/bin/bash -eu
# Copyright (C) Mats G. Liljegren <[email protected]>
# SPDX-License-Identifier: BSD-2-Clause
#################################
# Configurations
# Change this!
#readonly policyUrl="http://mats.mexit.se/files/gpg-signature-policy.md"
#readonly signingKeyId=CB9C8689AEA6A954
# Be verbose, 0 = false, 1 = true
readonly verbose=0
#################################
# End of configurations
# Sign all keys found as files with .gpg as extension in the current working
# directory. All signed key files are written to "out" sub-directory to
# current working directory.
#
# Syntax:
# sign.sh
# Determine gpg verbose parameter
case $verbose in
0) VERB="-q" ;;
1) VERB="" ;;
2) VERB="-v" ;;
*) VERB="-vv" ;;
esac
# Working directory, cleaned up at exit
readonly wdir=$(mktemp -d -t sign.XXXXXXXXXX)
# Output directory, this is where all resulting files are placed
readonly odir="$(pwd)/out"
# GPG command with ubiquitous parameters
readonly GPG="$(which gpg2)"
# Make sure GPG uses the correct TTY
export GPG_TTY=$(tty)
# Function run when exiting script
function finish {
rm -rf "$wdir"
}
# Make sure above function is run when script exits
trap finish EXIT
# Import key file, sign the key, and export to a keyfile in the working
# directory
# Export key to be signed including signature for given uid.
# Key will be exported to a file encrypted by the key to be signed.
#
# Assumptions:
# The key is found in ${wdir}/${keyid}.gpg, which should be done by signKey()
createSignature() {
declare -r keyid="$1"
declare -r uid="$2"
declare -r uidIdx="$3"
declare -r keyfile="$4"
# E-mail part of uid
declare -r email=$(echo "$uid" | sed -r 's/.*<(.*)>.*/\1/')
# Keyring to use while working with the key
declare -r keyring="${wdir}/${keyid}.${uidIdx}.keyring"
# If no email, then nothing to do
[[ -z $email ]] && return 0
$GPG $VERB --yes --no-default-keyring --keyring ${keyring} --import ${keyfile}
declare -r fullKeyId=$($GPG $VERB --yes --no-default-keyring --keyring ${keyring} --with-colons --list-keys ${keyid} | egrep '^pub:' -m 1 | sed -r 's/^.*:(.*?):.*:.*:.*:.*:.*:.*:.*:$/\1/')
declare -a uids
# Get list of all uids in the key
IFS='
' uids=($($GPG $VERB --yes --no-default-keyring --keyring ${keyring} --with-colons --list-keys ${keyid} | sed -rn 's/^uid:.*:(.*):$/\1/p'))
# Filter out unwanted uids
declare -ia removeUids=()
declare -i idx
for (( idx = 0; idx < ${#uids[@]}; idx++ )); do
if [[ ${uids[idx]} != $uid ]]; then
# Unwanted uid, mark for removal
removeUids+=($(( idx+1 )) )
fi
done
[[ ${#removeUids[@]} > 0 ]] && $GPG $VERB --yes --no-default-keyring --keyring ${keyring} --key-edit ${keyid} ${removeUids[@]:-} deluid save
# File name of key to create
declare -r keyfileToCreate="${odir}/${fullKeyId}.${uidIdx}-signed-by-${signingKeyId}.asc"
# Export key now containing only the wanted uid
$GPG $VERB --yes --no-default-keyring --keyring ${keyring} --output ${keyfileToCreate} --armor --export ${keyid}
printf "\n---- ${keyfileToCreate}: Created ----\n\n"
}
signKey() {
declare -r keyid="$1"
declare -r keyfile="${wdir}/${keyid}.gpg"
# Import key from file to working keyring
$GPG $VERB --yes --import ${keyid}.gpg
# Remove others signatures
$GPG $VERB --yes --edit-key ${keyid} clean minimize save
# Add our own signature
$GPG $VERB --yes --sig-policy-url ${policyUrl} --default-key ${signingKeyId} --sign-key ${keyid}
# Export to a new key file from keyring
$GPG $VERB --yes --output ${keyfile} --export ${keyid}
declare -a uids
# Get list of all uids in the key
IFS='
' uids=($($GPG $VERB --yes --with-colons --list-keys ${keyid} | sed -rn 's/^uid:[-mfuws]:.*:(.*):$/\1/p'))
declare -i idx
for (( idx = 0; idx < ${#uids[@]}; idx++ )); do
createSignature "${keyid}" "${uids[idx]}" "$(( idx+1 ))" "${keyfile}"
done
}
#
# Main function
#
# Check that the policy URL is correct
read -p "$policyUrl: Enter 'y' if this is the correct policy URL: " -n 1 answer
echo
[[ $answer != y ]] && {
printf "ABORTING\n"
exit 1
}
# Copy GNUPG configuration, so we do not alter the original one
mkdir ${wdir}/gnupg
cp -r ${GNUPGHOME:-~/.gnupg}/* ${wdir}/gnupg
# Start using our own GNUPG configuration
export GNUPGHOME=${wdir}/gnupg
# Ensure correct access rights to gnupg directory
chmod 0700 $GNUPGHOME
# Create output directory, if needed
mkdir -p ${odir}
# Iterate all GPG files in current directory
for file in *.gpg; do
keyid=$(basename $file .gpg)
signKey "$keyid" || printf "**** WARNING: Key ${keyid} not signed!\n" >&2
done