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
9 . $NOTMUCH_SRCDIR/test/test-lib-emacs.sh || exit 1
11 ##################################################
16 test_begin_subtest "emacs delivery of signed message via fcc"
19 "test signed message 001" \
20 "This is a test signed message." \
21 "(mml-secure-message-sign)"'
23 test_begin_subtest "emacs delivery of signed message via fcc and smtp"
24 emacs_deliver_message \
25 'signed message sent via SMTP' \
26 'This is a test that messages are sent via SMTP' \
27 "(add-hook 'message-send-mail-hook (lambda () (sleep-for 1)))
28 (mml-secure-message-sign)"
29 msg_file=$(notmuch search --output=files subject:signed-message-sent-via-SMTP)
30 test_expect_equal_message_body sent_message "$msg_file"
32 test_begin_subtest "signed part content-type indexing"
33 notmuch search mimetype:multipart/signed and mimetype:application/pgp-signature | notmuch_search_sanitize > OUTPUT
35 thread:XXX 2000-01-01 [1/1] Notmuch Test Suite; test signed message 001 (inbox signed)
36 thread:XXX 2000-01-01 [1/1] Notmuch Test Suite; signed message sent via SMTP (inbox signed)
38 test_expect_equal_file EXPECTED OUTPUT
40 test_begin_subtest "signature verification"
41 output=$(notmuch show --format=json --verify subject:"test signed message 001" \
42 | notmuch_json_show_sanitize \
43 | sed -e 's|"created": [1234567890]*|"created": 946728000|g')
44 expected='[[[{"id": "XXXXX",
47 "filename": ["YYYYY"],
48 "timestamp": 946728000,
49 "date_relative": "2000-01-01",
50 "tags": ["inbox","signed"],
51 "crypto": {"signed": {"status": [{ "status": "good", "created": 946728000, "email": "'"$SELF_EMAIL"'", "fingerprint": "'$FINGERPRINT'", "userid": "'"$SELF_USERID"'"}]}},
52 "headers": {"Subject": "test signed message 001",
53 "From": "Notmuch Test Suite <test_suite@notmuchmail.org>",
54 "To": "test_suite@notmuchmail.org",
55 "Date": "Sat, 01 Jan 2000 12:00:00 +0000"},
57 "sigstatus": [{"status": "good",
58 "fingerprint": "'$FINGERPRINT'",
60 "email": "'"$SELF_EMAIL"'",
61 "userid": "'"$SELF_USERID"'"}],
62 "content-type": "multipart/signed",
64 "content-type": "text/plain",
65 "content": "This is a test signed message.\n"},
67 "content-type": "application/pgp-signature",
68 "content-length": "NONZERO"}]}]},
70 test_expect_equal_json \
74 test_begin_subtest "detection of modified signed contents"
76 "bad signed message 001" \
77 "Incriminating stuff. This is a test signed message." \
78 "(mml-secure-message-sign)"
80 file=$(notmuch search --output=files subject:"bad signed message 001")
82 sed -i 's/Incriminating stuff. //' ${file}
84 output=$(notmuch show --format=json --verify subject:"bad signed message 001" \
85 | notmuch_json_show_sanitize \
86 | sed -e 's|"created": [1234567890]*|"created": 946728000|')
87 expected='[[[{"id": "XXXXX",
90 "filename": ["YYYYY"],
91 "timestamp": 946728000,
92 "date_relative": "2000-01-01",
93 "tags": ["inbox","signed"],
94 "crypto": {"signed": {"status": [{ "status": "bad", "keyid": "'$(echo $FINGERPRINT | cut -c 25-)'"}]}},
95 "headers": {"Subject": "bad signed message 001",
96 "From": "Notmuch Test Suite <test_suite@notmuchmail.org>",
97 "To": "test_suite@notmuchmail.org",
98 "Date": "Sat, 01 Jan 2000 12:00:00 +0000"},
100 "sigstatus": [{"status": "bad",
101 "keyid": "'$(echo $FINGERPRINT | cut -c 25-)'"}],
102 "content-type": "multipart/signed",
103 "content": [{"id": 2,
104 "content-type": "text/plain",
105 "content": "This is a test signed message.\n"},
107 "content-type": "application/pgp-signature",
108 "content-length": "NONZERO"}]}]},
110 test_expect_equal_json \
114 test_begin_subtest "corrupted pgp/mime signature"
116 "bad signed message 002" \
117 "Incriminating stuff. This is a test signed message." \
118 "(mml-secure-message-sign)"
120 file=$(notmuch search --output=files subject:"bad signed message 002")
122 awk '/-----BEGIN PGP SIGNATURE-----/{flag=1;print;next} \
123 /-----END PGP SIGNATURE-----/{flag=0;print;next} \
124 flag{gsub(/[A-Za-z]/,"0");print}!flag{print}' $file > $file.new
129 output=$(notmuch show --format=json --verify subject:"bad signed message 002" \
130 | notmuch_json_show_sanitize \
131 | sed -e 's|"created": [1234567890]*|"created": 946728000|')
132 expected='[[[{"id": "XXXXX",
136 "filename": ["YYYYY"],
137 "timestamp": 946728000,
138 "date_relative": "2000-01-01",
139 "tags": ["inbox","signed"],
140 "headers": {"Subject": "bad signed message 002",
141 "From": "Notmuch Test Suite <test_suite@notmuchmail.org>",
142 "To": "test_suite@notmuchmail.org",
143 "Date": "Sat, 01 Jan 2000 12:00:00 +0000"},
146 "content-type": "multipart/signed",
147 "content": [{"id": 2,
148 "content-type": "text/plain",
149 "content": "Incriminating stuff. This is a test signed message.\n"},
151 "content-type": "application/pgp-signature",
152 "content-length": "NONZERO"}]}]},
154 test_expect_equal_json \
158 test_begin_subtest "signature verification without full user ID validity"
159 # give the key no owner trust, removes validity on all user IDs of the
160 # certificate in the absence of other trusted certifiers:
161 gpg --quiet --batch --no-tty --export-ownertrust > "$GNUPGHOME/ownertrust.bak"
162 echo "${FINGERPRINT}:3:" | gpg --quiet --batch --no-tty --import-ownertrust
163 output=$(notmuch show --format=json --verify subject:"test signed message 001" \
164 | notmuch_json_show_sanitize \
165 | sed -e 's|"created": [1234567890]*|"created": 946728000|g')
166 expected='[[[{"id": "XXXXX",
169 "filename": ["YYYYY"],
170 "timestamp": 946728000,
171 "date_relative": "2000-01-01",
172 "tags": ["inbox","signed"],
173 "crypto": {"signed": {"status": [{ "status": "good", "created": 946728000, "fingerprint": "'$FINGERPRINT'"}]}},
174 "headers": {"Subject": "test signed message 001",
175 "From": "Notmuch Test Suite <test_suite@notmuchmail.org>",
176 "To": "test_suite@notmuchmail.org",
177 "Date": "Sat, 01 Jan 2000 12:00:00 +0000"},
179 "sigstatus": [{"status": "good",
180 "fingerprint": "'$FINGERPRINT'",
181 "created": 946728000}],
182 "content-type": "multipart/signed",
183 "content": [{"id": 2,
184 "content-type": "text/plain",
185 "content": "This is a test signed message.\n"},
187 "content-type": "application/pgp-signature",
188 "content-length": "NONZERO"}]}]},
190 test_expect_equal_json \
193 gpg --quiet --batch --no-tty --import-ownertrust < "$GNUPGHOME/ownertrust.bak"
195 test_begin_subtest "signature verification with signer key unavailable"
196 # move the gnupghome temporarily out of the way
197 mv "${GNUPGHOME}"{,.bak}
198 output=$(notmuch show --format=json --verify subject:"test signed message 001" \
199 | notmuch_json_show_sanitize \
200 | sed -e 's|"created": [1234567890]*|"created": 946728000|g')
201 expected='[[[{"id": "XXXXX",
204 "filename": ["YYYYY"],
205 "timestamp": 946728000,
206 "date_relative": "2000-01-01",
207 "tags": ["inbox","signed"],
208 "crypto": {"signed": {"status": [{"errors": {"key-missing": true}, "keyid": "'$(echo $FINGERPRINT | cut -c 25-)'", "status": "error"}]}},
209 "headers": {"Subject": "test signed message 001",
210 "From": "Notmuch Test Suite <test_suite@notmuchmail.org>",
211 "To": "test_suite@notmuchmail.org",
212 "Date": "Sat, 01 Jan 2000 12:00:00 +0000"},
214 "sigstatus": [{"status": "error",
215 "keyid": "'$(echo $FINGERPRINT | cut -c 25-)'",
216 "errors": {"key-missing": true}}],
217 "content-type": "multipart/signed",
218 "content": [{"id": 2,
219 "content-type": "text/plain",
220 "content": "This is a test signed message.\n"},
222 "content-type": "application/pgp-signature",
223 "content-length": "NONZERO"}]}]},
225 test_expect_equal_json \
228 mv "${GNUPGHOME}"{.bak,}
230 test_begin_subtest "emacs delivery of encrypted message with attachment"
231 # create a test encrypted message with attachment
232 cat <<EOF >TESTATTACHMENT
235 test_expect_success \
237 "test encrypted message 001" \
238 "This is a test encrypted message.\n" \
239 "(mml-attach-file \"TESTATTACHMENT\") (mml-secure-message-encrypt)"'
241 test_begin_subtest "encrypted part content-type indexing"
242 output=$(notmuch search mimetype:multipart/encrypted and mimetype:application/pgp-encrypted and mimetype:application/octet-stream | notmuch_search_sanitize)
243 test_expect_equal "$output" "thread:XXX 2000-01-01 [1/1] Notmuch Test Suite; test encrypted message 001 (encrypted inbox)"
245 test_begin_subtest "decryption, --format=text"
246 output=$(notmuch show --format=text --decrypt=true subject:"test encrypted message 001" \
247 | notmuch_show_sanitize_all \
248 | sed -e 's|"created": [1234567890]*|"created": 946728000|')
249 expected='
\fmessage{ id:XXXXX depth:0 match:1 excluded:0 filename:XXXXX
251 Notmuch Test Suite <test_suite@notmuchmail.org> (2000-01-01) (encrypted inbox)
252 Subject: test encrypted message 001
253 From: Notmuch Test Suite <test_suite@notmuchmail.org>
254 To: test_suite@notmuchmail.org
255 Date: Sat, 01 Jan 2000 12:00:00 +0000
258 \fpart{ ID: 1, Content-type: multipart/encrypted
259 \fpart{ ID: 2, Content-type: application/pgp-encrypted
260 Non-text part: application/pgp-encrypted
262 \fpart{ ID: 3, Content-type: multipart/mixed
263 \fpart{ ID: 4, Content-type: text/plain
264 This is a test encrypted message.
266 \fattachment{ ID: 5, Filename: TESTATTACHMENT, Content-type: application/octet-stream
267 Non-text part: application/octet-stream
277 test_begin_subtest "decryption, --format=json"
278 output=$(notmuch show --format=json --decrypt=true subject:"test encrypted message 001" \
279 | notmuch_json_show_sanitize \
280 | sed -e 's|"created": [1234567890]*|"created": 946728000|')
281 expected='[[[{"id": "XXXXX",
284 "filename": ["YYYYY"],
285 "timestamp": 946728000,
286 "date_relative": "2000-01-01",
287 "tags": ["encrypted","inbox"],
288 "crypto": {"decrypted": {"status": "full"}},
289 "headers": {"Subject": "test encrypted message 001",
290 "From": "Notmuch Test Suite <test_suite@notmuchmail.org>",
291 "To": "test_suite@notmuchmail.org",
292 "Date": "Sat, 01 Jan 2000 12:00:00 +0000"},
294 "encstatus": [{"status": "good"}],
295 "content-type": "multipart/encrypted",
296 "content": [{"id": 2,
297 "content-type": "application/pgp-encrypted",
298 "content-length": "NONZERO"},
300 "content-type": "multipart/mixed",
301 "content": [{"id": 4,
302 "content-type": "text/plain",
303 "content": "This is a test encrypted message.\n"},
305 "content-type": "application/octet-stream",
306 "content-disposition": "attachment",
307 "content-length": "NONZERO",
308 "content-transfer-encoding": "base64",
309 "filename": "TESTATTACHMENT"}]}]}]},
311 test_expect_equal_json \
315 test_begin_subtest "decryption, --format=json, --part=4"
316 output=$(notmuch show --format=json --part=4 --decrypt=true subject:"test encrypted message 001" \
317 | notmuch_json_show_sanitize \
318 | sed -e 's|"created": [1234567890]*|"created": 946728000|')
320 "content-type": "text/plain",
321 "content": "This is a test encrypted message.\n"}'
322 test_expect_equal_json \
326 test_begin_subtest "decrypt attachment (--part=5 --format=raw)"
331 subject:"test encrypted message 001" >OUTPUT
332 test_expect_equal_file TESTATTACHMENT OUTPUT
334 test_begin_subtest "decryption failure with missing key"
335 mv "${GNUPGHOME}"{,.bak}
336 output=$(notmuch show --format=json --decrypt=true subject:"test encrypted message 001" \
337 | notmuch_json_show_sanitize \
338 | sed -e 's|"created": [1234567890]*|"created": 946728000|')
339 expected='[[[{"id": "XXXXX",
343 "filename": ["YYYYY"],
344 "timestamp": 946728000,
345 "date_relative": "2000-01-01",
346 "tags": ["encrypted","inbox"],
347 "headers": {"Subject": "test encrypted message 001",
348 "From": "Notmuch Test Suite <test_suite@notmuchmail.org>",
349 "To": "test_suite@notmuchmail.org",
350 "Date": "Sat, 01 Jan 2000 12:00:00 +0000"},
352 "encstatus": [{"status": "bad"}],
353 "content-type": "multipart/encrypted",
354 "content": [{"id": 2,
355 "content-type": "application/pgp-encrypted",
356 "content-length": "NONZERO"},
358 "content-type": "application/octet-stream",
359 "content-length": "NONZERO"}]}]},
361 test_expect_equal_json \
364 mv "${GNUPGHOME}"{.bak,}
366 test_begin_subtest "emacs delivery of encrypted + signed message"
367 test_expect_success \
369 "test encrypted message 002" \
370 "This is another test encrypted message.\n" \
371 "(mml-secure-message-sign-encrypt)"'
373 test_begin_subtest "decryption + signature verification"
374 output=$(notmuch show --format=json --decrypt=true subject:"test encrypted message 002" \
375 | notmuch_json_show_sanitize \
376 | sed -e 's|"created": [1234567890]*|"created": 946728000|g')
377 expected='[[[{"id": "XXXXX",
380 "filename": ["YYYYY"],
381 "timestamp": 946728000,
382 "date_relative": "2000-01-01",
383 "tags": ["encrypted","inbox"],
384 "crypto": {"signed": {"status": [{ "status": "good", "created": 946728000, "fingerprint": "'$FINGERPRINT'", "email": "'"$SELF_EMAIL"'", "userid": "'"$SELF_USERID"'"}],
386 "decrypted": {"status": "full"}},
387 "headers": {"Subject": "test encrypted message 002",
388 "From": "Notmuch Test Suite <test_suite@notmuchmail.org>",
389 "To": "test_suite@notmuchmail.org",
390 "Date": "Sat, 01 Jan 2000 12:00:00 +0000"},
392 "encstatus": [{"status": "good"}],
393 "sigstatus": [{"status": "good",
394 "fingerprint": "'$FINGERPRINT'",
395 "created": 946728000,
396 "email": "'"$SELF_EMAIL"'",
397 "userid": "'"$SELF_USERID"'"}],
398 "content-type": "multipart/encrypted",
399 "content": [{"id": 2,
400 "content-type": "application/pgp-encrypted",
401 "content-length": "NONZERO"},
403 "content-type": "text/plain",
404 "content": "This is another test encrypted message.\n"}]}]},
406 test_expect_equal_json \
410 test_begin_subtest "reply to encrypted message"
411 output=$(notmuch reply --decrypt=true subject:"test encrypted message 002" \
412 | notmuch_drop_mail_headers In-Reply-To References)
413 expected='From: Notmuch Test Suite <test_suite@notmuchmail.org>
414 Subject: Re: test encrypted message 002
415 To: test_suite@notmuchmail.org
417 On 01 Jan 2000 12:00:00 -0000, Notmuch Test Suite <test_suite@notmuchmail.org> wrote:
418 > This is another test encrypted message.'
423 test_begin_subtest "Reply within emacs to an encrypted message"
424 test_emacs "(let ((message-hidden-headers '())
425 (notmuch-crypto-process-mime 't))
426 (notmuch-show \"subject:test.encrypted.message.002\")
429 grep -v -e '^In-Reply-To:' -e '^References:' -e '^Fcc:' < OUTPUT > OUTPUT.clean
431 From: Notmuch Test Suite <test_suite@notmuchmail.org>
432 To: test_suite@notmuchmail.org
433 Subject: Re: test encrypted message 002
434 --text follows this line--
435 <#secure method=pgpmime mode=signencrypt>
436 Notmuch Test Suite <test_suite@notmuchmail.org> writes:
438 > This is another test encrypted message.
440 test_expect_equal_file EXPECTED OUTPUT.clean
442 test_begin_subtest "signature verification with revoked key"
443 # generate revocation certificate and load it to revoke key
446 Notmuch Test Suite key revocation (automated) $(date '+%F_%T%z')
451 | gpg --no-tty --quiet --command-fd 0 --armor --gen-revoke "0x${FINGERPRINT}!" 2>/dev/null \
452 | gpg --no-tty --quiet --import
453 output=$(notmuch show --format=json --verify subject:"test signed message 001" \
454 | notmuch_json_show_sanitize \
455 | sed -e 's|"created": [1234567890]*|"created": 946728000|')
456 expected='[[[{"id": "XXXXX",
459 "filename": ["YYYYY"],
460 "timestamp": 946728000,
461 "date_relative": "2000-01-01",
462 "tags": ["inbox","signed"],
463 "crypto": {"signed": {"status": [{"errors": {"key-revoked": true}, "keyid": "'$(echo $FINGERPRINT | cut -c 25-)'", "status": "error"}]}},
464 "headers": {"Subject": "test signed message 001",
465 "From": "Notmuch Test Suite <test_suite@notmuchmail.org>",
466 "To": "test_suite@notmuchmail.org",
467 "Date": "Sat, 01 Jan 2000 12:00:00 +0000"},
469 "sigstatus": [{"status": "error",
470 "keyid": "6D92612D94E46381",
471 "errors": {"key-revoked": true}}],
472 "content-type": "multipart/signed",
473 "content": [{"id": 2,
474 "content-type": "text/plain",
475 "content": "This is a test signed message.\n"},
477 "content-type": "application/pgp-signature",
478 "content-length": "NONZERO"}]}]},
480 test_expect_equal_json \