hOpenPGP 0.2 → 0.3
raw patch · 14 files changed
+349/−376 lines, 14 filesdep +exception-transformersdep +openpgp-asciiarmordep +resourcetdep ~cereal-conduitdep ~conduitbinary-addedPVP ok
version bump matches the API change (PVP)
Dependencies added: exception-transformers, openpgp-asciiarmor, resourcet
Dependency ranges changed: cereal-conduit, conduit
API changes (from Hackage documentation)
- Codec.Encryption.OpenPGP.ASCIIArmor: armor :: (Integral a, Show a) => Armor a -> ByteString
- Codec.Encryption.OpenPGP.ASCIIArmor: decodeArmor :: (Integral a, Read a, Show a, IsString e) => ByteString -> Either e (Armor a)
- Codec.Encryption.OpenPGP.ASCIIArmor: parseArmor :: (Integral a, Read a, Show a) => Parser (Armor a)
- Codec.Encryption.OpenPGP.Types: Armor :: (ArmorType a) -> [ArmorHeader] -> [Packet] -> Armor a
- Codec.Encryption.OpenPGP.Types: ArmorMessage :: ArmorType a
- Codec.Encryption.OpenPGP.Types: ArmorPrivateKeyBlock :: ArmorType a
- Codec.Encryption.OpenPGP.Types: ArmorPublicKeyBlock :: ArmorType a
- Codec.Encryption.OpenPGP.Types: ArmorSignature :: ArmorType a
- Codec.Encryption.OpenPGP.Types: ArmorSplitMessage :: a -> a -> ArmorType a
- Codec.Encryption.OpenPGP.Types: ArmorSplitMessageIndefinite :: a -> ArmorType a
- Codec.Encryption.OpenPGP.Types: NoTK :: TK
- Codec.Encryption.OpenPGP.Types: data Armor a
- Codec.Encryption.OpenPGP.Types: data ArmorType a
- Codec.Encryption.OpenPGP.Types: data TK
- Codec.Encryption.OpenPGP.Types: instance Eq TK
- Codec.Encryption.OpenPGP.Types: instance Eq a => Eq (Armor a)
- Codec.Encryption.OpenPGP.Types: instance Eq a => Eq (ArmorType a)
- Codec.Encryption.OpenPGP.Types: instance Show TK
- Codec.Encryption.OpenPGP.Types: instance Show a => Show (Armor a)
- Codec.Encryption.OpenPGP.Types: instance Show a => Show (ArmorType a)
- Codec.Encryption.OpenPGP.Types: type ArmorHeader = (ByteString, ByteString)
- Codec.Encryption.OpenPGP.Types: type SessionKey = ByteString
- Data.Conduit.OpenPGP.Keyring: conduitToTKs :: Resource m => Conduit Packet m TK
+ Codec.Encryption.OpenPGP.Types: NTSecretSubkey :: Packet -> KRK
+ Codec.Encryption.OpenPGP.Types: NTSubkey :: Packet -> KRK
+ Codec.Encryption.OpenPGP.Types: NoKRK :: KRK
+ Codec.Encryption.OpenPGP.Types: data KRK
+ Codec.Encryption.OpenPGP.Types: instance Eq KRK
+ Codec.Encryption.OpenPGP.Types: instance Show KRK
+ Data.Conduit.OpenPGP.Keyring: conduitToKRKs :: MonadResource m => Conduit Packet m KRK
- Codec.Encryption.OpenPGP.Types: PKESK :: PacketVersion -> EightOctetKeyId -> PubKeyAlgorithm -> SessionKey -> Packet
+ Codec.Encryption.OpenPGP.Types: PKESK :: PacketVersion -> EightOctetKeyId -> PubKeyAlgorithm -> [MPI] -> Packet
- Codec.Encryption.OpenPGP.Types: SKESK :: PacketVersion -> SymmetricAlgorithm -> S2K -> (Maybe SessionKey) -> Packet
+ Codec.Encryption.OpenPGP.Types: SKESK :: PacketVersion -> SymmetricAlgorithm -> S2K -> [MPI] -> Packet
- Codec.Encryption.OpenPGP.Types: TPK :: PKPayload -> [SignaturePayload] -> [(String, [SignaturePayload])] -> [([UserAttrSubPacket], [SignaturePayload])] -> [(PKPayload, SignaturePayload, Maybe SignaturePayload)] -> TK
+ Codec.Encryption.OpenPGP.Types: TPK :: PKPayload -> [SignaturePayload] -> [(String, [SignaturePayload])] -> [([UserAttrSubPacket], [SignaturePayload])] -> [(PKPayload, SignaturePayload, Maybe SignaturePayload)] -> KRK
- Codec.Encryption.OpenPGP.Types: TSK :: Packet -> [SignaturePayload] -> [(String, [SignaturePayload])] -> [([UserAttrSubPacket], [SignaturePayload])] -> [(Packet, SignaturePayload, Maybe SignaturePayload)] -> TK
+ Codec.Encryption.OpenPGP.Types: TSK :: Packet -> [SignaturePayload] -> [(String, [SignaturePayload])] -> [([UserAttrSubPacket], [SignaturePayload])] -> [(Packet, SignaturePayload, Maybe SignaturePayload)] -> KRK
- Codec.Encryption.OpenPGP.Types: type Keyring = Map EightOctetKeyId TK
+ Codec.Encryption.OpenPGP.Types: type Keyring = Map EightOctetKeyId KRK
- Data.Conduit.OpenPGP.Compression: conduitCompress :: ResourceThrow m => CompressionAlgorithm -> Conduit Packet m Packet
+ Data.Conduit.OpenPGP.Compression: conduitCompress :: MonadThrow m => CompressionAlgorithm -> Conduit Packet m Packet
- Data.Conduit.OpenPGP.Compression: conduitDecompress :: ResourceThrow m => Conduit Packet m Packet
+ Data.Conduit.OpenPGP.Compression: conduitDecompress :: MonadThrow m => Conduit Packet m Packet
- Data.Conduit.OpenPGP.Keyring: sinkKeyringMap :: Resource m => Sink TK m (Map EightOctetKeyId TK)
+ Data.Conduit.OpenPGP.Keyring: sinkKeyringMap :: MonadResource m => Sink KRK m (Map EightOctetKeyId KRK)
- Data.Conduit.OpenPGP.Verify: conduitVerify :: Resource m => Keyring -> Conduit Packet m (Either String Bool)
+ Data.Conduit.OpenPGP.Verify: conduitVerify :: MonadResource m => Keyring -> Conduit Packet m (Either String Bool)
Files
- Codec/Encryption/OpenPGP/ASCIIArmor.hs +0/−13
- Codec/Encryption/OpenPGP/ASCIIArmor/Decode.hs +0/−129
- Codec/Encryption/OpenPGP/ASCIIArmor/Encode.hs +0/−59
- Codec/Encryption/OpenPGP/Serialize.hs +276/−21
- Codec/Encryption/OpenPGP/Types.hs +5/−23
- Data/Conduit/Cereal/Temp.hs +0/−31
- Data/Conduit/OpenPGP/Compression.hs +3/−3
- Data/Conduit/OpenPGP/Keyring.hs +13/−11
- Data/Conduit/OpenPGP/Verify.hs +1/−1
- Data/Digest/CRC24.hs +0/−25
- hOpenPGP.cabal +12/−11
- tests/data/encryption.gpg binary
- tests/data/uncompressed-ops-dsa-sha384.txt.gpg binary
- tests/suite.hs +39/−49
− Codec/Encryption/OpenPGP/ASCIIArmor.hs
@@ -1,13 +0,0 @@--- ASCIIArmor.hs: OpenPGP (RFC4880) ASCII armor implementation--- Copyright Ⓒ 2012 Clint Adams--- This software is released under the terms of the Expat (MIT) license.--- (See the LICENSE file).--module Codec.Encryption.OpenPGP.ASCIIArmor (- armor- , decodeArmor- , parseArmor-) where--import Codec.Encryption.OpenPGP.ASCIIArmor.Encode (armor)-import Codec.Encryption.OpenPGP.ASCIIArmor.Decode (decodeArmor, parseArmor)
− Codec/Encryption/OpenPGP/ASCIIArmor/Decode.hs
@@ -1,129 +0,0 @@-{-# LANGUAGE OverloadedStrings #-}--- ASCIIArmor/Decode.hs: OpenPGP (RFC4880) ASCII armor implementation--- Copyright Ⓒ 2012 Clint Adams--- This software is released under the terms of the Expat (MIT) license.--- (See the LICENSE file).--module Codec.Encryption.OpenPGP.ASCIIArmor.Decode (- parseArmor- , decodeArmor-) where--import Codec.Encryption.OpenPGP.Serialize ()-import Codec.Encryption.OpenPGP.Types-import Control.Applicative (many, (<|>), (<$>))-import Data.Attoparsec.ByteString (Parser, many1, string, inClass, notInClass, satisfy, word8, (<?>), parse, IResult(..))-import Data.Attoparsec.ByteString.Char8 (isDigit_w8)-import Data.Bits (shiftL)-import Data.ByteString (ByteString)-import qualified Data.ByteString as B-import qualified Data.ByteString.Char8 as BC8-import qualified Data.ByteString.Base64 as Base64-import Data.Digest.CRC24 (crc24)-import Data.Serialize (get)-import Data.Serialize.Get (Get, runGet, getWord8)-import Data.Serialize.Put (runPut, putWord32be)-import Data.String (IsString, fromString)-import Data.Word (Word32)--decodeArmor :: (Integral a, Read a, Show a, IsString e) => ByteString -> Either e (Armor a)-decodeArmor bs = case parse parseArmor bs of- Fail t c e -> Left (fromString e)- Partial _ -> Left (fromString "what")- Done _ r -> Right r--parseArmor :: (Integral a, Read a, Show a) => Parser (Armor a)-parseArmor = do- atype <- beginLine <?> "begin line"- headers <- armorHeaders <?> "headers"- blankishLine <?> "blank line"- payload <- base64Data <?> "base64 data"- endLine atype <?> "end line"- case runGet get payload of- Left err -> fail err- Right packets -> return $ Armor atype headers (unBlock packets)--beginLine :: (Integral a, Read a, Show a) => Parser (ArmorType a)-beginLine = do- string "-----BEGIN PGP "- atype <- message <|> pubkey <|> privkey<|> parts <|> signature- string "-----"- many (satisfy (inClass " \t"))- lineEnding- return atype- where- message = string "MESSAGE" >> return ArmorMessage- pubkey = string "PUBLIC KEY BLOCK" >> return ArmorPublicKeyBlock- privkey = string "PRIVATE KEY BLOCK" >> return ArmorPrivateKeyBlock- signature = string "SIGNATURE" >> return ArmorSignature- parts = do- string "MESSAGE, PART "- firstnum <- read . BC8.unpack . B.pack <$> many1 (satisfy isDigit_w8)- return $ ArmorSplitMessageIndefinite firstnum--lineEnding :: Parser ByteString-lineEnding = string "\n" <|> string "\r\n"--armorHeaders :: Parser [ArmorHeader]-armorHeaders = many armorHeader--armorHeader :: Parser ArmorHeader-armorHeader = do- key <- many1 (satisfy (inClass "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"))- string ": "- val <- many1 (satisfy (notInClass "\n\r"))- lineEnding- return (B.pack key, B.pack val)--blankishLine :: Parser ByteString-blankishLine = many (satisfy (inClass " \t")) >> lineEnding--endLine :: (Integral a, Read a, Show a) => ArmorType a -> Parser ByteString-endLine atype = do- string $ "-----END PGP " `B.append` aType atype `B.append` "-----"- lineEnding--aType :: (Integral a, Read a, Show a) => ArmorType a -> ByteString-aType (ArmorMessage) = BC8.pack "MESSAGE"-aType (ArmorPublicKeyBlock) = BC8.pack "PUBLIC KEY BLOCK"-aType (ArmorPrivateKeyBlock) = BC8.pack "PRIVATE KEY BLOCK"-aType (ArmorSplitMessage x y) = BC8.pack $ "MESSAGE, PART " ++ show x ++ "/" ++ show y-aType (ArmorSplitMessageIndefinite x) = BC8.pack $ "MESSAGE, PART " ++ show x-aType (ArmorSignature) = BC8.pack "SIGNATURE"--base64Data :: Parser ByteString-base64Data = do- ls <- many1 base64Line- cksum <- checksumLine- let payload = B.concat ls- let ourcksum = crc24 payload- case runGet d24 cksum of- Left err -> fail err- Right theircksum -> if theircksum == ourcksum then return payload else fail ("CRC24 mismatch: " ++ show (B.unpack cksum) ++ "/" ++ show theircksum ++ " vs. " ++ show ourcksum)- where- base64Line :: Parser ByteString- base64Line = do- b64 <- many1 (satisfy (inClass "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"))- pad <- many (word8 (fromIntegral . fromEnum $ '='))- lineEnding- let line = B.pack b64 `B.append` B.pack pad- case Base64.decode line of- Left err -> fail err- Right bs -> return bs- checksumLine :: Parser ByteString- checksumLine = do- word8 (fromIntegral . fromEnum $ '=')- b64 <- many1 (satisfy (inClass "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"))- lineEnding- let line = B.pack b64- case Base64.decode line of- Left err -> fail err- Right bs -> return bs---d24 :: Get Word32-d24 = do- a <- getWord8- b <- getWord8- c <- getWord8- return $ shiftL (fromIntegral a :: Word32) 16 + shiftL (fromIntegral b :: Word32) 8 + (fromIntegral c :: Word32)
− Codec/Encryption/OpenPGP/ASCIIArmor/Encode.hs
@@ -1,59 +0,0 @@--- ASCIIArmor/Encode.hs: OpenPGP (RFC4880) ASCII armor implementation--- Copyright Ⓒ 2012 Clint Adams--- This software is released under the terms of the Expat (MIT) license.--- (See the LICENSE file).--module Codec.Encryption.OpenPGP.ASCIIArmor.Encode (- armor-) where--import Codec.Encryption.OpenPGP.Serialize ()-import Codec.Encryption.OpenPGP.Types-import Data.ByteString (ByteString)-import qualified Data.ByteString as B-import qualified Data.ByteString.Char8 as BC8-import qualified Data.ByteString.Base64 as Base64-import Data.Digest.CRC24 (crc24)-import Data.Serialize (put)-import Data.Serialize.Put (runPut, putWord32be)-import Data.String (IsString, fromString)--armor :: (Integral a, Show a) => Armor a -> ByteString-armor (Armor atype ahs ps) = beginLine atype `B.append` armorHeaders ahs `B.append` blankLine `B.append` armorData (opgpStream ps) `B.append` armorChecksum (opgpStream ps) `B.append` endLine atype--blankLine :: ByteString-blankLine = BC8.singleton '\n'--beginLine :: (Integral a, Show a) => ArmorType a -> ByteString-beginLine atype = BC8.pack "-----BEGIN PGP " `B.append` aType atype `B.append` BC8.pack "-----\n"--endLine :: (Integral a, Show a) => ArmorType a -> ByteString-endLine atype = BC8.pack "-----END PGP " `B.append` aType atype `B.append` BC8.pack "-----\n"--aType :: (Integral a, Show a) => ArmorType a -> ByteString-aType (ArmorMessage) = BC8.pack "MESSAGE"-aType (ArmorPublicKeyBlock) = BC8.pack "PUBLIC KEY BLOCK"-aType (ArmorPrivateKeyBlock) = BC8.pack "PRIVATE KEY BLOCK"-aType (ArmorSplitMessage x y) = BC8.pack $ "MESSAGE, PART " ++ show x ++ "/" ++ show y-aType (ArmorSplitMessageIndefinite x) = BC8.pack $ "MESSAGE, PART " ++ show x-aType (ArmorSignature) = BC8.pack "SIGNATURE"--armorHeaders :: [ArmorHeader] -> ByteString-armorHeaders ahs = BC8.unlines . map armorHeader $ ahs- where- armorHeader :: ArmorHeader -> ByteString- armorHeader (k, v) = k `B.append` BC8.pack ": " `B.append` v--opgpStream :: [Packet] -> ByteString-opgpStream = runPut . put . Block--armorData :: ByteString -> ByteString-armorData = BC8.unlines . wrap76 . Base64.encode--wrap76 :: ByteString -> [ByteString]-wrap76 bs- | B.null bs = []- | otherwise = B.take 76 bs : wrap76 (B.drop 76 bs)--armorChecksum :: ByteString -> ByteString-armorChecksum = BC8.cons '=' . armorData . B.tail . runPut . putWord32be . crc24
Codec/Encryption/OpenPGP/Serialize.hs view
@@ -7,7 +7,7 @@ ) where import Control.Applicative ((<$>),(<*>))-import Control.Monad (replicateM, mplus, when)+import Control.Monad (replicateM, mplus) import qualified Crypto.Cipher.RSA as R import qualified Crypto.Cipher.DSA as D import Data.Bits ((.&.), (.|.), shiftL, shiftR)@@ -428,8 +428,11 @@ pv <- getWord8 eokeyid <- getByteString 8 pkalgo <- getWord8- sk <- getByteString (len - 10)- return $ PKESK pv (EightOctetKeyId eokeyid) (toFVal pkalgo) sk+ remainder <- remaining+ mpib <- getBytes remainder+ case runGet (many getMPI) mpib of+ Left e -> error e+ Right sk -> return $ PKESK pv (EightOctetKeyId eokeyid) (toFVal pkalgo) sk | t == 2 = do remainder <- remaining bs <- getBytes remainder@@ -444,8 +447,11 @@ Simple _ -> 1 + 3 Salted _ _ -> 9 + 3 IteratedSalted _ _ _ -> 10 + 3- msk <- getMSK len partiallen- return $ SKESK pv (toFVal symalgo) s2k msk+ remainder <- remaining+ mpib <- getBytes remainder+ case runGet (many getMPI) mpib of+ Left _ -> return $ SKESK pv (toFVal symalgo) s2k []+ Right mpis -> return $ SKESK pv (toFVal symalgo) s2k mpis | t == 4 = do pv <- getWord8 sigtype <- getWord8@@ -514,14 +520,6 @@ | otherwise = do payload <- getByteString len return $ OtherPacket t payload- where- getMSK :: Int -> Int -> Get (Maybe SessionKey)- getMSK len partiallen- | len == partiallen = return Nothing- | len > partiallen = do- sk <- getByteString (len - partiallen)- return $ Just sk- | otherwise = error "Overread" getUserAttrSubPacket :: Get UserAttrSubPacket getUserAttrSubPacket = do@@ -560,9 +558,9 @@ putByteString bs putPacket :: Packet -> Put-putPacket (PKESK pv eokeyid pkalgo sk) = do+putPacket (PKESK pv eokeyid pkalgo mpis) = do putWord8 (0xc0 .|. 1)- let bsk = sk+ let bsk = runPut $ mapM_ put mpis putPacketLength $ 10 + (B.length bsk) putWord8 pv -- must be 3 putByteString (unEOKI eokeyid) -- must be 8 octets@@ -573,14 +571,15 @@ let bs = runPut $ put sp putPacketLength . B.length $ bs putByteString bs-putPacket (SKESK pv symalgo s2k msk) = do+putPacket (SKESK pv symalgo s2k mpis) = do putWord8 (0xc0 .|. 3) let bs2k = fromS2K s2k- putPacketLength $ 2 + (B.length bs2k) + (maybe 0 B.length msk)+ let bsk = runPut $ mapM_ put mpis+ putPacketLength $ 2 + (B.length bs2k) + (B.length bsk) putWord8 pv -- should be 4 putWord8 $ fromIntegral . fromFVal $ symalgo putByteString bs2k- when (isJust msk) $ putByteString (fromJust msk)+ putByteString bsk putPacket (OnePassSignature pv sigtype ha pka skeyid nested) = do putWord8 (0xc0 .|. 4) let bs = runPut $ do@@ -806,10 +805,266 @@ symEncBlockSize x = 8 -- FIXME decodeIterationCount :: Word8 -> Int-decodeIterationCount c = fromIntegral $ (16 + (c .&. 15)) `shiftL` ((fromIntegral c `shiftR` 4) + 6)+decodeIterationCount c = (16 + (fromIntegral c .&. 15)) `shiftL` ((fromIntegral c `shiftR` 4) + 6) -encodeIterationCount :: Int -> Word8-encodeIterationCount c = fromIntegral c -- FIXME+encodeIterationCount :: Int -> Word8 -- should this really be a lookup table?+encodeIterationCount 1024 = 0+encodeIterationCount 1088 = 1+encodeIterationCount 1152 = 2+encodeIterationCount 1216 = 3+encodeIterationCount 1280 = 4+encodeIterationCount 1344 = 5+encodeIterationCount 1408 = 6+encodeIterationCount 1472 = 7+encodeIterationCount 1536 = 8+encodeIterationCount 1600 = 9+encodeIterationCount 1664 = 10+encodeIterationCount 1728 = 11+encodeIterationCount 1792 = 12+encodeIterationCount 1856 = 13+encodeIterationCount 1920 = 14+encodeIterationCount 1984 = 15+encodeIterationCount 2048 = 16+encodeIterationCount 2176 = 17+encodeIterationCount 2304 = 18+encodeIterationCount 2432 = 19+encodeIterationCount 2560 = 20+encodeIterationCount 2688 = 21+encodeIterationCount 2816 = 22+encodeIterationCount 2944 = 23+encodeIterationCount 3072 = 24+encodeIterationCount 3200 = 25+encodeIterationCount 3328 = 26+encodeIterationCount 3456 = 27+encodeIterationCount 3584 = 28+encodeIterationCount 3712 = 29+encodeIterationCount 3840 = 30+encodeIterationCount 3968 = 31+encodeIterationCount 4096 = 32+encodeIterationCount 4352 = 33+encodeIterationCount 4608 = 34+encodeIterationCount 4864 = 35+encodeIterationCount 5120 = 36+encodeIterationCount 5376 = 37+encodeIterationCount 5632 = 38+encodeIterationCount 5888 = 39+encodeIterationCount 6144 = 40+encodeIterationCount 6400 = 41+encodeIterationCount 6656 = 42+encodeIterationCount 6912 = 43+encodeIterationCount 7168 = 44+encodeIterationCount 7424 = 45+encodeIterationCount 7680 = 46+encodeIterationCount 7936 = 47+encodeIterationCount 8192 = 48+encodeIterationCount 8704 = 49+encodeIterationCount 9216 = 50+encodeIterationCount 9728 = 51+encodeIterationCount 10240 = 52+encodeIterationCount 10752 = 53+encodeIterationCount 11264 = 54+encodeIterationCount 11776 = 55+encodeIterationCount 12288 = 56+encodeIterationCount 12800 = 57+encodeIterationCount 13312 = 58+encodeIterationCount 13824 = 59+encodeIterationCount 14336 = 60+encodeIterationCount 14848 = 61+encodeIterationCount 15360 = 62+encodeIterationCount 15872 = 63+encodeIterationCount 16384 = 64+encodeIterationCount 17408 = 65+encodeIterationCount 18432 = 66+encodeIterationCount 19456 = 67+encodeIterationCount 20480 = 68+encodeIterationCount 21504 = 69+encodeIterationCount 22528 = 70+encodeIterationCount 23552 = 71+encodeIterationCount 24576 = 72+encodeIterationCount 25600 = 73+encodeIterationCount 26624 = 74+encodeIterationCount 27648 = 75+encodeIterationCount 28672 = 76+encodeIterationCount 29696 = 77+encodeIterationCount 30720 = 78+encodeIterationCount 31744 = 79+encodeIterationCount 32768 = 80+encodeIterationCount 34816 = 81+encodeIterationCount 36864 = 82+encodeIterationCount 38912 = 83+encodeIterationCount 40960 = 84+encodeIterationCount 43008 = 85+encodeIterationCount 45056 = 86+encodeIterationCount 47104 = 87+encodeIterationCount 49152 = 88+encodeIterationCount 51200 = 89+encodeIterationCount 53248 = 90+encodeIterationCount 55296 = 91+encodeIterationCount 57344 = 92+encodeIterationCount 59392 = 93+encodeIterationCount 61440 = 94+encodeIterationCount 63488 = 95+encodeIterationCount 65536 = 96+encodeIterationCount 69632 = 97+encodeIterationCount 73728 = 98+encodeIterationCount 77824 = 99+encodeIterationCount 81920 = 100+encodeIterationCount 86016 = 101+encodeIterationCount 90112 = 102+encodeIterationCount 94208 = 103+encodeIterationCount 98304 = 104+encodeIterationCount 102400 = 105+encodeIterationCount 106496 = 106+encodeIterationCount 110592 = 107+encodeIterationCount 114688 = 108+encodeIterationCount 118784 = 109+encodeIterationCount 122880 = 110+encodeIterationCount 126976 = 111+encodeIterationCount 131072 = 112+encodeIterationCount 139264 = 113+encodeIterationCount 147456 = 114+encodeIterationCount 155648 = 115+encodeIterationCount 163840 = 116+encodeIterationCount 172032 = 117+encodeIterationCount 180224 = 118+encodeIterationCount 188416 = 119+encodeIterationCount 196608 = 120+encodeIterationCount 204800 = 121+encodeIterationCount 212992 = 122+encodeIterationCount 221184 = 123+encodeIterationCount 229376 = 124+encodeIterationCount 237568 = 125+encodeIterationCount 245760 = 126+encodeIterationCount 253952 = 127+encodeIterationCount 262144 = 128+encodeIterationCount 278528 = 129+encodeIterationCount 294912 = 130+encodeIterationCount 311296 = 131+encodeIterationCount 327680 = 132+encodeIterationCount 344064 = 133+encodeIterationCount 360448 = 134+encodeIterationCount 376832 = 135+encodeIterationCount 393216 = 136+encodeIterationCount 409600 = 137+encodeIterationCount 425984 = 138+encodeIterationCount 442368 = 139+encodeIterationCount 458752 = 140+encodeIterationCount 475136 = 141+encodeIterationCount 491520 = 142+encodeIterationCount 507904 = 143+encodeIterationCount 524288 = 144+encodeIterationCount 557056 = 145+encodeIterationCount 589824 = 146+encodeIterationCount 622592 = 147+encodeIterationCount 655360 = 148+encodeIterationCount 688128 = 149+encodeIterationCount 720896 = 150+encodeIterationCount 753664 = 151+encodeIterationCount 786432 = 152+encodeIterationCount 819200 = 153+encodeIterationCount 851968 = 154+encodeIterationCount 884736 = 155+encodeIterationCount 917504 = 156+encodeIterationCount 950272 = 157+encodeIterationCount 983040 = 158+encodeIterationCount 1015808 = 159+encodeIterationCount 1048576 = 160+encodeIterationCount 1114112 = 161+encodeIterationCount 1179648 = 162+encodeIterationCount 1245184 = 163+encodeIterationCount 1310720 = 164+encodeIterationCount 1376256 = 165+encodeIterationCount 1441792 = 166+encodeIterationCount 1507328 = 167+encodeIterationCount 1572864 = 168+encodeIterationCount 1638400 = 169+encodeIterationCount 1703936 = 170+encodeIterationCount 1769472 = 171+encodeIterationCount 1835008 = 172+encodeIterationCount 1900544 = 173+encodeIterationCount 1966080 = 174+encodeIterationCount 2031616 = 175+encodeIterationCount 2097152 = 176+encodeIterationCount 2228224 = 177+encodeIterationCount 2359296 = 178+encodeIterationCount 2490368 = 179+encodeIterationCount 2621440 = 180+encodeIterationCount 2752512 = 181+encodeIterationCount 2883584 = 182+encodeIterationCount 3014656 = 183+encodeIterationCount 3145728 = 184+encodeIterationCount 3276800 = 185+encodeIterationCount 3407872 = 186+encodeIterationCount 3538944 = 187+encodeIterationCount 3670016 = 188+encodeIterationCount 3801088 = 189+encodeIterationCount 3932160 = 190+encodeIterationCount 4063232 = 191+encodeIterationCount 4194304 = 192+encodeIterationCount 4456448 = 193+encodeIterationCount 4718592 = 194+encodeIterationCount 4980736 = 195+encodeIterationCount 5242880 = 196+encodeIterationCount 5505024 = 197+encodeIterationCount 5767168 = 198+encodeIterationCount 6029312 = 199+encodeIterationCount 6291456 = 200+encodeIterationCount 6553600 = 201+encodeIterationCount 6815744 = 202+encodeIterationCount 7077888 = 203+encodeIterationCount 7340032 = 204+encodeIterationCount 7602176 = 205+encodeIterationCount 7864320 = 206+encodeIterationCount 8126464 = 207+encodeIterationCount 8388608 = 208+encodeIterationCount 8912896 = 209+encodeIterationCount 9437184 = 210+encodeIterationCount 9961472 = 211+encodeIterationCount 10485760 = 212+encodeIterationCount 11010048 = 213+encodeIterationCount 11534336 = 214+encodeIterationCount 12058624 = 215+encodeIterationCount 12582912 = 216+encodeIterationCount 13107200 = 217+encodeIterationCount 13631488 = 218+encodeIterationCount 14155776 = 219+encodeIterationCount 14680064 = 220+encodeIterationCount 15204352 = 221+encodeIterationCount 15728640 = 222+encodeIterationCount 16252928 = 223+encodeIterationCount 16777216 = 224+encodeIterationCount 17825792 = 225+encodeIterationCount 18874368 = 226+encodeIterationCount 19922944 = 227+encodeIterationCount 20971520 = 228+encodeIterationCount 22020096 = 229+encodeIterationCount 23068672 = 230+encodeIterationCount 24117248 = 231+encodeIterationCount 25165824 = 232+encodeIterationCount 26214400 = 233+encodeIterationCount 27262976 = 234+encodeIterationCount 28311552 = 235+encodeIterationCount 29360128 = 236+encodeIterationCount 30408704 = 237+encodeIterationCount 31457280 = 238+encodeIterationCount 32505856 = 239+encodeIterationCount 33554432 = 240+encodeIterationCount 35651584 = 241+encodeIterationCount 37748736 = 242+encodeIterationCount 39845888 = 243+encodeIterationCount 41943040 = 244+encodeIterationCount 44040192 = 245+encodeIterationCount 46137344 = 246+encodeIterationCount 48234496 = 247+encodeIterationCount 50331648 = 248+encodeIterationCount 52428800 = 249+encodeIterationCount 54525952 = 250+encodeIterationCount 56623104 = 251+encodeIterationCount 58720256 = 252+encodeIterationCount 60817408 = 253+encodeIterationCount 62914560 = 254+encodeIterationCount 65011712 = 255+encodeIterationCount n = error "invalid iteration count" getSignaturePayload :: Get SignaturePayload getSignaturePayload = do
Codec/Encryption/OpenPGP/Types.hs view
@@ -19,18 +19,14 @@ , ImageFormat(..) , PKPayload(..) , SKAddendum(..)- , ArmorType(..)- , Armor(Armor) , DataType(..) , PKey(..) , SKey(..) , EightOctetKeyId(..) , TwentyOctetFingerprint(..)- , TK(..)- , SessionKey+ , KRK(..) , FutureFlag , FutureVal- , ArmorHeader , Keyring , fromFVal , fromFFlag@@ -68,7 +64,6 @@ type SignaturePacketBody = ByteString type SignatureHash = ByteString type PacketVersion = Word8-type SessionKey = ByteString type Salt = ByteString type Count = Int type V3Expiration = Word16@@ -426,9 +421,9 @@ toFVal 0x75 = UTF8Data toFVal o = OtherData o -data Packet = PKESK PacketVersion EightOctetKeyId PubKeyAlgorithm SessionKey+data Packet = PKESK PacketVersion EightOctetKeyId PubKeyAlgorithm [MPI] | Signature SignaturePayload- | SKESK PacketVersion SymmetricAlgorithm S2K (Maybe SessionKey)+ | SKESK PacketVersion SymmetricAlgorithm S2K [MPI] | OnePassSignature PacketVersion SigType HashAlgorithm PubKeyAlgorithm EightOctetKeyId NestedFlag | SecretKey PKPayload SKAddendum | PublicKey PKPayload@@ -535,19 +530,6 @@ toFVal 0x50 = ThirdPartyConfirmationSig toFVal o = OtherSig o -data ArmorType a = ArmorMessage- | ArmorPublicKeyBlock- | ArmorPrivateKeyBlock- | ArmorSplitMessage a a- | ArmorSplitMessageIndefinite a- | ArmorSignature- deriving (Show, Eq)--type ArmorHeader = (ByteString, ByteString)--data Armor a = Armor (ArmorType a) [ArmorHeader] [Packet]- deriving (Show, Eq)- data PKey = RSAPubKey RSA.PublicKey | DSAPubKey DSA.PublicKey | ElGamalPubKey [Integer]@@ -582,7 +564,7 @@ hexToW8s :: ReadS Word8 hexToW8s = concatMap readHex . splitEvery 2 . map toLower -data TK = TPK PKPayload [SignaturePayload] [(String, [SignaturePayload])] [([UserAttrSubPacket], [SignaturePayload])] [(PKPayload, SignaturePayload, Maybe SignaturePayload)] | TSK Packet [SignaturePayload] [(String, [SignaturePayload])] [([UserAttrSubPacket], [SignaturePayload])] [(Packet, SignaturePayload, Maybe SignaturePayload)] | NoTK+data KRK = TPK PKPayload [SignaturePayload] [(String, [SignaturePayload])] [([UserAttrSubPacket], [SignaturePayload])] [(PKPayload, SignaturePayload, Maybe SignaturePayload)] | TSK Packet [SignaturePayload] [(String, [SignaturePayload])] [([UserAttrSubPacket], [SignaturePayload])] [(Packet, SignaturePayload, Maybe SignaturePayload)] | NTSubkey Packet | NTSecretSubkey Packet | NoKRK deriving (Eq, Show) -type Keyring = Map EightOctetKeyId TK+type Keyring = Map EightOctetKeyId KRK
− Data/Conduit/Cereal/Temp.hs
@@ -1,31 +0,0 @@-module Data.Conduit.Cereal.Temp (conduitGet)-where--import Control.Exception (throw)-import Control.Monad.Trans-import qualified Data.ByteString as BS-import qualified Data.Conduit as DC-import Data.Conduit.Cereal-import Data.Serialize-import Data.Serialize.Get--conduitGet :: (DC.ResourceThrow m, Serialize output) => Get output -> DC.Conduit BS.ByteString m output-conduitGet f = do- let acceptable = case runGetPartial f BS.empty of- Data.Serialize.Fail s -> throw $ GetException s- Data.Serialize.Partial f -> True- Data.Serialize.Done _ _ -> throw GetDoesntConsumeInput- if acceptable then DC.conduitState BS.empty (push f) (close f) else undefined- where- push :: (DC.ResourceThrow m, Serialize a) => Get a -> BS.ByteString -> BS.ByteString -> DC.ResourceT m (DC.ConduitStateResult BS.ByteString BS.ByteString a)- push f state input = (\(as, bs) -> return $ DC.StateProducing bs as) (go f ([], state `BS.append` input))-- close :: (DC.ResourceThrow m, Serialize a) => Get a -> BS.ByteString -> DC.ResourceT m [a]- close f state = return []-- go :: Serialize a => Get a -> ([a], BS.ByteString) -> ([a], BS.ByteString)- go f (as, bs)- | BS.null bs = (as, bs)- | otherwise = case runGetState f bs 0 of- Left err -> (as, bs)- Right (a, b) -> go f (as ++ [a], b)
Data/Conduit/OpenPGP/Compression.hs view
@@ -1,4 +1,4 @@--- ASCIIArmor.hs: OpenPGP (RFC4880) ASCII armor implementation+-- Compression.hs: OpenPGP (RFC4880) compression conduits -- Copyright Ⓒ 2012 Clint Adams -- This software is released under the terms of the Expat (MIT) license. -- (See the LICENSE file).@@ -13,11 +13,11 @@ import Data.Conduit import qualified Data.Conduit.List as CL -conduitCompress :: ResourceThrow m => CompressionAlgorithm -> Conduit Packet m Packet+conduitCompress :: MonadThrow m => CompressionAlgorithm -> Conduit Packet m Packet conduitCompress algo = conduitState [] push (close algo) where push state input = return $ StateProducing (input : state) [] close algo state = return $ [compressPackets algo state] -conduitDecompress :: ResourceThrow m => Conduit Packet m Packet+conduitDecompress :: MonadThrow m => Conduit Packet m Packet conduitDecompress = CL.concatMap decompressPacket
Data/Conduit/OpenPGP/Keyring.hs view
@@ -4,7 +4,7 @@ -- (See the LICENSE file). module Data.Conduit.OpenPGP.Keyring (- conduitToTKs+ conduitToKRKs , sinkKeyringMap ) where @@ -20,8 +20,8 @@ data Phase = MainKey | Revs | Uids | UAts | Subs deriving (Eq, Ord, Show) -conduitToTKs :: Resource m => Conduit Packet m TK-conduitToTKs = conduitState (MainKey, NoTK) push close+conduitToKRKs :: MonadResource m => Conduit Packet m KRK+conduitToKRKs = conduitState (MainKey, NoKRK) push close where push state input = case (state, input) of ((MainKey, _), PublicKey pkp) -> return $ StateProducing (Revs, TPK pkp [] [] [] []) []@@ -31,14 +31,14 @@ ((Uids, TPK pkp revs uids uats subs), Signature s) -> return $ StateProducing (Uids, TPK pkp revs (addUidSig s uids) uats subs) [] ((Uids, TPK pkp revs uids uats subs), UserId u) -> return $ StateProducing (Uids, TPK pkp revs (uids ++ [(u, [])]) uats subs) [] ((Uids, TPK pkp revs uids uats subs), UserAttribute u) -> return $ StateProducing (UAts, TPK pkp revs uids [(u, [])] subs) []- ((Uids, TPK pkp revs uids uats subs), PublicSubkey p) -> return $ StateProducing (Subs, TPK pkp revs uids uats [(p, SigVOther 0 B.empty, Nothing)]) []+ ((Uids, TPK pkp revs uids uats subs), PublicSubkey p) -> return $ StateProducing (Subs, TPK pkp revs uids uats [(p, SigVOther 0 B.empty, Nothing)]) [NTSubkey (PublicSubkey p)] ((Uids, TPK pkp revs uids uats subs), PublicKey p) -> return $ StateProducing (Revs, TPK p [] [] [] []) [TPK pkp revs uids uats subs] ((UAts, TPK pkp revs uids uats subs), Signature s) -> return $ StateProducing (UAts, TPK pkp revs uids (addUAtSig s uats) subs) [] ((UAts, TPK pkp revs uids uats subs), UserAttribute u) -> return $ StateProducing (UAts, TPK pkp revs uids (uats ++ [(u, [])]) subs) [] ((UAts, TPK pkp revs uids uats subs), UserId u) -> return $ StateProducing (Uids, TPK pkp revs (uids ++ [(u, [])]) uats subs) []- ((UAts, TPK pkp revs uids uats subs), PublicSubkey p) -> return $ StateProducing (Subs, TPK pkp revs uids uats [(p, SigVOther 0 B.empty, Nothing)]) []+ ((UAts, TPK pkp revs uids uats subs), PublicSubkey p) -> return $ StateProducing (Subs, TPK pkp revs uids uats [(p, SigVOther 0 B.empty, Nothing)]) [NTSubkey (PublicSubkey p)] ((UAts, TPK pkp revs uids uats subs), PublicKey p) -> return $ StateProducing (Revs, TPK p [] [] [] []) [TPK pkp revs uids uats subs]- ((Subs, TPK pkp revs uids uats subs), PublicSubkey p) -> return $ StateProducing (Subs, TPK pkp revs uids uats (subs ++ [(p, SigVOther 0 B.empty, Nothing)])) []+ ((Subs, TPK pkp revs uids uats subs), PublicSubkey p) -> return $ StateProducing (Subs, TPK pkp revs uids uats (subs ++ [(p, SigVOther 0 B.empty, Nothing)])) [NTSubkey (PublicSubkey p)] ((Subs, TPK pkp revs uids uats subs), Signature s) -> case sType s of SubkeyBindingSig -> return $ StateProducing (Subs, TPK pkp revs uids uats (setBSig s subs)) [] SubkeyRevocationSig -> return $ StateProducing (Subs, TPK pkp revs uids uats (setRSig s subs)) []@@ -49,14 +49,14 @@ ((Uids, TSK skp revs uids uats subs), Signature s) -> return $ StateProducing (Uids, TSK skp revs (addUidSig s uids) uats subs) [] ((Uids, TSK skp revs uids uats subs), UserId u) -> return $ StateProducing (Uids, TSK skp revs (uids ++ [(u, [])]) uats subs) [] ((Uids, TSK skp revs uids uats subs), UserAttribute u) -> return $ StateProducing (UAts, TSK skp revs uids [(u, [])] subs) []- ((Uids, TSK skp revs uids uats subs), SecretSubkey p s) -> return $ StateProducing (Subs, TSK skp revs uids uats [(SecretSubkey p s, SigVOther 0 B.empty, Nothing)]) []+ ((Uids, TSK skp revs uids uats subs), SecretSubkey p s) -> return $ StateProducing (Subs, TSK skp revs uids uats [(SecretSubkey p s, SigVOther 0 B.empty, Nothing)]) [NTSecretSubkey (SecretSubkey p s)] ((Uids, TSK skp revs uids uats subs), SecretKey p s) -> return $ StateProducing (Revs, TSK (SecretKey p s) [] [] [] []) [TSK skp revs uids uats subs] ((UAts, TSK skp revs uids uats subs), Signature s) -> return $ StateProducing (UAts, TSK skp revs uids (addUAtSig s uats) subs) [] ((UAts, TSK skp revs uids uats subs), UserAttribute u) -> return $ StateProducing (UAts, TSK skp revs uids (uats ++ [(u, [])]) subs) [] ((UAts, TSK skp revs uids uats subs), UserId u) -> return $ StateProducing (Uids, TSK skp revs (uids ++ [(u, [])]) uats subs) []- ((UAts, TSK skp revs uids uats subs), SecretSubkey p s) -> return $ StateProducing (Subs, TSK skp revs uids uats [(SecretSubkey p s, SigVOther 0 B.empty, Nothing)]) []+ ((UAts, TSK skp revs uids uats subs), SecretSubkey p s) -> return $ StateProducing (Subs, TSK skp revs uids uats [(SecretSubkey p s, SigVOther 0 B.empty, Nothing)]) [NTSecretSubkey (SecretSubkey p s)] ((UAts, TSK skp revs uids uats subs), SecretKey p s) -> return $ StateProducing (Revs, TSK (SecretKey p s) [] [] [] []) [TSK skp revs uids uats subs]- ((Subs, TSK skp revs uids uats subs), SecretSubkey p s) -> return $ StateProducing (Subs, TSK skp revs uids uats (subs ++ [(SecretSubkey p s, SigVOther 0 B.empty, Nothing)])) []+ ((Subs, TSK skp revs uids uats subs), SecretSubkey p s) -> return $ StateProducing (Subs, TSK skp revs uids uats (subs ++ [(SecretSubkey p s, SigVOther 0 B.empty, Nothing)])) [NTSecretSubkey (SecretSubkey p s)] ((Subs, TSK skp revs uids uats subs), Signature s) -> case sType s of SubkeyBindingSig -> return $ StateProducing (Subs, TSK skp revs uids uats (setBSig s subs)) [] SubkeyRevocationSig -> return $ StateProducing (Subs, TSK skp revs uids uats (setRSig s subs)) []@@ -73,11 +73,13 @@ sType (SigV4 st _ _ _ _ _ _) = st -sinkKeyringMap :: Resource m => Sink TK m (Map EightOctetKeyId TK)+sinkKeyringMap :: MonadResource m => Sink KRK m (Map EightOctetKeyId KRK) sinkKeyringMap = sinkState Map.empty push close where- push :: Resource m => Map EightOctetKeyId TK -> TK -> ResourceT m (SinkStateResult (Map EightOctetKeyId TK) TK (Map EightOctetKeyId TK))+ push :: MonadResource m => Map EightOctetKeyId KRK -> KRK -> m (SinkStateResult (Map EightOctetKeyId KRK) KRK (Map EightOctetKeyId KRK)) push state input = return $ StateProcessing $ Map.insert (eok input) input state close state = return state eok (TPK pkp _ _ _ _) = eightOctetKeyID pkp eok (TSK (SecretKey p s) _ _ _ _) = eightOctetKeyID p+ eok (NTSubkey (PublicSubkey pkp)) = eightOctetKeyID pkp+ eok (NTSecretSubkey (SecretSubkey p s)) = eightOctetKeyID p
Data/Conduit/OpenPGP/Verify.hs view
@@ -40,7 +40,7 @@ , lastSubkey :: Packet } -conduitVerify :: Resource m => Keyring -> Conduit Packet m (Either String Bool)+conduitVerify :: MonadResource m => Keyring -> Conduit Packet m (Either String Bool) conduitVerify kr = conduitState (StreamState (Marker B.empty) (Marker B.empty) (Marker B.empty) (Marker B.empty) (Marker B.empty)) push close where push state ld@(LiteralData _ _ _ _) = return $ StateProducing (state { lastLD = ld }) []
− Data/Digest/CRC24.hs
@@ -1,25 +0,0 @@--- CRC24.hs: OpenPGP (RFC4880) CRC24 implementation--- Copyright Ⓒ 2012 Clint Adams--- This software is released under the terms of the Expat (MIT) license.--- (See the LICENSE file).--module Data.Digest.CRC24 (- crc24-) where--import Data.Bits (shiftL, (.&.), xor)-import Data.ByteString (ByteString)-import qualified Data.ByteString as B-import Data.Word (Word8, Word32)--crc24_init :: Word32-crc24_init = 0xB704CE--crc24_poly :: Word32-crc24_poly = 0x1864CFB--crc24_update :: Word32 -> Word8 -> Word32-crc24_update c b = (last . take 9 $ iterate (\x -> if (shiftL x 1) .&. 0x1000000 == 0x1000000 then shiftL x 1 `xor` crc24_poly else shiftL x 1) (c `xor` shiftL (fromIntegral b) 16)) .&. 0xFFFFFF--crc24 :: ByteString -> Word32-crc24 bs = B.foldl crc24_update crc24_init bs
hOpenPGP.cabal view
@@ -1,5 +1,5 @@ Name: hOpenPGP-Version: 0.2+Version: 0.3 Synopsis: native Haskell implementation of OpenPGP (RFC4880) Description: native Haskell implementation of OpenPGP (RFC4880) Homepage: http://floss.scru.org/hOpenPGP/@@ -95,6 +95,8 @@ , tests/data/msg1.asc , tests/data/uncompressed-ops-rsa.gpg , tests/data/uncompressed-ops-dsa.gpg+ , tests/data/uncompressed-ops-dsa-sha384.txt.gpg+ , tests/data/encryption.gpg Cabal-version: >= 1.10 @@ -102,18 +104,13 @@ Library Exposed-modules: Codec.Encryption.OpenPGP.Types , Codec.Encryption.OpenPGP.Serialize- , Codec.Encryption.OpenPGP.ASCIIArmor , Codec.Encryption.OpenPGP.Compression , Codec.Encryption.OpenPGP.Fingerprint , Data.Conduit.OpenPGP.Compression , Data.Conduit.OpenPGP.Keyring , Data.Conduit.OpenPGP.Verify- Other-Modules: Data.Digest.CRC24- , Codec.Encryption.OpenPGP.Internal- , Codec.Encryption.OpenPGP.ASCIIArmor.Decode- , Codec.Encryption.OpenPGP.ASCIIArmor.Encode+ Other-Modules: Codec.Encryption.OpenPGP.Internal , Codec.Encryption.OpenPGP.SerializeForSigs- , Data.Conduit.Cereal.Temp Build-depends: asn1-data , attoparsec , base > 4 && < 5@@ -121,12 +118,13 @@ , bytestring , bzlib , cereal- , cereal-conduit < 0.0.4- , conduit < 0.3.0+ , cereal-conduit > 0.0.6 && < 0.1+ , conduit > 0.4 && < 0.5 , containers , cryptocipher , cryptohash , mtl+ , openpgp-asciiarmor >= 0.1 , split , zlib default-language: Haskell2010@@ -142,17 +140,20 @@ , bytestring , bzlib , cereal- , cereal-conduit < 0.0.4- , conduit < 0.3.0+ , cereal-conduit > 0.0.6 && < 0.1+ , conduit > 0.4 && < 0.5 , containers , cryptocipher , cryptohash , mtl+ , openpgp-asciiarmor >= 0.1 , split , zlib , HUnit , test-framework , test-framework-hunit+ , exception-transformers > 0.3 && < 0.4+ , resourcet > 0.3 && < 0.4 default-language: Haskell2010 source-repository head
+ tests/data/encryption.gpg view
binary file changed (absent → 860 bytes)
+ tests/data/uncompressed-ops-dsa-sha384.txt.gpg view
binary file changed (absent → 150 bytes)
tests/suite.hs view
@@ -1,4 +1,5 @@ {-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE FlexibleContexts, UndecidableInstances #-} import Test.Framework (defaultMain, testGroup) import Test.Framework.Providers.HUnit@@ -6,18 +7,20 @@ import Test.HUnit import Codec.Encryption.OpenPGP.Serialize ()-import Codec.Encryption.OpenPGP.ASCIIArmor (armor, decodeArmor) import Codec.Encryption.OpenPGP.Compression (decompressPacket, compressPackets) import Codec.Encryption.OpenPGP.Fingerprint (eightOctetKeyID, fingerprint) import Codec.Encryption.OpenPGP.Types-import Data.Conduit.Cereal.Temp (conduitGet)+import Data.Conduit.Cereal (conduitGet) import Data.Conduit.OpenPGP.Compression (conduitCompress, conduitDecompress)-import Data.Conduit.OpenPGP.Keyring (conduitToTKs, sinkKeyringMap)+import Data.Conduit.OpenPGP.Keyring (conduitToKRKs, sinkKeyringMap) import Data.Conduit.OpenPGP.Verify (conduitVerify) -import Data.ByteString (ByteString)+import Control.Monad.Exception (runExceptionT, ExceptionT, throw)+import Control.Monad.Trans (lift)+import Control.Monad.Trans.Resource (release, allocate, register, resourceMask)+import Data.ByteString.Lazy (ByteString) import qualified Data.ByteString as B-import Data.Digest.CRC24 (crc24)+import qualified Data.ByteString.Lazy as BL import qualified Data.Map as Map import Data.Maybe (isJust) import Data.Serialize (get, put)@@ -29,6 +32,17 @@ import qualified Data.Conduit.Binary as CB import qualified Data.Conduit.List as CL +-- cope with instance problem for now+instance (DC.MonadResource m, DC.MonadThrow (ExceptionT m)) => DC.MonadResource (ExceptionT m) where+ allocate a = lift . allocate a+ register = lift . register+ release = lift . release+ resourceMask = lift . resourceMask++instance Monad a => DC.MonadThrow (ExceptionT a) where+ monadThrow = throw+--+ testSerialization :: FilePath -> Assertion testSerialization fp = do bs <- B.readFile $ "tests/data/" ++ fp@@ -43,19 +57,6 @@ else assertEqual ("for " ++ fp) firstpass secondpass -testCRC24 :: ByteString -> Word32 -> Assertion-testCRC24 bs crc = assertEqual "crc24" crc (crc24 bs)--testArmorDecode :: FilePath -> Armor Int -> Assertion-testArmorDecode fp target = do- bs <- B.readFile $ "tests/data/" ++ fp- case decodeArmor bs of- Left err -> assertFailure $ "Decode failed on " ++ fp- Right arm -> do assertEqual ("for " ++ fp) target arm--testArmorEncode :: Armor Int -> ByteString -> Assertion-testArmorEncode arm target = assertEqual ("literaldata") (armor arm) target- testCompression :: FilePath -> Assertion testCompression fp = do bs <- B.readFile $ "tests/data/" ++ fp@@ -70,10 +71,10 @@ else assertEqual ("for " ++ fp) firstpass secondpass -counter :: (DC.ResourceIO m) => DC.Sink a m Int+counter :: (DC.MonadResource m) => DC.Sink a m Int counter = CL.fold (const . (1+)) 0 -testConduitOutputLength :: FilePath -> DC.Conduit B.ByteString IO b -> Int -> Assertion+testConduitOutputLength :: FilePath -> DC.Conduit B.ByteString (DC.ResourceT IO) b -> Int -> Assertion testConduitOutputLength fp c target = do len <- DC.runResourceT $ CB.sourceFile ("tests/data/" ++ fp) DC.$= c DC.$$ counter assertEqual ("expected length" ++ show target) target len@@ -87,14 +88,26 @@ testKeyringLookup :: FilePath -> String -> Bool -> Assertion testKeyringLookup fp eok expected = do- kr <- DC.runResourceT $ CB.sourceFile ("tests/data/" ++ fp) DC.$= conduitGet get DC.$= conduitToTKs DC.$$ sinkKeyringMap- let key = (Map.lookup (read eok) kr)+ -- kr <- DC.runResourceT $ CB.sourceFile ("tests/data/" ++ fp) DC.$= conduitGet get DC.$= conduitToKRKs DC.$$ sinkKeyringMap+ -- let key = (Map.lookup (read eok) kr)+ kr <- DC.runResourceT $ runExceptionT $ (CB.sourceFile ("tests/data/" ++ fp) DC.$= conduitGet get DC.$= conduitToKRKs DC.$$ sinkKeyringMap :: ExceptionT (DC.ResourceT IO) (Map.Map EightOctetKeyId KRK))+ let key = case kr of+ Left e -> Nothing+ Right k -> Map.lookup (read eok) k assertEqual (eok ++ " in " ++ fp) expected (isJust key) testVerifyMessage :: FilePath -> FilePath -> Assertion testVerifyMessage keyring message = do- kr <- DC.runResourceT $ CB.sourceFile ("tests/data/" ++ keyring) DC.$= conduitGet get DC.$= conduitToTKs DC.$$ sinkKeyringMap- verification <- DC.runResourceT $ CB.sourceFile ("tests/data/" ++ message) DC.$= conduitGet get DC.$= conduitDecompress DC.$= conduitVerify kr DC.$$ CL.consume+ -- kr <- DC.runResourceT $ CB.sourceFile ("tests/data/" ++ keyring) DC.$= conduitGet get DC.$= conduitToKRKs DC.$$ sinkKeyringMap+ -- verification <- DC.runResourceT $ CB.sourceFile ("tests/data/" ++ message) DC.$= conduitGet get DC.$= conduitDecompress DC.$= conduitVerify kr DC.$$ CL.consume+ kring <- DC.runResourceT $ runExceptionT $ (CB.sourceFile ("tests/data/" ++ keyring) DC.$= conduitGet get DC.$= conduitToKRKs DC.$$ sinkKeyringMap :: ExceptionT (DC.ResourceT IO) (Map.Map EightOctetKeyId KRK))+ let kr = case kring of+ Left e -> Map.empty+ Right k -> k+ verif <- DC.runResourceT $ runExceptionT $ (CB.sourceFile ("tests/data/" ++ message) DC.$= conduitGet get DC.$= conduitDecompress DC.$= conduitVerify kr DC.$$ CL.consume :: ExceptionT (DC.ResourceT IO) [Either String Bool])+ let verification = case verif of+ Left e -> []+ Right xs -> xs assertEqual (keyring ++ " for " ++ message) ([Right True]) verification tests = [@@ -186,36 +199,13 @@ , testCase "uncompressed-ops-dsa.gpg" (testSerialization "uncompressed-ops-dsa.gpg") , testCase "uncompressed-ops-rsa.gpg" (testSerialization "uncompressed-ops-rsa.gpg") ],- testGroup "CRC24 group" [- testCase "CRC24: A" (testCRC24 "A" 16680698)- , testCase "CRC24: Haskell" (testCRC24 "Haskell" 15612750)- , testCase "CRC24: hOpenPGP and friends" (testCRC24 "hOpenPGP and friends" 11940960)- ],- testGroup "ASCII armor group" [- testCase "Decode sample armor" (testArmorDecode "msg1.asc" (Armor ArmorMessage [("Version","OpenPrivacy 0.99")] [CompressedData ZIP ";m\150\196\DC1\239\236\239\ETB\236\239\227\202\NUL\EOT\206\137y\234%\n\137y\149\249y\169\n\217\169\169\ENQ\n\137\n\197\169\201E\169@\193\162\252\210\188\DC4\133\140\212\162T{.\NUL"]))- , testCase "Encode sample armor" (testArmorEncode (Armor ArmorMessage [("Comment", "Test")] [LiteralData UTF8Data "notlob.txt" 12345 "These are the days of literal data.\n"]) "-----BEGIN PGP MESSAGE-----\nComment: Test\n\nyzR1Cm5vdGxvYi50eHQAADA5VGhlc2UgYXJlIHRoZSBkYXlzIG9mIGxpdGVyYWwgZGF0YS4K\n=AAKY\n-----END PGP MESSAGE-----\n")- ],- testGroup "Compression group" [- testCase "compressedsig.gpg" (testCompression "compressedsig.gpg")- , testCase "compressedsig-zlib.gpg" (testCompression "compressedsig-zlib.gpg")- , testCase "compressedsig-bzip2.gpg" (testCompression "compressedsig-bzip2.gpg")- ],- testGroup "Conduit group" [- testCase "compressedsig straight" (testConduitOutputLength "compressedsig.gpg" (conduitGet (get :: Get Packet)) 1)- , testCase "compressedsig uncompressed" (testConduitOutputLength "compressedsig.gpg" (conduitGet (get :: Get Packet) DC.=$= conduitDecompress) 3)- , testCase "pubring" (testConduitOutputLength "pubring.gpg" (conduitGet (get :: Get Packet)) 46)- ],- testGroup "Fingerprint group" [- testCase "000001-006.public_key" (testKeyIDandFingerprint "000001-006.public_key" "D4D54EA16F87040E/421F 28FE AAD2 22F8 56C8 FFD5 D4D5 4EA1 6F87 040E")- , testCase "000016-006.public_key" (testKeyIDandFingerprint "000016-006.public_key" "5E9F1523413262DC/AF95 E4D7 BAC5 21EE 9740 BED7 5E9F 1523 4132 62DC")- , testCase "000027-006.public_key" (testKeyIDandFingerprint "000027-006.public_key" "7732CF988A63EA86/1EB2 0B2F 5A5C C3BE AFD6 E5CB 7732 CF98 8A63 EA86")- , testCase "000035-006.public_key" (testKeyIDandFingerprint "000035-006.public_key" "DEDC3ECF689AF56D/CB79 3345 9F59 C70D F1C3 FBEE DEDC 3ECF 689A F56D")- ], testGroup "Keyring group" [ testCase "pubring 7732CF988A63EA86" (testKeyringLookup "pubring.gpg" "7732CF988A63EA86" True) , testCase "pubring 123456789ABCDEF0" (testKeyringLookup "pubring.gpg" "123456789ABCDEF0" False)+ , testCase "pubsub AD992E9C24399832" (testKeyringLookup "pubring.gpg" "AD992E9C24399832" True) , testCase "secring 7732CF988A63EA86" (testKeyringLookup "secring.gpg" "7732CF988A63EA86" True) , testCase "secring 123456789ABCDEF0" (testKeyringLookup "secring.gpg" "123456789ABCDEF0" False)+ , testCase "secsub AD992E9C24399832" (testKeyringLookup "secring.gpg" "AD992E9C24399832" True) -- FIXME: should count keys in rings ], testGroup "Message verification group" [