diff options
author | Clint Adams <clint@softwarefreedom.org> | 2012-04-26 16:29:50 -0400 |
---|---|---|
committer | Clint Adams <clint@softwarefreedom.org> | 2012-04-26 16:29:50 -0400 |
commit | 716dd382221343e5da5daf1a9a8ac40304a7d74b (patch) | |
tree | 0a2b7bed56f9ec6564d4a9e918ab4e8fd53c0dc5 | |
parent | d17ea2bb11255f7e6ae9069d3b58e8f06d5946a5 (diff) |
Codec for "Cleartext Signatures"
-rw-r--r-- | Codec/Encryption/OpenPGP/ASCIIArmor/Decode.hs | 32 | ||||
-rw-r--r-- | Codec/Encryption/OpenPGP/ASCIIArmor/Encode.hs | 10 | ||||
-rw-r--r-- | Codec/Encryption/OpenPGP/ASCIIArmor/Types.hs | 2 | ||||
-rw-r--r-- | Codec/Encryption/OpenPGP/ASCIIArmor/Utils.hs | 17 | ||||
-rw-r--r-- | openpgp-asciiarmor.cabal | 9 | ||||
-rw-r--r-- | tests/data/msg3 | 9 | ||||
-rw-r--r-- | tests/data/msg3.asc | 29 | ||||
-rw-r--r-- | tests/data/msg3.sig | bin | 0 -> 543 bytes | |||
-rw-r--r-- | tests/data/msg4 | 1 | ||||
-rw-r--r-- | tests/data/msg4.asc | 17 | ||||
-rw-r--r-- | tests/data/msg4.sig | bin | 0 -> 543 bytes | |||
-rw-r--r-- | tests/suite.hs | 35 |
12 files changed, 154 insertions, 7 deletions
diff --git a/Codec/Encryption/OpenPGP/ASCIIArmor/Decode.hs b/Codec/Encryption/OpenPGP/ASCIIArmor/Decode.hs index 0376abc..b0033a8 100644 --- a/Codec/Encryption/OpenPGP/ASCIIArmor/Decode.hs +++ b/Codec/Encryption/OpenPGP/ASCIIArmor/Decode.hs | |||
@@ -10,7 +10,8 @@ module Codec.Encryption.OpenPGP.ASCIIArmor.Decode ( | |||
10 | ) where | 10 | ) where |
11 | 11 | ||
12 | import Codec.Encryption.OpenPGP.ASCIIArmor.Types | 12 | import Codec.Encryption.OpenPGP.ASCIIArmor.Types |
13 | import Control.Applicative (many, (<|>), (<$>), Alternative, (*>)) | 13 | import Codec.Encryption.OpenPGP.ASCIIArmor.Utils |
14 | import Control.Applicative (many, (<|>), (<$>), Alternative, (<*), (<*>), (*>), optional) | ||
14 | import Data.Attoparsec.ByteString (Parser, many1, string, inClass, notInClass, satisfy, word8, (<?>), parse, IResult(..)) | 15 | import Data.Attoparsec.ByteString (Parser, many1, string, inClass, notInClass, satisfy, word8, (<?>), parse, IResult(..)) |
15 | import Data.Attoparsec.ByteString.Char8 (isDigit_w8, anyChar) | 16 | import Data.Attoparsec.ByteString.Char8 (isDigit_w8, anyChar) |
16 | import Data.Attoparsec.Combinator (manyTill) | 17 | import Data.Attoparsec.Combinator (manyTill) |
@@ -37,8 +38,21 @@ parseArmors :: Parser [Armor] | |||
37 | parseArmors = many parseArmor | 38 | parseArmors = many parseArmor |
38 | 39 | ||
39 | parseArmor :: Parser Armor | 40 | parseArmor :: Parser Armor |
40 | parseArmor = do | 41 | parseArmor = prefixed (clearsigned <|> armor) <?> "armor" |
41 | atype <- prefixed beginLine <?> "begin line" | 42 | |
43 | clearsigned :: Parser Armor | ||
44 | clearsigned = do | ||
45 | string "-----BEGIN PGP SIGNED MESSAGE-----" <?> "clearsign header" | ||
46 | lineEnding <?> "line ending" | ||
47 | headers <- armorHeaders <?> "clearsign headers" | ||
48 | blankishLine <?> "blank line" | ||
49 | cleartext <- dashEscapedCleartext | ||
50 | sig <- armor | ||
51 | return $ ClearSigned headers cleartext sig | ||
52 | |||
53 | armor :: Parser Armor | ||
54 | armor = do | ||
55 | atype <- beginLine <?> "begin line" | ||
42 | headers <- armorHeaders <?> "headers" | 56 | headers <- armorHeaders <?> "headers" |
43 | blankishLine <?> "blank line" | 57 | blankishLine <?> "blank line" |
44 | payload <- base64Data <?> "base64 data" | 58 | payload <- base64Data <?> "base64 data" |
@@ -84,7 +98,7 @@ armorHeader = do | |||
84 | w8sToString = BC8.unpack . B.pack | 98 | w8sToString = BC8.unpack . B.pack |
85 | 99 | ||
86 | blankishLine :: Parser ByteString | 100 | blankishLine :: Parser ByteString |
87 | blankishLine = many (satisfy (inClass " \t")) >> lineEnding | 101 | blankishLine = many (satisfy (inClass " \t")) *> lineEnding |
88 | 102 | ||
89 | endLine :: ArmorType -> Parser ByteString | 103 | endLine :: ArmorType -> Parser ByteString |
90 | endLine atype = do | 104 | endLine atype = do |
@@ -138,3 +152,13 @@ d24 = do | |||
138 | 152 | ||
139 | prefixed :: Parser a -> Parser a | 153 | prefixed :: Parser a -> Parser a |
140 | prefixed end = end <|> anyChar *> prefixed end | 154 | prefixed end = end <|> anyChar *> prefixed end |
155 | |||
156 | dashEscapedCleartext :: Parser ByteString | ||
157 | dashEscapedCleartext = do | ||
158 | ls <- many1 ((deLine <|> unescapedLine) <* lineEnding) | ||
159 | return $ crlfUnlines ls | ||
160 | where | ||
161 | deLine :: Parser ByteString | ||
162 | deLine = B.pack <$> (string "- " *> many (satisfy (notInClass "\n\r"))) | ||
163 | unescapedLine :: Parser ByteString | ||
164 | unescapedLine = maybe B.empty B.pack <$> optional ((:) <$> satisfy (notInClass "-\n\r") <*> many (satisfy (notInClass "\n\r"))) | ||
diff --git a/Codec/Encryption/OpenPGP/ASCIIArmor/Encode.hs b/Codec/Encryption/OpenPGP/ASCIIArmor/Encode.hs index 28bb3e6..00d9dd3 100644 --- a/Codec/Encryption/OpenPGP/ASCIIArmor/Encode.hs +++ b/Codec/Encryption/OpenPGP/ASCIIArmor/Encode.hs | |||
@@ -22,6 +22,7 @@ encode = B.concat . map armor | |||
22 | 22 | ||
23 | armor :: Armor -> ByteString | 23 | armor :: Armor -> ByteString |
24 | armor (Armor atype ahs bs) = beginLine atype `B.append` armorHeaders ahs `B.append` blankLine `B.append` armorData bs `B.append` armorChecksum bs `B.append` endLine atype | 24 | armor (Armor atype ahs bs) = beginLine atype `B.append` armorHeaders ahs `B.append` blankLine `B.append` armorData bs `B.append` armorChecksum bs `B.append` endLine atype |
25 | armor (ClearSigned chs ctxt csig) = BC8.pack "-----BEGIN PGP SIGNED MESSAGE-----\n" `B.append` armorHeaders chs `B.append` blankLine `B.append` dashEscape ctxt `B.append` armor csig | ||
25 | 26 | ||
26 | blankLine :: ByteString | 27 | blankLine :: ByteString |
27 | blankLine = BC8.singleton '\n' | 28 | blankLine = BC8.singleton '\n' |
@@ -57,3 +58,12 @@ wordWrap lw bs | |||
57 | 58 | ||
58 | armorChecksum :: ByteString -> ByteString | 59 | armorChecksum :: ByteString -> ByteString |
59 | armorChecksum = BC8.cons '=' . armorData . B.tail . runPut . putWord32be . crc24 | 60 | armorChecksum = BC8.cons '=' . armorData . B.tail . runPut . putWord32be . crc24 |
61 | |||
62 | dashEscape :: ByteString -> ByteString | ||
63 | dashEscape = BC8.unlines . map escapeLine . BC8.lines | ||
64 | where | ||
65 | escapeLine :: ByteString -> ByteString | ||
66 | escapeLine l | ||
67 | | BC8.singleton '-' `B.isPrefixOf` l = BC8.pack "- " `B.append` l | ||
68 | | BC8.pack "From " `B.isPrefixOf` l = BC8.pack "- " `B.append` l | ||
69 | | otherwise = l | ||
diff --git a/Codec/Encryption/OpenPGP/ASCIIArmor/Types.hs b/Codec/Encryption/OpenPGP/ASCIIArmor/Types.hs index 46416c1..88a03ce 100644 --- a/Codec/Encryption/OpenPGP/ASCIIArmor/Types.hs +++ b/Codec/Encryption/OpenPGP/ASCIIArmor/Types.hs | |||
@@ -11,7 +11,7 @@ module Codec.Encryption.OpenPGP.ASCIIArmor.Types ( | |||
11 | import Data.ByteString (ByteString) | 11 | import Data.ByteString (ByteString) |
12 | 12 | ||
13 | data Armor = Armor ArmorType [(String, String)] ByteString | 13 | data Armor = Armor ArmorType [(String, String)] ByteString |
14 | | ClearSigned [(String, String)] String Armor | 14 | | ClearSigned [(String, String)] ByteString Armor |
15 | deriving (Show, Eq) | 15 | deriving (Show, Eq) |
16 | 16 | ||
17 | data ArmorType = ArmorMessage | 17 | data ArmorType = ArmorMessage |
diff --git a/Codec/Encryption/OpenPGP/ASCIIArmor/Utils.hs b/Codec/Encryption/OpenPGP/ASCIIArmor/Utils.hs new file mode 100644 index 0000000..014c8aa --- /dev/null +++ b/Codec/Encryption/OpenPGP/ASCIIArmor/Utils.hs | |||
@@ -0,0 +1,17 @@ | |||
1 | -- ASCIIArmor/Utils.hs: OpenPGP (RFC4880) ASCII armor implementation | ||
2 | -- Copyright Ⓒ 2012 Clint Adams | ||
3 | -- This software is released under the terms of the ISC license. | ||
4 | -- (See the LICENSE file). | ||
5 | |||
6 | module Codec.Encryption.OpenPGP.ASCIIArmor.Utils ( | ||
7 | crlfUnlines | ||
8 | ) where | ||
9 | |||
10 | import Data.ByteString (ByteString) | ||
11 | import qualified Data.ByteString as B | ||
12 | import qualified Data.ByteString.Char8 as BC8 | ||
13 | import Data.List (intersperse) | ||
14 | |||
15 | crlfUnlines :: [ByteString] -> ByteString | ||
16 | crlfUnlines [] = B.empty | ||
17 | crlfUnlines ss = B.concat $ intersperse (BC8.pack "\r\n") ss | ||
diff --git a/openpgp-asciiarmor.cabal b/openpgp-asciiarmor.cabal index 9b141c2..afa7010 100644 --- a/openpgp-asciiarmor.cabal +++ b/openpgp-asciiarmor.cabal | |||
@@ -15,9 +15,15 @@ Extra-source-files: tests/suite.hs | |||
15 | , tests/data/msg1a.asc | 15 | , tests/data/msg1a.asc |
16 | , tests/data/msg1b.asc | 16 | , tests/data/msg1b.asc |
17 | , tests/data/msg1c.asc | 17 | , tests/data/msg1c.asc |
18 | , tests/data/msg2.asc | ||
19 | , tests/data/msg1.gpg | 18 | , tests/data/msg1.gpg |
19 | , tests/data/msg2.asc | ||
20 | , tests/data/msg2.pgp | 20 | , tests/data/msg2.pgp |
21 | , tests/data/msg3 | ||
22 | , tests/data/msg3.asc | ||
23 | , tests/data/msg3.sig | ||
24 | , tests/data/msg4 | ||
25 | , tests/data/msg4.asc | ||
26 | , tests/data/msg4.sig | ||
21 | 27 | ||
22 | Cabal-version: >= 1.10 | 28 | Cabal-version: >= 1.10 |
23 | 29 | ||
@@ -29,6 +35,7 @@ Library | |||
29 | , Codec.Encryption.OpenPGP.ASCIIArmor.Types | 35 | , Codec.Encryption.OpenPGP.ASCIIArmor.Types |
30 | Other-Modules: Data.Digest.CRC24 | 36 | Other-Modules: Data.Digest.CRC24 |
31 | , Codec.Encryption.OpenPGP.ASCIIArmor.Multipart | 37 | , Codec.Encryption.OpenPGP.ASCIIArmor.Multipart |
38 | , Codec.Encryption.OpenPGP.ASCIIArmor.Utils | ||
32 | Build-depends: attoparsec | 39 | Build-depends: attoparsec |
33 | , base > 4 && < 5 | 40 | , base > 4 && < 5 |
34 | , base64-bytestring | 41 | , base64-bytestring |
diff --git a/tests/data/msg3 b/tests/data/msg3 new file mode 100644 index 0000000..e9d15c8 --- /dev/null +++ b/tests/data/msg3 | |||
@@ -0,0 +1,9 @@ | |||
1 | This is a message that will be clearsigned. | ||
2 | |||
3 | From RFC4880, we know that some of these lines should be | ||
4 | dash-escaped. | ||
5 | |||
6 | -Lines starting with a minus-hyphen MUST be escaped. | ||
7 | - Lines starting with "From" SHOULD be escaped. | ||
8 | |||
9 | Other lines MAY be escaped. | ||
diff --git a/tests/data/msg3.asc b/tests/data/msg3.asc new file mode 100644 index 0000000..6d90d30 --- /dev/null +++ b/tests/data/msg3.asc | |||
@@ -0,0 +1,29 @@ | |||
1 | -----BEGIN PGP SIGNED MESSAGE----- | ||
2 | Hash: SHA1 | ||
3 | |||
4 | This is a message that will be clearsigned. | ||
5 | |||
6 | - From RFC4880, we know that some of these lines should be | ||
7 | dash-escaped. | ||
8 | |||
9 | - -Lines starting with a minus-hyphen MUST be escaped. | ||
10 | - - Lines starting with "From" SHOULD be escaped. | ||
11 | |||
12 | Other lines MAY be escaped. | ||
13 | -----BEGIN PGP SIGNATURE----- | ||
14 | Version: OpenPrivacy 0.99 | ||
15 | |||
16 | iQIcBAEBAgAGBQJPmXqrAAoJEN/7iwtcb1WCG3AQAJ6TBeX12YDI1f/AdtV46quG | ||
17 | augJYpYZvBbKESGXue1Nv22a7uH4h8LgWRsaEQxMBUwJvlMJfNkjEMAkXQbkj/Og | ||
18 | J+78bAGMV1GtC5MuwPr8E+M8Z/uHhbzj3fWuUask0Q057u655YIEdlnY4OcZv9jW | ||
19 | hT+/2kNcC8aw9+kg0I175XNxwBhRXoRKX6dhyAkRSnz7yuQtGXH7kQJAt7TOxxAb | ||
20 | dud+u5IJixDPebG+NONPfuW5VB8erByW6UPIy4BQBnaxflSD8qJXxCDMWNzOBlYG | ||
21 | whKXDmlcVgy3J7ghSh2zcFcZhM30Ng49t6k57HOXR9XnI5dskY45yns2nD4kt58/ | ||
22 | 7anmscGGj0S3pzoUuFAdVIEvziYDhISs35CmTmNh4r4LVuh4R+Zurt3mbe8O6amm | ||
23 | ZOWZzPsEDX/13B/DnL//70jVhTXUBqDj6MeNj5XHXVbIlfmIyeVLOIXiT/+u1FFt | ||
24 | +0ERqwFI152GGJJWlikn5bR6P89Xz+04OeTBdxV1fCGt+hlvN6e5X9K15P16QDiq | ||
25 | 4COHMZyIyHbtQr92BIj0P46WNsNZJDaoegHl6xtbq60eV3W+LRvgHNphjE+mdIp0 | ||
26 | EV5lBqDGupGYpHkPjZBg0pqASs0Xd3P7SwkoVimtH7mXCPrL4K+o6X8IwsfEMCGY | ||
27 | Ddej4NK0eolGoz/1sKB0 | ||
28 | =ZShm | ||
29 | -----END PGP SIGNATURE----- | ||
diff --git a/tests/data/msg3.sig b/tests/data/msg3.sig new file mode 100644 index 0000000..67ceced --- /dev/null +++ b/tests/data/msg3.sig | |||
Binary files differ | |||
diff --git a/tests/data/msg4 b/tests/data/msg4 new file mode 100644 index 0000000..b69b7b6 --- /dev/null +++ b/tests/data/msg4 | |||
@@ -0,0 +1 @@ | |||
This message is detach-signed. | |||
diff --git a/tests/data/msg4.asc b/tests/data/msg4.asc new file mode 100644 index 0000000..d1968f4 --- /dev/null +++ b/tests/data/msg4.asc | |||
@@ -0,0 +1,17 @@ | |||
1 | -----BEGIN PGP SIGNATURE----- | ||
2 | Version: GnuPG v1.4.12 (GNU/Linux) | ||
3 | |||
4 | iQIcBAABAgAGBQJPmZE0AAoJEN/7iwtcb1WC6EcQAK+NpDfsgTJgq+5nhZLZQcDC | ||
5 | +b+8K5eDn+Z/btFZz1h2mF3Y+MpJdgG5fvSSHsYRWiGuT8OBK5wm3vSYnSr8BeA5 | ||
6 | JUJDdhasF7LVosb0ToNiWLbtj9D9iiqmCaPW56Y2u3Ktv5Y4nOAWZw31OGv21B1c | ||
7 | ptYVv2iy1qPGgnHxYgM5ib37hzKlkTEGKFNMpfYqsMBZyXiKuLpVhEWelawMnCPJ | ||
8 | 3b7loOhYvR1Odmolg0dmcFsay7s3uXC/nze+xqTM0Z1HnMxQVW54aixhOoajDO6V | ||
9 | p7OUUN5g/PBXHvx/gh7gPqgRCazo93rHSgoP//AoEuljrU4W9iNpCEcE5HTdYx0b | ||
10 | xh10WxWE4VHI8BVt5qhSzPe8BmFRWz+g9CmsJdmhw45W8XxRJMJwoTWzGPcmHTFk | ||
11 | JTOgJ9/MKcBvYGsBd0wGYq82DbDPdtwGgh5Aa3nz1dxzLCq7qIhOa3VEYKAhCjTx | ||
12 | UHWnKZrdjSKz8U4D6CECyxlK5UApPc4jWzn3XYCX8s2F84YW7htduE57Yf60bXom | ||
13 | aefIbDWef1Q4MOUV10h1gyjXtdSiIHvJ0ItvGKmRiXztjhq6+azYN+4RaXzpF5/N | ||
14 | pqG/DNeTouzMRSzEoLTQ2oBHB8VIbCnP6J2Ck3wPfJZfc6FyCv0gMPQ5pTToll97 | ||
15 | 6toTAyOHl3pI/inp7IGj | ||
16 | =TJqj | ||
17 | -----END PGP SIGNATURE----- | ||
diff --git a/tests/data/msg4.sig b/tests/data/msg4.sig new file mode 100644 index 0000000..94483e2 --- /dev/null +++ b/tests/data/msg4.sig | |||
Binary files differ | |||
diff --git a/tests/suite.hs b/tests/suite.hs index 6fdd816..838a5f3 100644 --- a/tests/suite.hs +++ b/tests/suite.hs | |||
@@ -5,6 +5,7 @@ import Test.HUnit | |||
5 | 5 | ||
6 | import Codec.Encryption.OpenPGP.ASCIIArmor (encode, decode, multipartMerge) | 6 | import Codec.Encryption.OpenPGP.ASCIIArmor (encode, decode, multipartMerge) |
7 | import Codec.Encryption.OpenPGP.ASCIIArmor.Types | 7 | import Codec.Encryption.OpenPGP.ASCIIArmor.Types |
8 | import Codec.Encryption.OpenPGP.ASCIIArmor.Utils | ||
8 | 9 | ||
9 | import Data.ByteString (ByteString) | 10 | import Data.ByteString (ByteString) |
10 | import qualified Data.ByteString as B | 11 | import qualified Data.ByteString as B |
@@ -35,11 +36,39 @@ testArmorMultipartDecode fp target = do | |||
35 | where | 36 | where |
36 | getPayload (Armor _ _ pl) = pl | 37 | getPayload (Armor _ _ pl) = pl |
37 | 38 | ||
39 | testClearsignedDecodeBody :: FilePath -> FilePath -> Assertion | ||
40 | testClearsignedDecodeBody fp target = do | ||
41 | bs <- B.readFile $ "tests/data/" ++ fp | ||
42 | tbs <- B.readFile $ "tests/data/" ++ target | ||
43 | case decode bs of | ||
44 | Left e -> assertFailure $ "Decode failed (" ++ e ++ ") on " ++ fp | ||
45 | Right [a] -> assertEqual ("for " ++ fp) (convertEndings tbs) (getBody a) | ||
46 | where | ||
47 | getBody (ClearSigned _ txt _) = txt | ||
48 | convertEndings = crlfUnlines . BC8.lines | ||
49 | |||
50 | testClearsignedDecodeSig :: FilePath -> FilePath -> Assertion | ||
51 | testClearsignedDecodeSig fp target = do | ||
52 | bs <- B.readFile $ "tests/data/" ++ fp | ||
53 | tbs <- B.readFile $ "tests/data/" ++ target | ||
54 | case decode bs of | ||
55 | Left e -> assertFailure $ "Decode failed (" ++ e ++ ") on " ++ fp | ||
56 | Right [a] -> assertEqual ("for " ++ fp) tbs (getSig a) | ||
57 | where | ||
58 | getSig (ClearSigned _ _ (Armor _ _ sig)) = sig | ||
59 | |||
38 | testArmorEncode :: [FilePath] -> FilePath -> Assertion | 60 | testArmorEncode :: [FilePath] -> FilePath -> Assertion |
39 | testArmorEncode fps target = do | 61 | testArmorEncode fps target = do |
40 | bss <- mapM (\fp -> B.readFile $ "tests/data/" ++ fp) fps | 62 | bss <- mapM (\fp -> B.readFile $ "tests/data/" ++ fp) fps |
41 | tbs <- B.readFile $ "tests/data/" ++ target | 63 | tbs <- B.readFile $ "tests/data/" ++ target |
42 | assertEqual ("literaldata") (encode (map (\bs -> Armor ArmorMessage [("Version","OpenPrivacy 0.99")] bs) bss)) tbs | 64 | assertEqual ("literaldata") tbs (encode (map (\bs -> Armor ArmorMessage [("Version","OpenPrivacy 0.99")] bs) bss)) |
65 | |||
66 | testClearsignedEncode :: FilePath -> FilePath -> FilePath -> Assertion | ||
67 | testClearsignedEncode ftxt fsig ftarget = do | ||
68 | txt <- B.readFile $ "tests/data/" ++ ftxt | ||
69 | sig <- B.readFile $ "tests/data/" ++ fsig | ||
70 | target <- B.readFile $ "tests/data/" ++ ftarget | ||
71 | assertEqual ("clearsigned encode") target (encode [ClearSigned [("Hash","SHA1")] txt (Armor ArmorSignature [("Version","OpenPrivacy 0.99")] sig)]) | ||
43 | 72 | ||
44 | tests = [ | 73 | tests = [ |
45 | testGroup "CRC24" [ | 74 | testGroup "CRC24" [ |
@@ -51,9 +80,13 @@ tests = [ | |||
51 | testCase "Decode sample armor" (testArmorDecode "msg1.asc" ["msg1.gpg"]) | 80 | testCase "Decode sample armor" (testArmorDecode "msg1.asc" ["msg1.gpg"]) |
52 | , testCase "Decode sample armor with cruft" (testArmorDecode "msg1a.asc" ["msg1.gpg"]) | 81 | , testCase "Decode sample armor with cruft" (testArmorDecode "msg1a.asc" ["msg1.gpg"]) |
53 | , testCase "Decode multiple sample armors" (testArmorDecode "msg1b.asc" ["msg1.gpg","msg1.gpg","msg1.gpg"]) | 82 | , testCase "Decode multiple sample armors" (testArmorDecode "msg1b.asc" ["msg1.gpg","msg1.gpg","msg1.gpg"]) |
83 | , testCase "Decode detached signature" (testArmorDecode "msg4.asc" ["msg4.sig"]) | ||
54 | , testCase "Decode multi-part armor" (testArmorMultipartDecode "msg2.asc" "msg2.pgp") | 84 | , testCase "Decode multi-part armor" (testArmorMultipartDecode "msg2.asc" "msg2.pgp") |
85 | , testCase "Decode body of clear-signed" (testClearsignedDecodeBody "msg3.asc" "msg3") | ||
86 | , testCase "Decode sig of clear-signed" (testClearsignedDecodeSig "msg3.asc" "msg3.sig") | ||
55 | , testCase "Encode sample armor" (testArmorEncode ["msg1.gpg"] "msg1.asc") | 87 | , testCase "Encode sample armor" (testArmorEncode ["msg1.gpg"] "msg1.asc") |
56 | , testCase "Encode multiple sample armors" (testArmorEncode ["msg1.gpg","msg1.gpg","msg1.gpg"] "msg1c.asc") | 88 | , testCase "Encode multiple sample armors" (testArmorEncode ["msg1.gpg","msg1.gpg","msg1.gpg"] "msg1c.asc") |
89 | , testCase "Encode clear-signed sig" (testClearsignedEncode "msg3" "msg3.sig" "msg3.asc") | ||
57 | ] | 90 | ] |
58 | ] | 91 | ] |
59 | 92 | ||