summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorClint Adams <clint@debian.org>2012-04-25 21:48:48 -0400
committerClint Adams <clint@debian.org>2012-04-25 21:48:48 -0400
commit83f494d1c3dbf75054284334bc30e8a1b9825146 (patch)
tree7a69de9239aaf6c3607f49340c48b0506d3a9598
parent4a0bb47803be6be43b8bb5c62f302019a25f9fd1 (diff)
Fix decoding of multi-part ASCII armor.
-rw-r--r--Codec/Encryption/OpenPGP/ASCIIArmor/Decode.hs46
-rw-r--r--Codec/Encryption/OpenPGP/ASCIIArmor/Encode.hs10
-rw-r--r--Codec/Encryption/OpenPGP/ASCIIArmor/Types.hs16
3 files changed, 38 insertions, 34 deletions
diff --git a/Codec/Encryption/OpenPGP/ASCIIArmor/Decode.hs b/Codec/Encryption/OpenPGP/ASCIIArmor/Decode.hs
index e69087c..0376abc 100644
--- a/Codec/Encryption/OpenPGP/ASCIIArmor/Decode.hs
+++ b/Codec/Encryption/OpenPGP/ASCIIArmor/Decode.hs
@@ -26,17 +26,17 @@ import Data.Serialize.Put (runPut, putWord32be)
26import Data.String (IsString, fromString) 26import Data.String (IsString, fromString)
27import Data.Word (Word32) 27import Data.Word (Word32)
28 28
29decode :: (Integral a, Read a, Show a, IsString e) => ByteString -> Either e ([Armor a]) 29decode :: IsString e => ByteString -> Either e [Armor]
30decode bs = go (parse parseArmors bs) 30decode bs = go (parse parseArmors bs)
31 where 31 where
32 go (Fail t c e) = Left (fromString e) 32 go (Fail t c e) = Left (fromString e)
33 go (Partial cont) = go (cont B.empty) 33 go (Partial cont) = go (cont B.empty)
34 go (Done _ r) = Right r 34 go (Done _ r) = Right r
35 35
36parseArmors :: (Integral a, Read a, Show a) => Parser ([Armor a]) 36parseArmors :: Parser [Armor]
37parseArmors = many parseArmor 37parseArmors = many parseArmor
38 38
39parseArmor :: (Integral a, Read a, Show a) => Parser (Armor a) 39parseArmor :: Parser Armor
40parseArmor = do 40parseArmor = do
41 atype <- prefixed beginLine <?> "begin line" 41 atype <- prefixed beginLine <?> "begin line"
42 headers <- armorHeaders <?> "headers" 42 headers <- armorHeaders <?> "headers"
@@ -45,23 +45,27 @@ parseArmor = do
45 endLine atype <?> "end line" 45 endLine atype <?> "end line"
46 return $ Armor atype headers payload 46 return $ Armor atype headers payload
47 47
48beginLine :: (Integral a, Read a, Show a) => Parser (ArmorType a) 48beginLine :: Parser ArmorType
49beginLine = do 49beginLine = do
50 string "-----BEGIN PGP " 50 string "-----BEGIN PGP " <?> "leading minus-hyphens"
51 atype <- message <|> pubkey <|> privkey<|> parts <|> signature 51 atype <- pubkey <|> privkey <|> parts <|> message <|> signature
52 string "-----" 52 string "-----" <?> "trailing minus-hyphens"
53 many (satisfy (inClass " \t")) 53 many (satisfy (inClass " \t")) <?> "whitespace"
54 lineEnding 54 lineEnding <?> "line ending"
55 return atype 55 return atype
56 where 56 where
57 message = string "MESSAGE" >> return ArmorMessage 57 message = string "MESSAGE" *> return ArmorMessage
58 pubkey = string "PUBLIC KEY BLOCK" >> return ArmorPublicKeyBlock 58 pubkey = string "PUBLIC KEY BLOCK" *> return ArmorPublicKeyBlock
59 privkey = string "PRIVATE KEY BLOCK" >> return ArmorPrivateKeyBlock 59 privkey = string "PRIVATE KEY BLOCK" *> return ArmorPrivateKeyBlock
60 signature = string "SIGNATURE" >> return ArmorSignature 60 signature = string "SIGNATURE" *> return ArmorSignature
61 parts = do 61 parts = string "MESSAGE, PART " *> (partsdef <|> partsindef)
62 string "MESSAGE, PART " 62 partsdef = do
63 firstnum <- read . BC8.unpack . B.pack <$> many1 (satisfy isDigit_w8) 63 firstnum <- num
64 return $ ArmorSplitMessageIndefinite firstnum 64 word8 (fromIntegral . fromEnum $ '/')
65 secondnum <- num
66 return $ ArmorSplitMessage (B.pack firstnum) (B.pack secondnum)
67 partsindef = ArmorSplitMessageIndefinite . B.pack <$> num
68 num = many1 (satisfy isDigit_w8) <?> "number"
65 69
66lineEnding :: Parser ByteString 70lineEnding :: Parser ByteString
67lineEnding = string "\n" <|> string "\r\n" 71lineEnding = string "\n" <|> string "\r\n"
@@ -82,17 +86,17 @@ armorHeader = do
82blankishLine :: Parser ByteString 86blankishLine :: Parser ByteString
83blankishLine = many (satisfy (inClass " \t")) >> lineEnding 87blankishLine = many (satisfy (inClass " \t")) >> lineEnding
84 88
85endLine :: (Integral a, Read a, Show a) => ArmorType a -> Parser ByteString 89endLine :: ArmorType -> Parser ByteString
86endLine atype = do 90endLine atype = do
87 string $ "-----END PGP " `B.append` aType atype `B.append` "-----" 91 string $ "-----END PGP " `B.append` aType atype `B.append` "-----"
88 lineEnding 92 lineEnding
89 93
90aType :: (Integral a, Read a, Show a) => ArmorType a -> ByteString 94aType :: ArmorType -> ByteString
91aType (ArmorMessage) = BC8.pack "MESSAGE" 95aType (ArmorMessage) = BC8.pack "MESSAGE"
92aType (ArmorPublicKeyBlock) = BC8.pack "PUBLIC KEY BLOCK" 96aType (ArmorPublicKeyBlock) = BC8.pack "PUBLIC KEY BLOCK"
93aType (ArmorPrivateKeyBlock) = BC8.pack "PRIVATE KEY BLOCK" 97aType (ArmorPrivateKeyBlock) = BC8.pack "PRIVATE KEY BLOCK"
94aType (ArmorSplitMessage x y) = BC8.pack $ "MESSAGE, PART " ++ show x ++ "/" ++ show y 98aType (ArmorSplitMessage x y) = BC8.pack "MESSAGE, PART " `B.append` x `B.append` BC8.singleton '/' `B.append` y
95aType (ArmorSplitMessageIndefinite x) = BC8.pack $ "MESSAGE, PART " ++ show x 99aType (ArmorSplitMessageIndefinite x) = BC8.pack "MESSAGE, PART " `B.append` x
96aType (ArmorSignature) = BC8.pack "SIGNATURE" 100aType (ArmorSignature) = BC8.pack "SIGNATURE"
97 101
98base64Data :: Parser ByteString 102base64Data :: Parser ByteString
diff --git a/Codec/Encryption/OpenPGP/ASCIIArmor/Encode.hs b/Codec/Encryption/OpenPGP/ASCIIArmor/Encode.hs
index 99d4d54..28bb3e6 100644
--- a/Codec/Encryption/OpenPGP/ASCIIArmor/Encode.hs
+++ b/Codec/Encryption/OpenPGP/ASCIIArmor/Encode.hs
@@ -17,22 +17,22 @@ import Data.Serialize (put)
17import Data.Serialize.Put (runPut, putWord32be) 17import Data.Serialize.Put (runPut, putWord32be)
18import Data.String (IsString, fromString) 18import Data.String (IsString, fromString)
19 19
20encode :: (Integral a, Show a) => [Armor a] -> ByteString 20encode :: [Armor] -> ByteString
21encode = B.concat . map armor 21encode = B.concat . map armor
22 22
23armor :: (Integral a, Show a) => Armor a -> ByteString 23armor :: Armor -> ByteString
24armor (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 24armor (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 25
26blankLine :: ByteString 26blankLine :: ByteString
27blankLine = BC8.singleton '\n' 27blankLine = BC8.singleton '\n'
28 28
29beginLine :: (Integral a, Show a) => ArmorType a -> ByteString 29beginLine :: ArmorType -> ByteString
30beginLine atype = BC8.pack "-----BEGIN PGP " `B.append` aType atype `B.append` BC8.pack "-----\n" 30beginLine atype = BC8.pack "-----BEGIN PGP " `B.append` aType atype `B.append` BC8.pack "-----\n"
31 31
32endLine :: (Integral a, Show a) => ArmorType a -> ByteString 32endLine :: ArmorType -> ByteString
33endLine atype = BC8.pack "-----END PGP " `B.append` aType atype `B.append` BC8.pack "-----\n" 33endLine atype = BC8.pack "-----END PGP " `B.append` aType atype `B.append` BC8.pack "-----\n"
34 34
35aType :: (Integral a, Show a) => ArmorType a -> ByteString 35aType :: ArmorType -> ByteString
36aType (ArmorMessage) = BC8.pack "MESSAGE" 36aType (ArmorMessage) = BC8.pack "MESSAGE"
37aType (ArmorPublicKeyBlock) = BC8.pack "PUBLIC KEY BLOCK" 37aType (ArmorPublicKeyBlock) = BC8.pack "PUBLIC KEY BLOCK"
38aType (ArmorPrivateKeyBlock) = BC8.pack "PRIVATE KEY BLOCK" 38aType (ArmorPrivateKeyBlock) = BC8.pack "PRIVATE KEY BLOCK"
diff --git a/Codec/Encryption/OpenPGP/ASCIIArmor/Types.hs b/Codec/Encryption/OpenPGP/ASCIIArmor/Types.hs
index 8c7ef6f..46416c1 100644
--- a/Codec/Encryption/OpenPGP/ASCIIArmor/Types.hs
+++ b/Codec/Encryption/OpenPGP/ASCIIArmor/Types.hs
@@ -10,14 +10,14 @@ module Codec.Encryption.OpenPGP.ASCIIArmor.Types (
10 10
11import Data.ByteString (ByteString) 11import Data.ByteString (ByteString)
12 12
13data Armor a = Armor (ArmorType a) [(String, String)] ByteString 13data Armor = Armor ArmorType [(String, String)] ByteString
14 | ClearSigned [(String, String)] String (Armor a) 14 | ClearSigned [(String, String)] String Armor
15 deriving (Show, Eq) 15 deriving (Show, Eq)
16 16
17data ArmorType a = ArmorMessage 17data ArmorType = ArmorMessage
18 | ArmorPublicKeyBlock 18 | ArmorPublicKeyBlock
19 | ArmorPrivateKeyBlock 19 | ArmorPrivateKeyBlock
20 | ArmorSplitMessage a a 20 | ArmorSplitMessage ByteString ByteString
21 | ArmorSplitMessageIndefinite a 21 | ArmorSplitMessageIndefinite ByteString
22 | ArmorSignature 22 | ArmorSignature
23 deriving (Show, Eq) 23 deriving (Show, Eq)