summaryrefslogtreecommitdiff
path: root/Codec
diff options
context:
space:
mode:
authorClint Adams <clint@softwarefreedom.org>2012-04-26 16:29:50 -0400
committerClint Adams <clint@softwarefreedom.org>2012-04-26 16:29:50 -0400
commit716dd382221343e5da5daf1a9a8ac40304a7d74b (patch)
tree0a2b7bed56f9ec6564d4a9e918ab4e8fd53c0dc5 /Codec
parentd17ea2bb11255f7e6ae9069d3b58e8f06d5946a5 (diff)
Codec for "Cleartext Signatures"
Diffstat (limited to 'Codec')
-rw-r--r--Codec/Encryption/OpenPGP/ASCIIArmor/Decode.hs32
-rw-r--r--Codec/Encryption/OpenPGP/ASCIIArmor/Encode.hs10
-rw-r--r--Codec/Encryption/OpenPGP/ASCIIArmor/Types.hs2
-rw-r--r--Codec/Encryption/OpenPGP/ASCIIArmor/Utils.hs17
4 files changed, 56 insertions, 5 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
12import Codec.Encryption.OpenPGP.ASCIIArmor.Types 12import Codec.Encryption.OpenPGP.ASCIIArmor.Types
13import Control.Applicative (many, (<|>), (<$>), Alternative, (*>)) 13import Codec.Encryption.OpenPGP.ASCIIArmor.Utils
14import Control.Applicative (many, (<|>), (<$>), Alternative, (<*), (<*>), (*>), optional)
14import Data.Attoparsec.ByteString (Parser, many1, string, inClass, notInClass, satisfy, word8, (<?>), parse, IResult(..)) 15import Data.Attoparsec.ByteString (Parser, many1, string, inClass, notInClass, satisfy, word8, (<?>), parse, IResult(..))
15import Data.Attoparsec.ByteString.Char8 (isDigit_w8, anyChar) 16import Data.Attoparsec.ByteString.Char8 (isDigit_w8, anyChar)
16import Data.Attoparsec.Combinator (manyTill) 17import Data.Attoparsec.Combinator (manyTill)
@@ -37,8 +38,21 @@ parseArmors :: Parser [Armor]
37parseArmors = many parseArmor 38parseArmors = many parseArmor
38 39
39parseArmor :: Parser Armor 40parseArmor :: Parser Armor
40parseArmor = do 41parseArmor = prefixed (clearsigned <|> armor) <?> "armor"
41 atype <- prefixed beginLine <?> "begin line" 42
43clearsigned :: Parser Armor
44clearsigned = 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
53armor :: Parser Armor
54armor = 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
86blankishLine :: Parser ByteString 100blankishLine :: Parser ByteString
87blankishLine = many (satisfy (inClass " \t")) >> lineEnding 101blankishLine = many (satisfy (inClass " \t")) *> lineEnding
88 102
89endLine :: ArmorType -> Parser ByteString 103endLine :: ArmorType -> Parser ByteString
90endLine atype = do 104endLine atype = do
@@ -138,3 +152,13 @@ d24 = do
138 152
139prefixed :: Parser a -> Parser a 153prefixed :: Parser a -> Parser a
140prefixed end = end <|> anyChar *> prefixed end 154prefixed end = end <|> anyChar *> prefixed end
155
156dashEscapedCleartext :: Parser ByteString
157dashEscapedCleartext = 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
23armor :: Armor -> 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
25armor (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
26blankLine :: ByteString 27blankLine :: ByteString
27blankLine = BC8.singleton '\n' 28blankLine = BC8.singleton '\n'
@@ -57,3 +58,12 @@ wordWrap lw bs
57 58
58armorChecksum :: ByteString -> ByteString 59armorChecksum :: ByteString -> ByteString
59armorChecksum = BC8.cons '=' . armorData . B.tail . runPut . putWord32be . crc24 60armorChecksum = BC8.cons '=' . armorData . B.tail . runPut . putWord32be . crc24
61
62dashEscape :: ByteString -> ByteString
63dashEscape = 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 (
11import Data.ByteString (ByteString) 11import Data.ByteString (ByteString)
12 12
13data Armor = Armor ArmorType [(String, String)] ByteString 13data 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
17data ArmorType = ArmorMessage 17data 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
6module Codec.Encryption.OpenPGP.ASCIIArmor.Utils (
7 crlfUnlines
8) where
9
10import Data.ByteString (ByteString)
11import qualified Data.ByteString as B
12import qualified Data.ByteString.Char8 as BC8
13import Data.List (intersperse)
14
15crlfUnlines :: [ByteString] -> ByteString
16crlfUnlines [] = B.empty
17crlfUnlines ss = B.concat $ intersperse (BC8.pack "\r\n") ss