4 # - decryption/verification with signer key not available
5 # - verification of signatures from expired/revoked keys
7 test_description='PGP/MIME signature verification and decryption'
8 . $(dirname "$0")/test-lib.sh || exit 1
10 ##################################################
14 test_begin_subtest "emacs delivery of signed message"
17 "test signed message 001" \
18 "This is a test signed message." \
19 "(mml-secure-message-sign)"'
21 test_begin_subtest "signed part content-type indexing"
22 output=$(notmuch search mimetype:multipart/signed and mimetype:application/pgp-signature | notmuch_search_sanitize)
23 test_expect_equal "$output" "thread:XXX 2000-01-01 [1/1] Notmuch Test Suite; test signed message 001 (inbox signed)"
25 test_begin_subtest "signature verification"
26 output=$(notmuch show --format=json --verify subject:"test signed message 001" \
27 | notmuch_json_show_sanitize \
28 | sed -e 's|"created": [1234567890]*|"created": 946728000|g')
29 expected='[[[{"id": "XXXXX",
32 "filename": ["YYYYY"],
33 "timestamp": 946728000,
34 "date_relative": "2000-01-01",
35 "tags": ["inbox","signed"],
36 "crypto": {"signed": {"status": [{ "status": "good", "created": 946728000, "fingerprint": "'$FINGERPRINT'", "userid": "'"$SELF_USERID"'"}]}},
37 "headers": {"Subject": "test signed message 001",
38 "From": "Notmuch Test Suite <test_suite@notmuchmail.org>",
39 "To": "test_suite@notmuchmail.org",
40 "Date": "Sat, 01 Jan 2000 12:00:00 +0000"},
42 "sigstatus": [{"status": "good",
43 "fingerprint": "'$FINGERPRINT'",
45 "userid": "'"$SELF_USERID"'"}],
46 "content-type": "multipart/signed",
48 "content-type": "text/plain",
49 "content": "This is a test signed message.\n"},
51 "content-type": "application/pgp-signature",
52 "content-length": "NONZERO"}]}]},
54 test_expect_equal_json \
58 test_begin_subtest "detection of modified signed contents"
60 "bad signed message 001" \
61 "Incriminating stuff. This is a test signed message." \
62 "(mml-secure-message-sign)"
64 file=$(notmuch search --output=files subject:"bad signed message 001")
66 sed -i 's/Incriminating stuff. //' ${file}
68 output=$(notmuch show --format=json --verify subject:"bad signed message 001" \
69 | notmuch_json_show_sanitize \
70 | sed -e 's|"created": [1234567890]*|"created": 946728000|')
71 expected='[[[{"id": "XXXXX",
74 "filename": ["YYYYY"],
75 "timestamp": 946728000,
76 "date_relative": "2000-01-01",
77 "tags": ["inbox","signed"],
78 "crypto": {"signed": {"status": [{ "status": "bad", "keyid": "'$(echo $FINGERPRINT | cut -c 25-)'"}]}},
79 "headers": {"Subject": "bad signed message 001",
80 "From": "Notmuch Test Suite <test_suite@notmuchmail.org>",
81 "To": "test_suite@notmuchmail.org",
82 "Date": "Sat, 01 Jan 2000 12:00:00 +0000"},
84 "sigstatus": [{"status": "bad",
85 "keyid": "'$(echo $FINGERPRINT | cut -c 25-)'"}],
86 "content-type": "multipart/signed",
88 "content-type": "text/plain",
89 "content": "This is a test signed message.\n"},
91 "content-type": "application/pgp-signature",
92 "content-length": "NONZERO"}]}]},
94 test_expect_equal_json \
98 test_begin_subtest "corrupted pgp/mime signature"
100 "bad signed message 002" \
101 "Incriminating stuff. This is a test signed message." \
102 "(mml-secure-message-sign)"
104 file=$(notmuch search --output=files subject:"bad signed message 002")
106 awk '/-----BEGIN PGP SIGNATURE-----/{flag=1;print;next} \
107 /-----END PGP SIGNATURE-----/{flag=0;print;next} \
108 flag{gsub(/[A-Za-z]/,"0");print}!flag{print}' $file > $file.new
113 output=$(notmuch show --format=json --verify subject:"bad signed message 002" \
114 | notmuch_json_show_sanitize \
115 | sed -e 's|"created": [1234567890]*|"created": 946728000|')
116 expected='[[[{"id": "XXXXX",
120 "filename": ["YYYYY"],
121 "timestamp": 946728000,
122 "date_relative": "2000-01-01",
123 "tags": ["inbox","signed"],
124 "headers": {"Subject": "bad signed message 002",
125 "From": "Notmuch Test Suite <test_suite@notmuchmail.org>",
126 "To": "test_suite@notmuchmail.org",
127 "Date": "Sat, 01 Jan 2000 12:00:00 +0000"},
130 "content-type": "multipart/signed",
131 "content": [{"id": 2,
132 "content-type": "text/plain",
133 "content": "Incriminating stuff. This is a test signed message.\n"},
135 "content-type": "application/pgp-signature",
136 "content-length": "NONZERO"}]}]},
138 test_expect_equal_json \
142 test_begin_subtest "signature verification without full user ID validity"
143 # give the key no owner trust, removes validity on all user IDs of the
144 # certificate in the absence of other trusted certifiers:
145 gpg --quiet --batch --no-tty --export-ownertrust > "$GNUPGHOME/ownertrust.bak"
146 echo "${FINGERPRINT}:3:" | gpg --quiet --batch --no-tty --import-ownertrust
147 output=$(notmuch show --format=json --verify subject:"test signed message 001" \
148 | notmuch_json_show_sanitize \
149 | sed -e 's|"created": [1234567890]*|"created": 946728000|g')
150 expected='[[[{"id": "XXXXX",
153 "filename": ["YYYYY"],
154 "timestamp": 946728000,
155 "date_relative": "2000-01-01",
156 "tags": ["inbox","signed"],
157 "crypto": {"signed": {"status": [{ "status": "good", "created": 946728000, "fingerprint": "'$FINGERPRINT'"}]}},
158 "headers": {"Subject": "test signed message 001",
159 "From": "Notmuch Test Suite <test_suite@notmuchmail.org>",
160 "To": "test_suite@notmuchmail.org",
161 "Date": "Sat, 01 Jan 2000 12:00:00 +0000"},
163 "sigstatus": [{"status": "good",
164 "fingerprint": "'$FINGERPRINT'",
165 "created": 946728000}],
166 "content-type": "multipart/signed",
167 "content": [{"id": 2,
168 "content-type": "text/plain",
169 "content": "This is a test signed message.\n"},
171 "content-type": "application/pgp-signature",
172 "content-length": "NONZERO"}]}]},
174 test_expect_equal_json \
177 gpg --quiet --batch --no-tty --import-ownertrust < "$GNUPGHOME/ownertrust.bak"
179 test_begin_subtest "signature verification with signer key unavailable"
180 # move the gnupghome temporarily out of the way
181 mv "${GNUPGHOME}"{,.bak}
182 output=$(notmuch show --format=json --verify subject:"test signed message 001" \
183 | notmuch_json_show_sanitize \
184 | sed -e 's|"created": [1234567890]*|"created": 946728000|g')
185 expected='[[[{"id": "XXXXX",
188 "filename": ["YYYYY"],
189 "timestamp": 946728000,
190 "date_relative": "2000-01-01",
191 "tags": ["inbox","signed"],
192 "crypto": {"signed": {"status": [{"errors": {"key-missing": true}, "keyid": "'$(echo $FINGERPRINT | cut -c 25-)'", "status": "error"}]}},
193 "headers": {"Subject": "test signed message 001",
194 "From": "Notmuch Test Suite <test_suite@notmuchmail.org>",
195 "To": "test_suite@notmuchmail.org",
196 "Date": "Sat, 01 Jan 2000 12:00:00 +0000"},
198 "sigstatus": [{"status": "error",
199 "keyid": "'$(echo $FINGERPRINT | cut -c 25-)'",
200 "errors": {"key-missing": true}}],
201 "content-type": "multipart/signed",
202 "content": [{"id": 2,
203 "content-type": "text/plain",
204 "content": "This is a test signed message.\n"},
206 "content-type": "application/pgp-signature",
207 "content-length": "NONZERO"}]}]},
209 test_expect_equal_json \
212 mv "${GNUPGHOME}"{.bak,}
214 test_begin_subtest "emacs delivery of encrypted message with attachment"
215 # create a test encrypted message with attachment
216 cat <<EOF >TESTATTACHMENT
219 test_expect_success \
221 "test encrypted message 001" \
222 "This is a test encrypted message.\n" \
223 "(mml-attach-file \"TESTATTACHMENT\") (mml-secure-message-encrypt)"'
225 test_begin_subtest "encrypted part content-type indexing"
226 output=$(notmuch search mimetype:multipart/encrypted and mimetype:application/pgp-encrypted and mimetype:application/octet-stream | notmuch_search_sanitize)
227 test_expect_equal "$output" "thread:XXX 2000-01-01 [1/1] Notmuch Test Suite; test encrypted message 001 (encrypted inbox)"
229 test_begin_subtest "decryption, --format=text"
230 output=$(notmuch show --format=text --decrypt=true subject:"test encrypted message 001" \
231 | notmuch_show_sanitize_all \
232 | sed -e 's|"created": [1234567890]*|"created": 946728000|')
233 expected='
\fmessage{ id:XXXXX depth:0 match:1 excluded:0 filename:XXXXX
235 Notmuch Test Suite <test_suite@notmuchmail.org> (2000-01-01) (encrypted inbox)
236 Subject: test encrypted message 001
237 From: Notmuch Test Suite <test_suite@notmuchmail.org>
238 To: test_suite@notmuchmail.org
239 Date: Sat, 01 Jan 2000 12:00:00 +0000
242 \fpart{ ID: 1, Content-type: multipart/encrypted
243 \fpart{ ID: 2, Content-type: application/pgp-encrypted
244 Non-text part: application/pgp-encrypted
246 \fpart{ ID: 3, Content-type: multipart/mixed
247 \fpart{ ID: 4, Content-type: text/plain
248 This is a test encrypted message.
250 \fattachment{ ID: 5, Filename: TESTATTACHMENT, Content-type: application/octet-stream
251 Non-text part: application/octet-stream
261 test_begin_subtest "decryption, --format=json"
262 output=$(notmuch show --format=json --decrypt=true subject:"test encrypted message 001" \
263 | notmuch_json_show_sanitize \
264 | sed -e 's|"created": [1234567890]*|"created": 946728000|')
265 expected='[[[{"id": "XXXXX",
268 "filename": ["YYYYY"],
269 "timestamp": 946728000,
270 "date_relative": "2000-01-01",
271 "tags": ["encrypted","inbox"],
272 "crypto": {"decrypted": {"status": "full"}},
273 "headers": {"Subject": "test encrypted message 001",
274 "From": "Notmuch Test Suite <test_suite@notmuchmail.org>",
275 "To": "test_suite@notmuchmail.org",
276 "Date": "Sat, 01 Jan 2000 12:00:00 +0000"},
278 "encstatus": [{"status": "good"}],
279 "content-type": "multipart/encrypted",
280 "content": [{"id": 2,
281 "content-type": "application/pgp-encrypted",
282 "content-length": "NONZERO"},
284 "content-type": "multipart/mixed",
285 "content": [{"id": 4,
286 "content-type": "text/plain",
287 "content": "This is a test encrypted message.\n"},
289 "content-type": "application/octet-stream",
290 "content-disposition": "attachment",
291 "content-length": "NONZERO",
292 "content-transfer-encoding": "base64",
293 "filename": "TESTATTACHMENT"}]}]}]},
295 test_expect_equal_json \
299 test_begin_subtest "decryption, --format=json, --part=4"
300 output=$(notmuch show --format=json --part=4 --decrypt=true subject:"test encrypted message 001" \
301 | notmuch_json_show_sanitize \
302 | sed -e 's|"created": [1234567890]*|"created": 946728000|')
304 "content-type": "text/plain",
305 "content": "This is a test encrypted message.\n"}'
306 test_expect_equal_json \
310 test_begin_subtest "decrypt attachment (--part=5 --format=raw)"
315 subject:"test encrypted message 001" >OUTPUT
316 test_expect_equal_file TESTATTACHMENT OUTPUT
318 test_begin_subtest "decryption failure with missing key"
319 mv "${GNUPGHOME}"{,.bak}
320 output=$(notmuch show --format=json --decrypt=true subject:"test encrypted message 001" \
321 | notmuch_json_show_sanitize \
322 | sed -e 's|"created": [1234567890]*|"created": 946728000|')
323 expected='[[[{"id": "XXXXX",
327 "filename": ["YYYYY"],
328 "timestamp": 946728000,
329 "date_relative": "2000-01-01",
330 "tags": ["encrypted","inbox"],
331 "headers": {"Subject": "test encrypted message 001",
332 "From": "Notmuch Test Suite <test_suite@notmuchmail.org>",
333 "To": "test_suite@notmuchmail.org",
334 "Date": "Sat, 01 Jan 2000 12:00:00 +0000"},
336 "encstatus": [{"status": "bad"}],
337 "content-type": "multipart/encrypted",
338 "content": [{"id": 2,
339 "content-type": "application/pgp-encrypted",
340 "content-length": "NONZERO"},
342 "content-type": "application/octet-stream",
343 "content-length": "NONZERO"}]}]},
345 test_expect_equal_json \
348 mv "${GNUPGHOME}"{.bak,}
350 test_begin_subtest "emacs delivery of encrypted + signed message"
351 test_expect_success \
353 "test encrypted message 002" \
354 "This is another test encrypted message.\n" \
355 "(mml-secure-message-sign-encrypt)"'
357 test_begin_subtest "decryption + signature verification"
358 output=$(notmuch show --format=json --decrypt=true subject:"test encrypted message 002" \
359 | notmuch_json_show_sanitize \
360 | sed -e 's|"created": [1234567890]*|"created": 946728000|g')
361 expected='[[[{"id": "XXXXX",
364 "filename": ["YYYYY"],
365 "timestamp": 946728000,
366 "date_relative": "2000-01-01",
367 "tags": ["encrypted","inbox"],
368 "crypto": {"signed": {"status": [{ "status": "good", "created": 946728000, "fingerprint": "'$FINGERPRINT'", "userid": "'"$SELF_USERID"'"}],
370 "decrypted": {"status": "full"}},
371 "headers": {"Subject": "test encrypted message 002",
372 "From": "Notmuch Test Suite <test_suite@notmuchmail.org>",
373 "To": "test_suite@notmuchmail.org",
374 "Date": "Sat, 01 Jan 2000 12:00:00 +0000"},
376 "encstatus": [{"status": "good"}],
377 "sigstatus": [{"status": "good",
378 "fingerprint": "'$FINGERPRINT'",
379 "created": 946728000,
380 "userid": "'"$SELF_USERID"'"}],
381 "content-type": "multipart/encrypted",
382 "content": [{"id": 2,
383 "content-type": "application/pgp-encrypted",
384 "content-length": "NONZERO"},
386 "content-type": "text/plain",
387 "content": "This is another test encrypted message.\n"}]}]},
389 test_expect_equal_json \
393 test_begin_subtest "reply to encrypted message"
394 output=$(notmuch reply --decrypt=true subject:"test encrypted message 002" \
395 | notmuch_drop_mail_headers In-Reply-To References)
396 expected='From: Notmuch Test Suite <test_suite@notmuchmail.org>
397 Subject: Re: test encrypted message 002
398 To: test_suite@notmuchmail.org
400 On 01 Jan 2000 12:00:00 -0000, Notmuch Test Suite <test_suite@notmuchmail.org> wrote:
401 > This is another test encrypted message.'
406 test_begin_subtest "Reply within emacs to an encrypted message"
407 test_emacs "(let ((message-hidden-headers '())
408 (notmuch-crypto-process-mime 't))
409 (notmuch-show \"subject:test.encrypted.message.002\")
412 grep -v -e '^In-Reply-To:' -e '^References:' -e '^Fcc:' < OUTPUT > OUTPUT.clean
414 From: Notmuch Test Suite <test_suite@notmuchmail.org>
415 To: test_suite@notmuchmail.org
416 Subject: Re: test encrypted message 002
417 --text follows this line--
418 <#secure method=pgpmime mode=signencrypt>
419 Notmuch Test Suite <test_suite@notmuchmail.org> writes:
421 > This is another test encrypted message.
423 test_expect_equal_file EXPECTED OUTPUT.clean
425 test_begin_subtest "signature verification with revoked key"
426 # generate revocation certificate and load it to revoke key
429 Notmuch Test Suite key revocation (automated) $(date '+%F_%T%z')
434 | gpg --no-tty --quiet --command-fd 0 --armor --gen-revoke "0x${FINGERPRINT}!" 2>/dev/null \
435 | gpg --no-tty --quiet --import
436 output=$(notmuch show --format=json --verify subject:"test signed message 001" \
437 | notmuch_json_show_sanitize \
438 | sed -e 's|"created": [1234567890]*|"created": 946728000|')
439 expected='[[[{"id": "XXXXX",
442 "filename": ["YYYYY"],
443 "timestamp": 946728000,
444 "date_relative": "2000-01-01",
445 "tags": ["inbox","signed"],
446 "crypto": {"signed": {"status": [{"errors": {"key-revoked": true}, "keyid": "'$(echo $FINGERPRINT | cut -c 25-)'", "status": "error"}]}},
447 "headers": {"Subject": "test signed message 001",
448 "From": "Notmuch Test Suite <test_suite@notmuchmail.org>",
449 "To": "test_suite@notmuchmail.org",
450 "Date": "Sat, 01 Jan 2000 12:00:00 +0000"},
452 "sigstatus": [{"status": "error",
453 "keyid": "6D92612D94E46381",
454 "errors": {"key-revoked": true}}],
455 "content-type": "multipart/signed",
456 "content": [{"id": 2,
457 "content-type": "text/plain",
458 "content": "This is a test signed message.\n"},
460 "content-type": "application/pgp-signature",
461 "content-length": "NONZERO"}]}]},
463 test_expect_equal_json \