summaryrefslogtreecommitdiff
path: root/tests/corpus
diff options
context:
space:
mode:
Diffstat (limited to 'tests/corpus')
-rw-r--r--tests/corpus/OpenPGP/.gitignore1
-rw-r--r--tests/corpus/OpenPGP/README.md4
-rwxr-xr-xtests/corpus/OpenPGP/genkeys31
-rwxr-xr-xtests/corpus/OpenPGP/gnupg-import27
-rw-r--r--tests/corpus/OpenPGP/julia.key59
-rw-r--r--tests/corpus/OpenPGP/julia.pgp30
-rw-r--r--tests/corpus/OpenPGP/obrian.key59
-rw-r--r--tests/corpus/OpenPGP/obrian.pgp30
-rw-r--r--tests/corpus/OpenPGP/winston.key59
-rw-r--r--tests/corpus/OpenPGP/winston.pgp30
-rw-r--r--tests/corpus/expected.A.eml69
-rw-r--r--tests/corpus/sample.A.eml32
12 files changed, 431 insertions, 0 deletions
diff --git a/tests/corpus/OpenPGP/.gitignore b/tests/corpus/OpenPGP/.gitignore
new file mode 100644
index 0000000..03f357b
--- /dev/null
+++ b/tests/corpus/OpenPGP/.gitignore
@@ -0,0 +1 @@
+GNUPGHOME
diff --git a/tests/corpus/OpenPGP/README.md b/tests/corpus/OpenPGP/README.md
new file mode 100644
index 0000000..037d893
--- /dev/null
+++ b/tests/corpus/OpenPGP/README.md
@@ -0,0 +1,4 @@
+This directory contains OpenPGP public and private key material that
+can be used to interpret messages from this corpus.
+
+See the genkey script for how they were generated.
diff --git a/tests/corpus/OpenPGP/genkeys b/tests/corpus/OpenPGP/genkeys
new file mode 100755
index 0000000..d5e74b8
--- /dev/null
+++ b/tests/corpus/OpenPGP/genkeys
@@ -0,0 +1,31 @@
+#!/bin/bash
+
+# Daniel Kahn Gillmor <dkg@fifthhorseman.net>
+# 2015-07-15
+
+# How to generate the keys used for the creation of the message
+# corpus.
+
+export WORKDIR=$(mktemp -d)
+export GNUPGHOME="$WORKDIR"
+
+cat >"${WORKDIR}/gpg-agent.conf"<<EOF
+allow-loopback-pinentry
+no-allow-external-cache
+EOF
+cleanup() {
+ gpgconf --kill gpg-agent
+ rm -rf "$WORKDIR"
+}
+
+trap cleanup EXIT
+
+gpg2 --batch --pinentry-mode=loopback --passphrase=_winston_ --quick-gen-key 'Winston <winston@example.net>'
+gpg2 --batch --pinentry-mode=loopback --passphrase=_julia_ --quick-gen-key 'Julia <julia@example.org>'
+gpg2 --batch --pinentry-mode=loopback --passphrase=_obrian_ --quick-gen-key "O'Brian <obrian@example.com>"
+
+for x in winston julia obrian; do
+ gpg2 --armor --batch --pinentry-mode=loopback --passphrase=_${x}_ --output $x.key --export-secret-key $x
+ gpg2 --armor --batch --output $x.pgp --export $x
+done
+
diff --git a/tests/corpus/OpenPGP/gnupg-import b/tests/corpus/OpenPGP/gnupg-import
new file mode 100755
index 0000000..a92bce2
--- /dev/null
+++ b/tests/corpus/OpenPGP/gnupg-import
@@ -0,0 +1,27 @@
+#!/bin/bash
+
+mkdir -p -m 0700 GNUPGHOME
+export GNUPGHOME=$(pwd)/GNUPGHOME
+
+cat >GNUPGHOME/gpg-agent.conf <<EOF
+allow-loopback-pinentry
+no-allow-external-cache
+EOF
+
+for x in winston obrian julia; do
+ <$x.key gpg2 --batch --pinentry-mode=loopback --passphrase=_${x}_ --import
+done
+
+# mark all keys with ultimate ownertrust. This is a silly hack, but
+# it's due to the fact that this corpus hasn't really decided whether
+# the GnuPG homedir is supposed to represent one particular user's
+# config (in which case we should just import one secret key, mark it
+# with ultimate ownertrust and have it sign the others) or just
+# pragmatically handle all the secret keys in a single homedir. For
+# now, we're opting for the latter.
+
+gpg2 --import-ownertrust <<EOF
+5A7AD43844FB30BE7DB1B3FD15FB4EBC8E2D6CB7:6
+9A9CC2E1546C7A04D23048641BC98889B8EA08B3:6
+2BC85B8EF240B7422E9C19F2E0D7563140A09310:6
+EOF
diff --git a/tests/corpus/OpenPGP/julia.key b/tests/corpus/OpenPGP/julia.key
new file mode 100644
index 0000000..e2c558e
--- /dev/null
+++ b/tests/corpus/OpenPGP/julia.key
@@ -0,0 +1,59 @@
+-----BEGIN PGP PRIVATE KEY BLOCK-----
+Version: GnuPG v2
+
+lQPGBFWmZK8BCAC+iejpS2pWGQT3I9diXAMO5j+MvSRRJCJ8r/aFwKFoSO3FwDEn
+hKT7T5Fj1S/NEahAJgjw3pghNpA/C/CVSy9+lCUDjpRDyYX+18bXrc5DsGD3OHNt
+95QLyyOsed/nGbVvpPvwl/TMMjzEw+NVtjb84F2n52YfcGhXoEzweWozSuBvyjBZ
+/8vWREytW/J3SBQTGfC/dPfoN8PrA1SkpCkE7bOAVEibcWK5gs7BHsxNxLXLF8EX
+Yy0F+XIJIC0bRCJk7akJRhu+dCsVFOOldSKg+RVl65ntSxTx8f/iJGAAAOqu5Ozj
+B3tM0Yd88msUcPmW/hLaJmT888v89+Pj7YplABEBAAH+BwMCNWGV3PrQ41LQULol
+fuPlmH3P7bWhZexAxFkx7CwQp8PpbyQf45xvTkCu6nJI5qW0+DYmHi84Cd7u4Txm
+Rb2bnvO/pujZYn7g4MJW3CWEy4IhrJy9/COjoze2M3eEUyX/o6AYZNWEykGyfdSY
+GDStHVIhJcwU5c5yCPPtCttFQQCa9ZlY6kSdKX63cekyH22ZrUlolSQD66VuDsWb
+NB44+2cd/Ysi74WqI3/7Sn3NH5o8czjfaxQkdV6WYy1l6GxlN7IjMD66kWSfUX4l
+7cBzF1+Gszrg837tEDR8ZuVi5x3oA9G6X7bnUpjSG8Lz1MNv0voV4CuTbIeOiMZn
+78wOjSiMyevQ5l0Zv8T165bI62E3nznEKPbwOg2VMI0hsclrAu2THrUR3+iZZJHR
+BACGeZveMWoqd+Q45i0s4w08CVUhO3d0wDmMjSDC6ysEpibAowDrlzB0uvNxrTNW
+z/b522G/pAMK/83zwMZpFqw2gFGTKR+0xGi2tyBFEwGoWbT+6nFFYRHCYjLckoDT
+jditX1ISKt6fLrVS8AL8NxE/zv84DMGvU2DiOHUgjdheEaxvoU4WSNrjGbRySHPU
+KLeyqTT5GUQU+S1LWO/bbEZZXkpmRvUN/TaS8mQoMuM/SukMzkupInxLb4Gpk1Y6
+UT6yFxh9Ah1J/YKORWiq8OcdwDpYT2Ab0Xbru3g5zIKr62bPdCqXa93MtOs2/Qhb
+oOx6mVj0I/TVuARD5uYu6cJKviq3ZmDNj3obnMdBIlHigQUmiSeT2ZPrnwr7HDJR
+NqvDyDHGIOXgdXT59DoaiXzxrx5kTn95V3QXI39eUPDdnLptOX7BeeG+/YV5A5yy
+ItzZvZmRl70ugzG7rBTqxRo2Fr2rGmWUuBG+cgBrmakRnnka99JJzPTFLNbdgI2b
+SNzDGlSU/8jjtBlKdWxpYSA8anVsaWFAZXhhbXBsZS5vcmc+iQE3BBMBCAAhBQJV
+pmSvAhsDBQsJCAcCBhUICQoLAgQWAgMBAh4BAheAAAoJEODXVjFAoJMQ+N4IAJzx
+XBl7+j2fdVOpfviknXQYNk8kN2Va8rP6R+JpIMOyldexhPZ9HHerdTtzfbmrWaCl
++ytjvffJXDC6PDV/1wWcVvN291w8Lp2mDp3EH9vVtiHlCWCEfTkWG9d7GOXXZREe
+lFQfZaHh3DMD0DEY2c2Z8ztdPvbQd2cTUadroxALAyPJcwtvYu/ZItSbEtUw/UaR
+LL5BS/CEI6NKSC6A2JWJQRdYRHefnJuOqxGXQuaUZljGmQgMi6225lSRdRZLx36l
+oYh7+2UcIVoAcoAVV876tNUEdqT39lUxyBBNcGAY+WJK3TDn79osjOINMeD9YuqB
+H9+GzoKtAaMuvCvbhS6dA8YEVaZkrwEIAKWDa0H04mb5wnbwGoRNABfUAcIUzR1c
+XCIk/FcXsqt70xz7oFw9yisgZgIX2NyWtxCTIDzAaGtPADGCjaNgTgl6nSrJxljY
+RKGycNUkSS/axnAp7f1lOmUvQkdf1IXuUxSP5rEMxwVbXCdGiPxIJcfecsqxwao8
+NlkSvR5A4rvJx1ihrE+bmYPL559uUmEr+zD06dr2rWNpuDXG2/fPwEXlNvrmCFoQ
+i5nhAEoKvUii9s/pWj5yeb0yNnPW3lYSXD08iItyZvnFydxoPdm19lTFdr+Rvluj
+H2Ve99UalgNxA6iZ7d5n1VKdrEoq7JHEq2EZ9454XFBPHx2mkS1ZX2MAEQEAAf4H
+AwLh8ZP+jrKostBh0kYuEkGjajwJZS32eTGUXVErWqP/7NnfHfDrAApHBBcl1bIW
+WhZQOfwL5uhszCvVJgBUPn76VZJ5L/wkJMF/koCg63WOWXyxX0Qn7oXDCKeU57b8
+1SKFjbkJg1xXr2Y0MJsbtUfD/JgYvO/dE60rWlMrFogQIF5Iih3lk2RxtGD4diJJ
+S4IoewrygGrt8dzpoboSPsY741FYheNKrPiBAS5HB/orrSDI8tDuBbzBVHppF76n
+NitYlI8DZBPzOk6/uQZM9ajQ/WRPrBRdgW7h3qGEdUF9TdHrDng0eHiJB9XO9KYy
+fnvhGCQ8VOrscMGJuvtRw7M4Pa1ZuR4n3tfXd7qtnBulqUMjW2HpXnmneaN8UrAd
+PBAxB5TRP3LD83HqvSVjTUYrviUBY9ip4NU3w3kWNBweF1PiJKEzpYKrqStt1IC9
+uQtm7sS5BsBX6LqnlZOku1C36cs1VocarTnZIrMz2lZVe2ps6K2xlrhndT8DA5Y6
+8U+GoS0zsJW3ie/l+W3iNsGzH8++MnEi0AvU8R3VqlJ8xMsF/RPiSqxwU6hk1Doo
+kO7m5cGJOvP8mMoyej3xHvIjjOpqeunIxRY5zLt3kVjpokLgNIFIr4WenCWkb+pb
+l/7mb97zm6c888Ijs+W7+GwpprtVuM+qRjEtRtS+laYMJwf0ZwyoGwOZZt4HUdnd
+H7KvxT2V5veM/l37iTYGorFJ2RmydvytXPF2MwmKQPPofzOOYb/jMF52vbYxHcV+
+PgHxvFz67JPMis7JPk1IkUQdyg7WhiMQqro1WkkIKC/NAL7Vk8uel3yugJtU5l9T
+GqBoNWchLQNX1YbDdD1GzHNa7rsXVUkyOegHzl+YOGBXw5tZMcuB1EZL2xCXktqk
+Fk7f99iG1hkECIxg3QYrQVKFB4YEoF2JAR8EGAEIAAkFAlWmZK8CGwwACgkQ4NdW
+MUCgkxBiVQf9F4AJJ17cU+lJQGWlHizxi/mPdoMWXUva6x/XOcDGzVebW3xnXv91
+jFfZTW0ePDRB4XRCl5BL6ttWTPgdmbWl9utkp6s7jrnO9HbiCYqMUUvPTR3W9+nM
+TCCHQZzsop1Z/fyOeMgJ17nyCowSyXQq3o7B8uxg8iaHyA229wupNWDva1i9zBn9
+Z3hsP/G5aTRJKlPJ7ZuBHLqT6D+Hw+/ikTvbGsDlWw6dKiPHOb2OgKjnf4CG34FI
+M78diy/mYK7hS1eU67972nZEOCNJshoPDx6gUKj+Nl4NfPh9euBlWVkE3YHQTFCt
+aDjtAVjGPvw5WbpSXHH3YM7eK3LJPKsAvQ==
+=sfSJ
+-----END PGP PRIVATE KEY BLOCK-----
diff --git a/tests/corpus/OpenPGP/julia.pgp b/tests/corpus/OpenPGP/julia.pgp
new file mode 100644
index 0000000..c3bf3c2
--- /dev/null
+++ b/tests/corpus/OpenPGP/julia.pgp
@@ -0,0 +1,30 @@
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: GnuPG v2
+
+mQENBFWmZK8BCAC+iejpS2pWGQT3I9diXAMO5j+MvSRRJCJ8r/aFwKFoSO3FwDEn
+hKT7T5Fj1S/NEahAJgjw3pghNpA/C/CVSy9+lCUDjpRDyYX+18bXrc5DsGD3OHNt
+95QLyyOsed/nGbVvpPvwl/TMMjzEw+NVtjb84F2n52YfcGhXoEzweWozSuBvyjBZ
+/8vWREytW/J3SBQTGfC/dPfoN8PrA1SkpCkE7bOAVEibcWK5gs7BHsxNxLXLF8EX
+Yy0F+XIJIC0bRCJk7akJRhu+dCsVFOOldSKg+RVl65ntSxTx8f/iJGAAAOqu5Ozj
+B3tM0Yd88msUcPmW/hLaJmT888v89+Pj7YplABEBAAG0GUp1bGlhIDxqdWxpYUBl
+eGFtcGxlLm9yZz6JATcEEwEIACEFAlWmZK8CGwMFCwkIBwIGFQgJCgsCBBYCAwEC
+HgECF4AACgkQ4NdWMUCgkxD43ggAnPFcGXv6PZ91U6l++KSddBg2TyQ3ZVrys/pH
+4mkgw7KV17GE9n0cd6t1O3N9uatZoKX7K2O998lcMLo8NX/XBZxW83b3XDwunaYO
+ncQf29W2IeUJYIR9ORYb13sY5ddlER6UVB9loeHcMwPQMRjZzZnzO10+9tB3ZxNR
+p2ujEAsDI8lzC29i79ki1JsS1TD9RpEsvkFL8IQjo0pILoDYlYlBF1hEd5+cm46r
+EZdC5pRmWMaZCAyLrbbmVJF1FkvHfqWhiHv7ZRwhWgBygBVXzvq01QR2pPf2VTHI
+EE1wYBj5YkrdMOfv2iyM4g0x4P1i6oEf34bOgq0Boy68K9uFLrkBDQRVpmSvAQgA
+pYNrQfTiZvnCdvAahE0AF9QBwhTNHVxcIiT8Vxeyq3vTHPugXD3KKyBmAhfY3Ja3
+EJMgPMBoa08AMYKNo2BOCXqdKsnGWNhEobJw1SRJL9rGcCnt/WU6ZS9CR1/Uhe5T
+FI/msQzHBVtcJ0aI/Eglx95yyrHBqjw2WRK9HkDiu8nHWKGsT5uZg8vnn25SYSv7
+MPTp2vatY2m4Ncbb98/AReU2+uYIWhCLmeEASgq9SKL2z+laPnJ5vTI2c9beVhJc
+PTyIi3Jm+cXJ3Gg92bX2VMV2v5G+W6MfZV731RqWA3EDqJnt3mfVUp2sSirskcSr
+YRn3jnhcUE8fHaaRLVlfYwARAQABiQEfBBgBCAAJBQJVpmSvAhsMAAoJEODXVjFA
+oJMQYlUH/ReACSde3FPpSUBlpR4s8Yv5j3aDFl1L2usf1znAxs1Xm1t8Z17/dYxX
+2U1tHjw0QeF0QpeQS+rbVkz4HZm1pfbrZKerO465zvR24gmKjFFLz00d1vfpzEwg
+h0Gc7KKdWf38jnjICde58gqMEsl0Kt6OwfLsYPImh8gNtvcLqTVg72tYvcwZ/Wd4
+bD/xuWk0SSpTye2bgRy6k+g/h8Pv4pE72xrA5VsOnSojxzm9joCo53+Aht+BSDO/
+HYsv5mCu4UtXlOu/e9p2RDgjSbIaDw8eoFCo/jZeDXz4fXrgZVlZBN2B0ExQrWg4
+7QFYxj78OVm6Ulxx92DO3ityyTyrAL0=
+=8jVN
+-----END PGP PUBLIC KEY BLOCK-----
diff --git a/tests/corpus/OpenPGP/obrian.key b/tests/corpus/OpenPGP/obrian.key
new file mode 100644
index 0000000..37bd877
--- /dev/null
+++ b/tests/corpus/OpenPGP/obrian.key
@@ -0,0 +1,59 @@
+-----BEGIN PGP PRIVATE KEY BLOCK-----
+Version: GnuPG v2
+
+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
+MuCm/QNgbu+E4rf3zmvTHhjAXyxT6kfXCwxdbA==
+=WTVE
+-----END PGP PRIVATE KEY BLOCK-----
diff --git a/tests/corpus/OpenPGP/obrian.pgp b/tests/corpus/OpenPGP/obrian.pgp
new file mode 100644
index 0000000..0751fc6
--- /dev/null
+++ b/tests/corpus/OpenPGP/obrian.pgp
@@ -0,0 +1,30 @@
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: GnuPG v2
+
+mQENBFWmZLABCADTWhsDvyR2bWT/edmFt5vOiBVGT3lR5BnxdP8j6rlWLZ+T+FZZ
+JeUzuV87zaGvjlj2Sl11X61qh963WxyUJGg1GjIRg1mT1n9o0FPmTAet2iQr2PFv
+GSdwFgPg9XvK+O99ij3+oAGTkjXtXuy+y/rrD9k4E1k63q0uHBpiTJ428mab9+Jo
+cQEcwzPwfU7yTtYb1oQChuNto0eeQajeNc9oFcklZ1FLDKfedPiYtXJuSzo1PeDz
+ViYDX1qY/CmTKZjhIjYxBEsa5DRdHsRNqMDojxi4eUORIGBAcDF1Jrz6wWrFa3Vs
+K7J88aGX3y4BMA9HL+aMyl4mauwLm5YByBNpABEBAAG0HE8nQnJpYW4gPG9icmlh
+bkBleGFtcGxlLmNvbT6JATcEEwEIACEFAlWmZLACGwMFCwkIBwIGFQgJCgsCBBYC
+AwECHgECF4AACgkQG8mIibjqCLMX0wgAhPWPL7fRW4ZoLhSYeBMtiyZGZ3TR1TXG
+UOa8OZw387cRPOOkdf7SbhfjqEVfyOyH56L10y+uu5GwoU0E+iNDH5qy63YJRisd
+27IiK9TPwYVn7E1eOHgtnSiCniUKjfa0EJV+8gZMmCQdjE1lwPPLmwKxqWN21kiS
+JcWcYz3E7ctDiHzlmmpWna9BQAAbqJYnbMWF9YmtdQ4jlkRI8o6PiSh5IZ+dn81b
+5GNqXm8WYhvIQrYiCmQRsc4fC+B/mfMjFQiYjN/jLuWmJg1WJ/w3k6KNy8ocmMQV
+KOFGbGEtCrw2wUmar7qlEVj7bvmH7+uCE6VRDAJ4SmTgAzQP8f+bObkBDQRVpmSw
+AQgAn1e3f3xHlPUXvC4LQzCu5YnWDK13DVhobuHz5rymQJX8gWhvp8HUOYUtAGXc
+4lhctJzVViZLUsLl8ixcgUCC78lZnAcNE1jQ65MB4wBCSD3V2Jmw7aPLFZtO0lqL
+z40Y1FhOgcQd+AdUEqVCu1T/Hbu/+Pjkh4ZE9DXkogsgD1OCRL1QaegvnMjxACyS
+z8bw+8rCg1stGbTQ/hydNajCySpc33Sb/6Bt0rw+tY8wZVCwfT6h1nEmTAE3UG00
+KjFOY+Xy69MM7QMYZ3+m/Ujad51vG28GXvGPy8hUzfQJn4ih8+q8p9GfCX7TYZe7
+Rv+rNG7SVcBs+velGPou4QIUHwARAQABiQEfBBgBCAAJBQJVpmSwAhsMAAoJEBvJ
+iIm46gizncYIAITjPmeFbNl+odoYEqtR46o1wxmlElYDWNohgNzLiPOK1QHGnDOF
+hLwBMtInbcP7uU0AIg1ov+wwZiMKQz+cebBA5CeUu/pQHA1ftkjX/myNJ5kTxVvw
+dh6LtH4wQO9nAm8/o1+WX0qZuWAGzZgiRZTeZlQHqjjbrA/TKt5+36ZQfOznCr5+
+DznMNcvS3oD/FPJd7conhBHSmhHJ2Fx4+c9lp+GbB7N4BxCbsIgl4g2yZwdFa6i6
+yxy/smHxDyz3lZvdN3Ls0BjFifI/uQMWdKjBI3W5iUlhRqOr5oWVWfsnevYcuDLg
+pv0DYG7vhOK3985r0x4YwF8sU+pH1wsMXWw=
+=05aR
+-----END PGP PUBLIC KEY BLOCK-----
diff --git a/tests/corpus/OpenPGP/winston.key b/tests/corpus/OpenPGP/winston.key
new file mode 100644
index 0000000..8a29764
--- /dev/null
+++ b/tests/corpus/OpenPGP/winston.key
@@ -0,0 +1,59 @@
+-----BEGIN PGP PRIVATE KEY BLOCK-----
+Version: GnuPG v2
+
+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
+uWPeDAsLSS+VXRtnvjQBPQk2D3N+eCqBX+XMog==
+=qHx1
+-----END PGP PRIVATE KEY BLOCK-----
diff --git a/tests/corpus/OpenPGP/winston.pgp b/tests/corpus/OpenPGP/winston.pgp
new file mode 100644
index 0000000..b008d61
--- /dev/null
+++ b/tests/corpus/OpenPGP/winston.pgp
@@ -0,0 +1,30 @@
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: GnuPG v2
+
+mQENBFWmZKwBCACc1JThxcPtPcS9K33SnyzKsDjqo1G5pL3hyxlB/Y/lHBESIcoH
+KtTm8H/tSxHCpBWn+NK84cFDw1bw+lCRx8xjocdBBg7R0IUcUePBu7GD602mNRSn
+lTbvOaeaJxjeO9pckd/Ag2Np3hRktXmVZqISeiqeFGvqlTNgLnSngHzRl4hfmdyb
++cqMT3w3rSCH4/Nb0o+qEm7OeRk2NmqQnkDCPBGPwDLZDLGyMPruo4DbNjylJ4+e
+2/Oaq/iIK1VXU5CzFarC5UHTOMCK9ymsnL3QSJj8fmTjptZlEvmqs0FN396unuEO
+hQrmokJJl6Ro9PBifsvhllkQIhCwdgXlujIzABEBAAG0HVdpbnN0b24gPHdpbnN0
+b25AZXhhbXBsZS5uZXQ+iQE3BBMBCAAhBQJVpmSsAhsDBQsJCAcCBhUICQoLAgQW
+AgMBAh4BAheAAAoJEBX7TryOLWy3rYQH/j4cv+OTjrJeQepupq2tTgtMepdWmr7v
+RW/1VJw6PKk77WLWvnBmLnpDKS/ageEkv5pjsTSB9RqoUmTj6n5MZArIVid1B3q6
+qQ9hwdC1kIGuTYZd+/nEulsxu+r8xTOwcnfKCTVPuP4X8h29dFwEOg8WQ0WNgiFG
+o6Sgogtx3rNApGMWRItUkNGQmKvHzG5XiGkRwfBWPKsUwN91Onnx4kdD1lzWvwRl
+bWkyBKgrD79tZeRyB87Ns6LZ+C3MOZ3ucfL9/UbKf1Mvzsg8hc9//v2i/zhP9ArY
+XefGtUu9N03NvGWQYbLIDb7ZihLpswCGanxUUbHQMOYz/g1uI862Q2W5AQ0EVaZk
+rAEIAMEzK5hvFn7lxQtkVZ1xoJ0KIb8UwgpRMAqRTzlfjn72NmdVDaHfuWD5Xn1Q
+cQcV1/yypkwfkHbo1jbJFaChZmAFaQ2inutqzakDLRMpJJc/uILaIiojskoILZtp
+wGNlEvtvZrJzuduV8+TH/NKRXP8mG24lIfXQFGRRs+/XNjoyjyINPnsHG9EGHJlB
+oZx9tiMlLJQwC1fJITUoM5m7OYEv7bpTYc2FmIXyAwk8tNKiRfd3M2BWAnwfCF/V
+maBewmMLHU5YRfRCD1x3R28RQcwyBUSaN5+va0YY0WdBHgTt4zJd/hnT+N001rsp
++VfVDT10GDM4DcNNEPv58xLmTKcAEQEAAYkBHwQYAQgACQUCVaZkrAIbDAAKCRAV
++068ji1stxKzB/4iRi/oQ43mvZoG0IODJSqa8nOQJtaaKG3ekHg07kaC/FAjPeTg
+bxiqcMiKKGOkgQYHhxnZBob8ykr4fwuxpskUJQ2iiEp4+lhBU/Y5zbktZA9761mC
+hUM6EFPGvcmeyG+cRBPcc+GJL1yKLXZwhN1gY/BTeieKgAzDFpsChm+MPaPoJ98e
+nLQpy/f3yi4evayWRfnSQR9EMkt5C/1umhzutOlzjSaigyd0eT3j2SD5LGkEe8GX
+Iwj1QtsI8Cj88olUbpcZfVIAx5Ee7Hin/jtvjac9uvmv6zJ/YNg+cc29EsYYYLi5
+Y94MCwtJL5VdG2e+NAE9CTYPc354KoFf5cyi
+=Wk6a
+-----END PGP PUBLIC KEY BLOCK-----
diff --git a/tests/corpus/expected.A.eml b/tests/corpus/expected.A.eml
new file mode 100644
index 0000000..437f3db
--- /dev/null
+++ b/tests/corpus/expected.A.eml
@@ -0,0 +1,69 @@
+Content-Type: multipart/signed; protocol="application/pgp-signature";
+ micalg="pgp-sha256"; boundary="cccccccccccc"
+MIME-Version: 1.0
+Date: Thu, 16 Jul 2015 11:44:44 +0200
+Subject: alternative text/html message with embedded header, signed
+Message-ID: A@memoryhole.example
+To: Julia <julia@example.org>
+From: Winston <winston@example.net>
+
+--cccccccccccc
+Content-Type: multipart/mixed; boundary="bbbbbbbbbbbb"
+
+--bbbbbbbbbbbb
+Content-Type: text/rfc822-headers
+Content-Disposition: attachment
+
+Date: Thu, 16 Jul 2015 11:44:44 +0200
+Subject: alternative text/html message with embedded header, signed
+Message-ID: A@memoryhole.example
+To: Julia <julia@example.org>
+From: Winston <winston@example.net>
+
+--bbbbbbbbbbbb
+Content-Type: multipart/alternative; boundary="aaaaaaaaaaaa"
+
+--aaaaaaaaaaaa
+Content-Type: text/plain
+
+This is a test
+message on multiple lines
+
+with a silly bit more.
+--
+and a .sig here.
+
+--aaaaaaaaaaaa
+Content-Type: text/html
+
+<html>
+<head>
+<title>titles are usually unrendered</title>
+</head>
+<body>
+<p>This is a test<br/>message on multiple lines</p>
+<p>with a silly bit more.</p>
+<hr/>
+<p>and a .sig here.</p>
+</body>
+</html>
+--aaaaaaaaaaaa--
+
+--bbbbbbbbbbbb--
+
+--cccccccccccc
+Content-Type: application/pgp-signature; name="signature.asc"
+
+-----BEGIN PGP SIGNATURE-----
+
+iQEcBAABCAAGBQJWAiCsAAoJEBX7TryOLWy3JpEH/Ao8INvddDi7OJhsXWlLAHiu
+GaDS/xSXvsXgVe3IstKQLeepwvjkrismFNxQ7+5uBJxVXr+TgQgG8KAXZM7VYl+D
+rBnZYTlLnepSeeqeS3gcB9EWNABopCuDjEdCDO+CHudR4vFaN8wlqafxMdKqR74z
+i+49RXUXlBJMJJNNKrzJyatltRRyGBM0sqUIt6ZqrhwT5DwJZFbMBLx23X9heFFi
+7oLGSrAzlSfVr8KM5DoniAyNXSNWtVjj1hl8xCVJtIfsOcvpwCVR15vzfuH623og
+0Ag7G0GyKb1yNKlIZeUvJ7uo4Tm2+gUikn7Pk1eGqAEC5R7Ip1u8bkEtgdftinw=
+=OeWg
+-----END PGP SIGNATURE-----
+
+--cccccccccccc--
+
diff --git a/tests/corpus/sample.A.eml b/tests/corpus/sample.A.eml
new file mode 100644
index 0000000..cf67839
--- /dev/null
+++ b/tests/corpus/sample.A.eml
@@ -0,0 +1,32 @@
+Subject: alternative text/html message with embedded header, signed
+Message-ID: A@memoryhole.example
+Date: Thu, 16 Jul 2015 11:44:44 +0200
+To: Julia <julia@example.org>
+From: Winston <winston@example.net>
+MIME-Version: 1.0
+Content-Type: multipart/alternative; boundary="aaaaaaaaaaaa"
+
+--aaaaaaaaaaaa
+Content-Type: text/plain
+
+This is a test
+message on multiple lines
+
+with a silly bit more.
+--
+and a .sig here.
+
+--aaaaaaaaaaaa
+Content-Type: text/html
+
+<html>
+<head>
+<title>titles are usually unrendered</title>
+</head>
+<body>
+<p>This is a test<br/>message on multiple lines</p>
+<p>with a silly bit more.</p>
+<hr/>
+<p>and a .sig here.</p>
+</body>
+</html>