packages feed

hOpenPGP 0.14 → 1.0

raw patch · 11 files changed

+187/−134 lines, 11 filesdep +incremental-parserdep ~basePVP ok

version bump matches the API change (PVP)

Dependencies added: incremental-parser

Dependency ranges changed: base

API changes (from Hackage documentation)

- Codec.Encryption.OpenPGP.KeyInfo: keySize :: PKey -> Int
- Codec.Encryption.OpenPGP.Types: _tkPKP :: TK -> PKPayload
- Codec.Encryption.OpenPGP.Types: _tkmSKA :: TK -> Maybe SKAddendum
- Codec.Encryption.OpenPGP.Types: tkPKP :: Lens' TK PKPayload
- Codec.Encryption.OpenPGP.Types: tkmSKA :: Lens' TK (Maybe SKAddendum)
+ Codec.Encryption.OpenPGP.KeyInfo: pubkeySize :: PKey -> Either [Char] Int
+ Codec.Encryption.OpenPGP.Types: _tkKey :: TK -> (PKPayload, Maybe SKAddendum)
+ Codec.Encryption.OpenPGP.Types: instance Ord SKAddendum
+ Codec.Encryption.OpenPGP.Types: tkKey :: Lens' TK (PKPayload, Maybe SKAddendum)
- Codec.Encryption.OpenPGP.Types: TK :: PKPayload -> Maybe SKAddendum -> [SignaturePayload] -> [(String, [SignaturePayload])] -> [([UserAttrSubPacket], [SignaturePayload])] -> [(Pkt, SignaturePayload, Maybe SignaturePayload)] -> TK
+ Codec.Encryption.OpenPGP.Types: TK :: (PKPayload, Maybe SKAddendum) -> [SignaturePayload] -> [(String, [SignaturePayload])] -> [([UserAttrSubPacket], [SignaturePayload])] -> [(Pkt, [SignaturePayload])] -> TK
- Codec.Encryption.OpenPGP.Types: _tkSubs :: TK -> [(Pkt, SignaturePayload, Maybe SignaturePayload)]
+ Codec.Encryption.OpenPGP.Types: _tkSubs :: TK -> [(Pkt, [SignaturePayload])]
- Codec.Encryption.OpenPGP.Types: tkSubs :: Lens' TK [(Pkt, SignaturePayload, Maybe SignaturePayload)]
+ Codec.Encryption.OpenPGP.Types: tkSubs :: Lens' TK [(Pkt, [SignaturePayload])]

Files

Codec/Encryption/OpenPGP/Expirations.hs view
@@ -8,6 +8,7 @@  , getKeyExpirationTimesFromSignature ) where +import Control.Lens ((&), (^.), _1) import Data.List (sort) import Data.Time.Clock (UTCTime) import Data.Time.Clock.POSIX (posixSecondsToUTCTime)@@ -18,8 +19,8 @@ isTKTimeValid :: UTCTime -> TK -> Bool isTKTimeValid ct key = ct >= keyCreationTime && ct < keyExpirationTime     where-        keyCreationTime = posixSecondsToUTCTime . realToFrac . _timestamp . _tkPKP $ key-        keyExpirationTime = posixSecondsToUTCTime . realToFrac . ((+) (_timestamp . _tkPKP $ key)) . newest . concatMap getKeyExpirationTimesFromSignature $ (concatMap snd (_tkUIDs key) ++ concatMap snd (_tkUAts key))+        keyCreationTime = key^.tkKey._1.timestamp & posixSecondsToUTCTime . realToFrac+        keyExpirationTime = posixSecondsToUTCTime . realToFrac . ((+) (key^.tkKey._1.timestamp)) . newest . concatMap getKeyExpirationTimesFromSignature $ (concatMap snd (key^.tkUIDs) ++ concatMap snd (key^.tkUAts)) 	newest [] = maxBound 	newest xs = last (sort xs) 
Codec/Encryption/OpenPGP/Fingerprint.hs view
@@ -1,5 +1,5 @@ -- Fingerprint.hs: OpenPGP (RFC4880) fingerprinting methods--- Copyright © 2012-2013  Clint Adams+-- Copyright © 2012-2014  Clint Adams -- This software is released under the terms of the Expat license. -- (See the LICENSE file). @@ -21,7 +21,7 @@ eightOctetKeyID :: PKPayload -> EightOctetKeyId eightOctetKeyID (PKPayload DeprecatedV3 _ _ RSA (RSAPubKey rp)) = (EightOctetKeyId . B.reverse . B.take 4 . B.reverse . integerToBEBS . RSA.public_n) rp eightOctetKeyID p4@(PKPayload V4 _ _ _ _) = (EightOctetKeyId . B.drop 12 . unTOF . fingerprint) p4-eightOctetKeyID _ = error "This should never happen."+eightOctetKeyID _ = error "This should never happen (eightOctetKeyID)."  fingerprint :: PKPayload -> TwentyOctetFingerprint fingerprint p3@(PKPayload DeprecatedV3 _ _ _ _) = (TwentyOctetFingerprint . MD5.hash) (runPut $ putPKPforFingerprinting (PublicKeyPkt p3))
Codec/Encryption/OpenPGP/Internal.hs view
@@ -3,6 +3,8 @@ -- This software is released under the terms of the Expat license. -- (See the LICENSE file). +{-# LANGUAGE OverloadedStrings #-}+ module Codec.Encryption.OpenPGP.Internal (    countBits  , beBSToInteger@@ -31,7 +33,9 @@ import Codec.Encryption.OpenPGP.Types  countBits :: ByteString -> Word16-countBits bs = fromIntegral (B.length bs * 8) - fromIntegral (go (B.head bs) 7)+countBits bs+    | B.null bs = 0+    | otherwise = fromIntegral (B.length bs * 8) - fromIntegral (go (B.head bs) 7)     where         go :: Word8 -> Int -> Word8         go _ 0 = 7@@ -51,7 +55,7 @@                       }  emptyPSC :: PktStreamContext-emptyPSC = PktStreamContext (MarkerPkt B.empty) (MarkerPkt B.empty) (MarkerPkt B.empty) (MarkerPkt B.empty) (MarkerPkt B.empty)+emptyPSC = PktStreamContext (OtherPacketPkt 0 "lastLD placeholder") (OtherPacketPkt 0 "lastUIDorUAt placeholder") (OtherPacketPkt 0 "lastSig placeholder") (OtherPacketPkt 0 "lastPrimaryKey placeholder") (OtherPacketPkt 0 "lastSubkey placeholder")  issuer :: Pkt -> Maybe EightOctetKeyId issuer (SignaturePkt (SigV4 _ _ _ _ usubs _ _)) = fmap (\(SigSubPacket _ (Issuer i)) -> i) (find isIssuer usubs)@@ -60,15 +64,15 @@         isIssuer _ = False issuer _ = Nothing -hashDescr :: HashAlgorithm -> HashDescr-hashDescr SHA1 = hashDescrSHA1-hashDescr RIPEMD160 = hashDescrRIPEMD160-hashDescr SHA256 = hashDescrSHA256-hashDescr SHA384 = hashDescrSHA384-hashDescr SHA512 = hashDescrSHA512-hashDescr SHA224 = hashDescrSHA224-hashDescr DeprecatedMD5 = hashDescrMD5-hashDescr _ = error "Hash problem" -- FIXME+hashDescr :: HashAlgorithm -> Either String HashDescr+hashDescr SHA1 = Right hashDescrSHA1+hashDescr RIPEMD160 = Right hashDescrRIPEMD160+hashDescr SHA256 = Right hashDescrSHA256+hashDescr SHA384 = Right hashDescrSHA384+hashDescr SHA512 = Right hashDescrSHA512+hashDescr SHA224 = Right hashDescrSHA224+hashDescr DeprecatedMD5 = Right hashDescrMD5+hashDescr x = Left $ "Unknown hash problem: " ++ show x  pubkeyToMPIs :: PKey -> [MPI] pubkeyToMPIs (RSAPubKey k) = [MPI (RSA.public_n k), MPI (RSA.public_e k)]
Codec/Encryption/OpenPGP/KeyInfo.hs view
@@ -1,10 +1,10 @@ -- KeyInfo.hs: OpenPGP (RFC4880) fingerprinting methods--- Copyright © 2012-2013  Clint Adams+-- Copyright © 2012-2014  Clint Adams -- This software is released under the terms of the Expat license. -- (See the LICENSE file).  module Codec.Encryption.OpenPGP.KeyInfo (-   keySize+   pubkeySize  , pkalgoAbbrev ) where @@ -18,9 +18,10 @@  import Codec.Encryption.OpenPGP.Types -keySize (RSAPubKey x) = RSA.public_size x * 8-keySize (DSAPubKey x) = bitcount . DSA.params_p . DSA.public_params $ x-keySize (ElGamalPubKey x) = bitcount $ head x+pubkeySize (RSAPubKey x) = Right (RSA.public_size x * 8)+pubkeySize (DSAPubKey x) = Right (bitcount . DSA.params_p . DSA.public_params $ x)+pubkeySize (ElGamalPubKey x) = Right (bitcount $ head x)+pubkeySize x = Left $ "Unable to calculate size of " ++ show x  bitcount = (*8) . length . unfoldr (\x -> if x == 0 then Nothing else Just (True, x `shiftR` 8)) 
Codec/Encryption/OpenPGP/Serialize.hs view
@@ -496,12 +496,12 @@                        3 -> do len <- remaining                                bs <- getByteString len                                return (t, bs)-                       _ -> error "This should never happen."+                       _ -> error "This should never happen (getPacketTypeAndPayload/0x00)."         0x40 -> do                    len <- fmap fromIntegral getPacketLength                    bs <- getByteString len                    return (tag .&. 0x3f, bs)-        _ -> error "This should never happen."+        _ -> error "This should never happen (getPacketTypeAndPayload/???)."  getPkt :: Get Pkt getPkt = do
Codec/Encryption/OpenPGP/SerializeForSigs.hs view
@@ -1,5 +1,5 @@ -- SerializeForSigs.hs: OpenPGP (RFC4880) special serialization for signature purposes--- Copyright © 2012-2013  Clint Adams+-- Copyright © 2012-2014  Clint Adams -- This software is released under the terms of the Expat license. -- (See the LICENSE file). @@ -34,7 +34,7 @@     let bs = runPut $ put pkp     putWord16be . fromIntegral $ B.length bs     putByteString bs-putPKPforFingerprinting _ = fail "This should never happen"+putPKPforFingerprinting _ = fail "This should never happen (putPKPforFingerprinting)"  putMPIforFingerprinting:: MPI -> Put putMPIforFingerprinting(MPI i) = let bs = integerToBEBS i in putByteString bs@@ -48,7 +48,7 @@     let hb = runPut $ mapM_ put hashed     putWord16be . fromIntegral . B.length $ hb     putByteString hb-putPartialSigforSigning _ = fail "This should never happen"+putPartialSigforSigning _ = fail "This should never happen (putPartialSigforSigning)"  putSigTrailer :: Pkt -> Put putSigTrailer (SignaturePkt (SigV4 _ _ _ hs _ _ _)) = do@@ -56,12 +56,12 @@             putWord8 0xff             putWord32be . fromIntegral . (+6) . B.length $ runPut $ mapM_ put hs             -- this +6 seems like a bug in RFC4880-putSigTrailer _ = fail "This should never happen"+putSigTrailer _ = fail "This should never happen (putSigTrailer)"  putUforSigning :: Pkt -> Put putUforSigning u@(UserIdPkt _) = putUIDforSigning u putUforSigning u@(UserAttributePkt _) = putUAtforSigning u-putUforSigning _ = fail "This should never happen"+putUforSigning _ = fail "This should never happen (putUforSigning)"  putUIDforSigning :: Pkt -> Put putUIDforSigning (UserIdPkt u) = do@@ -69,7 +69,7 @@     let bs = encodeUtf8 . T.pack $ u     putWord32be . fromIntegral . B.length $ bs     putByteString bs-putUIDforSigning _ = fail "This should never happen"+putUIDforSigning _ = fail "This should never happen (putUIDforSigning)"  putUAtforSigning :: Pkt -> Put putUAtforSigning (UserAttributePkt us) = do@@ -77,7 +77,7 @@     let bs = runPut (mapM_ put us)     putWord32be . fromIntegral . B.length $ bs     putByteString bs-putUAtforSigning _ = fail "This should never happen"+putUAtforSigning _ = fail "This should never happen (putUAtforSigning)"  putSigforSigning :: Pkt -> Put putSigforSigning (SignaturePkt (SigV4 st pka ha hashed _ left16 mpis)) = do@@ -92,7 +92,7 @@ putKeyforSigning (PublicSubkeyPkt pkp) = putKeyForSigning' pkp putKeyforSigning (SecretKeyPkt pkp _) = putKeyForSigning' pkp putKeyforSigning (SecretSubkeyPkt pkp _) = putKeyForSigning' pkp-putKeyforSigning _ = fail "This should never happen"+putKeyforSigning x = fail ("This should never happen (putKeyforSigning) " ++ show (pktTag x) ++ "/" ++ show x)  putKeyForSigning' :: PKPayload -> Put putKeyForSigning' pkp = do
Codec/Encryption/OpenPGP/Signatures.hs view
@@ -10,7 +10,8 @@  , verifyTKWith ) where -import Control.Monad (guard, liftM2)+import Control.Lens ((^.), _1)+import Control.Monad (liftM2)  import Crypto.PubKey.HashDescr (HashDescr(..)) import qualified Crypto.PubKey.DSA as DSA@@ -34,46 +35,50 @@ verifySigWith :: (Pkt -> Maybe UTCTime -> ByteString -> Either String Verification) -> Pkt -> PktStreamContext -> Maybe UTCTime -> Either String Verification -- FIXME: check expiration here? verifySigWith vf sig@(SignaturePkt (SigV4 st _ _ hs _ _ _)) state mt = do     v <- vf sig mt (payloadForSig st state)-    _ <- mapM_ (checkIssuer (eightOctetKeyID (_verificationSigner v)) . _sspPayload) hs+    _ <- mapM_ (checkIssuer (eightOctetKeyID (v^.verificationSigner)) . _sspPayload) hs     return v     where         checkIssuer :: EightOctetKeyId -> SigSubPacketPayload -> Either String Bool         checkIssuer signer (Issuer i) = if signer == i then Right True else Left "issuer subpacket does not match"         checkIssuer _ _ = Right True-verifySigWith _ _ _ _ = Left "This should never happen."+verifySigWith _ _ _ _ = Left "This should never happen (verifySigWith)."  verifyTKWith :: (Pkt -> PktStreamContext -> Maybe UTCTime -> Either String Verification) -> Maybe UTCTime -> TK -> Either String TK verifyTKWith vsf mt key = do     revokers <- checkRevokers key     revs <- checkKeyRevocations revokers key-    let uids = filter (\(_, sps) -> sps /= []) . checkUidSigs $ _tkUIDs key -- FIXME: check revocations here?-    let uats = filter (\(_, sps) -> sps /= []) . checkUAtSigs $ _tkUAts key -- FIXME: check revocations here?-    let subs = concatMap checkSub $ _tkSubs key -- FIXME: check revocations here?-    return (TK (_tkPKP key) (_tkmSKA key) revs uids uats subs)+    let uids = filter (\(_, sps) -> sps /= []) . checkUidSigs $ key^.tkUIDs -- FIXME: check revocations here?+    let uats = filter (\(_, sps) -> sps /= []) . checkUAtSigs $ key^.tkUAts -- FIXME: check revocations here?+    let subs = concatMap checkSub $ key^.tkSubs -- FIXME: check revocations here?+    return (TK (key^.tkKey) revs uids uats subs)     where         checkRevokers = Right . concat . rights . map verifyRevoker . filter isRevokerP . _tkRevs         checkKeyRevocations :: [(PubKeyAlgorithm, TwentyOctetFingerprint)] -> TK -> Either String [SignaturePayload]-        checkKeyRevocations rs k = Prelude.sequence . concatMap (filterRevs rs) . rights . map (liftM2 fmap (,) vSig) . _tkRevs $ k+        checkKeyRevocations rs k = Prelude.sequence . concatMap (filterRevs rs) . rights . map (liftM2 fmap (,) vSig) $ k^.tkRevs         checkUidSigs :: [(String, [SignaturePayload])] -> [(String, [SignaturePayload])]         checkUidSigs = map (\(uid, sps) -> (uid, (rights . map (\sp -> fmap (const sp) (vUid (uid, sp)))) sps))         checkUAtSigs :: [([UserAttrSubPacket], [SignaturePayload])] -> [([UserAttrSubPacket], [SignaturePayload])]         checkUAtSigs = map (\(uat, sps) -> (uat, (rights . map (\sp -> fmap (const sp) (vUAt (uat, sp)))) sps))-        checkSub :: (Pkt, SignaturePayload, Maybe SignaturePayload) -> [(Pkt, SignaturePayload, Maybe SignaturePayload)]-        checkSub (pkt, sp, mrp) = if revokedSub pkt mrp then [] else checkSub' pkt sp-        revokedSub :: Pkt -> Maybe SignaturePayload -> Bool-        revokedSub _ Nothing = False-        revokedSub p (Just rp) = vSubSig p rp-        checkSub' :: Pkt -> SignaturePayload -> [(Pkt, SignaturePayload, Maybe SignaturePayload)]-        checkSub' p sp = guard (vSubSig p sp) >> return (p, sp, Nothing)+        checkSub :: (Pkt, [SignaturePayload]) -> [(Pkt, [SignaturePayload])]+        checkSub (pkt, sps) = if revokedSub pkt sps then [] else checkSub' pkt sps+        revokedSub :: Pkt -> [SignaturePayload] -> Bool+        revokedSub _ [] = False+        revokedSub p sigs = any (vSubSig p) (filter isSubkeyRevocation sigs)+        checkSub' :: Pkt -> [SignaturePayload] -> [(Pkt, [SignaturePayload])]+        checkSub' p sps = let goodsigs = filter (vSubSig p) (filter isSubkeyBindingSig sps) in if null goodsigs then [] else [(p, goodsigs)]         getHasheds (SigV4 _ _ _ ha _ _ _) = ha         getHasheds _ = [] 	filterRevs :: [(PubKeyAlgorithm, TwentyOctetFingerprint)] -> (SignaturePayload, Verification) -> [Either String SignaturePayload] 	filterRevs vokers spv = case spv of                                      (s@(SigV4 SignatureDirectlyOnAKey _ _ _ _ _ _), _) -> [Right s]-                                     (s@(SigV4 KeyRevocationSig pka _ _ _ _ _), v) -> if (_verificationSigner v == _tkPKP key) || any (\(p,f) -> p == pka && f == fingerprint (_verificationSigner v)) vokers then [Left "Key revoked"] else [Right s]+                                     (s@(SigV4 KeyRevocationSig pka _ _ _ _ _), v) -> if (v^.verificationSigner == key ^. tkKey._1) || any (\(p,f) -> p == pka && f == fingerprint (v^.verificationSigner)) vokers then [Left "Key revoked"] else [Right s] 				     _ -> []         isKeyRevocation (SigV4 KeyRevocationSig _ _ _ _ _ _) = True         isKeyRevocation _ = False+        isSubkeyRevocation (SigV4 SubkeyRevocationSig _ _ _ _ _ _) = True+        isSubkeyRevocation _ = False+        isSubkeyBindingSig (SigV4 SubkeyBindingSig _ _ _ _ _ _) = True+        isSubkeyBindingSig _ = False         isRevokerP (SigV4 SignatureDirectlyOnAKey _ _ h u _ _) = any isRevocationKeySSP h && any isIssuerSSP u         isRevokerP _ = False         isRevocationKeySSP (SigSubPacket _ (RevocationKey {})) = True@@ -81,13 +86,13 @@         isIssuerSSP (SigSubPacket _ (Issuer _)) = True         isIssuerSSP _ = False         vUid :: (String, SignaturePayload) -> Either String Verification-        vUid (uid, sp) = vsf (SignaturePkt sp) emptyPSC { lastPrimaryKey = PublicKeyPkt (_tkPKP key), lastUIDorUAt = UserIdPkt uid } mt+        vUid (uid, sp) = vsf (SignaturePkt sp) emptyPSC { lastPrimaryKey = PublicKeyPkt (key ^. tkKey._1), lastUIDorUAt = UserIdPkt uid } mt         vUAt :: ([UserAttrSubPacket], SignaturePayload) -> Either String Verification-        vUAt (uat, sp) = vsf (SignaturePkt sp) emptyPSC { lastPrimaryKey = PublicKeyPkt (_tkPKP key), lastUIDorUAt = UserAttributePkt uat } mt+        vUAt (uat, sp) = vsf (SignaturePkt sp) emptyPSC { lastPrimaryKey = PublicKeyPkt (key ^. tkKey._1), lastUIDorUAt = UserAttributePkt uat } mt         vSig :: SignaturePayload -> Either String Verification-        vSig sp = vsf (SignaturePkt sp) emptyPSC { lastPrimaryKey = PublicKeyPkt (_tkPKP key) } mt+        vSig sp = vsf (SignaturePkt sp) emptyPSC { lastPrimaryKey = PublicKeyPkt (key ^. tkKey._1) } mt         vSubSig :: Pkt -> SignaturePayload -> Bool-        vSubSig sk sp = case vsf (SignaturePkt sp) emptyPSC { lastPrimaryKey = PublicKeyPkt (_tkPKP key), lastSubkey = sk} mt of+        vSubSig sk sp = case vsf (SignaturePkt sp) emptyPSC { lastPrimaryKey = PublicKeyPkt (key ^. tkKey._1), lastSubkey = sk} mt of                                 Left _ -> False 				Right _ -> True         verifyRevoker :: SignaturePayload -> Either String [(PubKeyAlgorithm, TwentyOctetFingerprint)]@@ -103,7 +108,7 @@  verifyAgainstKeys :: [TK] -> Pkt -> Maybe UTCTime -> ByteString -> Either String Verification verifyAgainstKeys ks sig mt payload = do-    let allrelevantpkps = filter (\x -> issuer sig == Just (eightOctetKeyID x)) (concatMap (\x -> _tkPKP x:map subPKP (_tkSubs x)) ks)+    let allrelevantpkps = filter (\x -> issuer sig == Just (eightOctetKeyID x)) (concatMap (\x -> (x ^. tkKey._1):map subPKP (_tkSubs x)) ks)     let results = map (\pkp -> verify' sig pkp (hashalgo sig) (finalPayload sig payload)) allrelevantpkps     case rights results of         [] -> Left (concatMap (++"/") (lefts results))@@ -111,26 +116,28 @@ 	          return (Verification r ((_signaturePayload . fromPkt) sig)) -- FIXME: this should also check expiration time and flags of the signing key         _ -> Left "multiple successes; unexpected condition"     where-        subPKP (pack, _, _) = subPKP' pack+        subPKP (pack, _) = subPKP' pack         subPKP' (PublicSubkeyPkt p) = p         subPKP' (SecretSubkeyPkt p _) = p         verify' (SignaturePkt s) (pub@(PKPayload V4 _ _ _ pkey)) ha pl = verify'' (pkaAndMPIs s) ha pub pkey pl-        verify' _ _ _ _ = error "This should never happen."-        verify'' (DSA,mpis) ha pub (DSAPubKey pkey) bs = verify''' (dsaVerify mpis ha pkey bs) pub-        verify'' (RSA,mpis) ha pub (RSAPubKey pkey) bs = verify''' (rsaVerify mpis ha pkey bs) pub+        verify' _ _ _ _ = error "This should never happen (verify')."+        verify'' (DSA,mpis) ha pub (DSAPubKey pkey) bs = verify''' (dsaVerify mpis (hashDescr ha) pkey bs) pub+        verify'' (RSA,mpis) ha pub (RSAPubKey pkey) bs = verify''' (rsaVerify mpis (hashDescr ha) pkey bs) pub         verify'' _ _ _ _ _ = Left "unimplemented key type" 	verify''' f pub = if f then Right pub else Left "verification failed"-	dsaVerify mpis ha pkey = DSA.verify (dsaTruncate pkey . hashFunction (hashDescr ha)) pkey (dsaMPIsToSig mpis)-	rsaVerify mpis ha pkey bs = P15.verify (hashDescr ha) pkey bs (rsaMPItoSig mpis)+	dsaVerify mpis (Right hd) pkey = DSA.verify (dsaTruncate pkey . hashFunction hd) pkey (dsaMPIsToSig mpis)+	dsaVerify _ (Left _) _ = const False  -- FIXME: this should be some sort of Either chain+	rsaVerify mpis (Right hd) pkey bs = P15.verify hd pkey bs (rsaMPItoSig mpis)+	rsaVerify _ (Left _) _ _ = False  -- FIXME: this should be some sort of Either chain         dsaMPIsToSig mpis = DSA.Signature (unMPI (head mpis)) (unMPI (mpis !! 1))         rsaMPItoSig mpis = integerToBEBS (unMPI (head mpis))         hashalgo :: Pkt -> HashAlgorithm         hashalgo (SignaturePkt (SigV4 _ _ ha _ _ _ _)) = ha-        hashalgo _ = error "This should never happen."+        hashalgo _ = error "This should never happen (hashalgo)."         dsaTruncate pkey bs = if countBits bs > dsaQLen pkey then B.take (fromIntegral (dsaQLen pkey) `div` 8) bs else bs -- FIXME: uneven bits         dsaQLen = countBits . integerToBEBS . DSA.params_q . DSA.public_params 	pkaAndMPIs (SigV4 _ pka _ _ _ _ mpis) = (pka,mpis)-	pkaAndMPIs _ = error "This should never happen."+	pkaAndMPIs _ = error "This should never happen (pkaAndMPIs)."         isSignatureExpired :: Pkt -> Maybe UTCTime -> Either String Bool         isSignatureExpired s Nothing = return False         isSignatureExpired s (Just t) = if any (expiredBefore t) ((\(SigV4 _ _ _ h _ _ _) -> h) . _signaturePayload . fromPkt $ s) then Left "signature expired" else return True
Codec/Encryption/OpenPGP/Types.hs view
@@ -394,6 +394,9 @@                 | SUUnencrypted SKey Word16     deriving (Data, Eq, Show, Typeable) +instance Ord SKAddendum where+    compare a b = show a `compare` show b -- FIXME: this is ridiculous+ data DataType = BinaryData               | TextData               | UTF8Data@@ -549,16 +552,15 @@ hexToW8s = concatMap readHex . chunksOf 2 . map toLower  data TK = TK {-    _tkPKP :: PKPayload-  , _tkmSKA :: Maybe SKAddendum+    _tkKey  :: (PKPayload, Maybe SKAddendum)   , _tkRevs :: [SignaturePayload]   , _tkUIDs :: [(String, [SignaturePayload])]   , _tkUAts :: [([UserAttrSubPacket], [SignaturePayload])]-  , _tkSubs :: [(Pkt, SignaturePayload, Maybe SignaturePayload)]+  , _tkSubs :: [(Pkt, [SignaturePayload])]   } deriving (Data, Eq, Show, Typeable)  instance Ord TK where-    compare = comparing _tkPKP -- FIXME: is this ridiculous?+    compare = comparing _tkKey -- FIXME: is this ridiculous?  type Keyring = IxSet TK 
Data/Conduit/OpenPGP/Filter.hs view
@@ -21,12 +21,14 @@  , OValue(..) ) where +import Control.Error.Util (hush) import qualified Data.ByteString as B import Data.Conduit import qualified Data.Conduit.List as CL+import Data.Maybe (fromMaybe)  import Codec.Encryption.OpenPGP.Internal (sigType, sigPKA, sigHA)-import Codec.Encryption.OpenPGP.KeyInfo (keySize)+import Codec.Encryption.OpenPGP.KeyInfo (pubkeySize) import Codec.Encryption.OpenPGP.Types  data FilterPredicates = FilterPredicates {@@ -122,7 +124,7 @@         opreduce PKGreaterThan = (>)         vreduce (PKPVVersion, p) = PKPInt (kv (_keyVersion p))         vreduce (PKPVPKA, p) = PKPPKA (_pkalgo p)-        vreduce (PKPVKeysize, p) = PKPInt (keySize . _pubkey $ p)+        vreduce (PKPVKeysize, p) = PKPInt (fromMaybe 0 . hush . pubkeySize . _pubkey $ p) -- FIXME: a Left here should invalidate the predicate or something         vreduce (PKPVTimestamp, p) = PKPInt (fromIntegral (_timestamp p)) 	kv DeprecatedV3 = 3 	kv V4 = 4
Data/Conduit/OpenPGP/Keyring.hs view
@@ -9,15 +9,15 @@  , sinkKeyringMap ) where -import qualified Data.ByteString as B+import Control.Applicative (many, some, (<$>), (<*>), (<|>), (<*)) import Data.Conduit import qualified Data.Conduit.List as CL import Data.IxSet (empty, insert)-import Data.Foldable (traverse_)+import Data.Monoid (Monoid, (<>), mconcat) -import Codec.Encryption.OpenPGP.Internal (sigType) import Codec.Encryption.OpenPGP.Types import Data.Conduit.OpenPGP.Keyring.Instances ()+import Text.ParserCombinators.Incremental.LeftBiasedLocal (concatMany, feed, feedEof, inspect, satisfy, Parser)  data Phase = MainKey | Revs | Uids | UAts | Subs | SkippingBroken     deriving (Eq, Ord, Show)@@ -28,81 +28,115 @@ conduitToTKsDropping :: MonadResource m => Conduit Pkt m TK conduitToTKsDropping = conduitToTKs' False -fakecmAccum :: Monad m => (a -> (Phase, Maybe TK) -> ((Phase, Maybe TK), [TK])) -> (Phase, Maybe TK) -> Conduit a m TK-fakecmAccum f =+fakecmAccum :: Monad m => (accum -> (accum, [b])) -> (a -> accum -> (accum, [b])) -> accum -> Conduit a m b+fakecmAccum finalizer f =     loop   where     loop accum =-        await >>= maybe (finalyield accum) go+        await >>= maybe (Prelude.mapM_ yield (snd (finalizer accum))) go       where         go a = do             let (accum', bs) = f a accum             Prelude.mapM_ yield bs             loop accum'-        finalyield = traverse_ yield . snd  conduitToTKs' :: MonadResource m => Bool -> Conduit Pkt m TK-conduitToTKs' intolerant = fakecmAccum push (MainKey, Nothing)+conduitToTKs' intolerant = CL.filter notTrustPacket =$= CL.map (:[]) =$= fakecmAccum finalizeParsing (parseAChunk (parseTK intolerant)) ([], Just (Nothing, parseTK intolerant)) =$= CL.catMaybes     where-        push i s = case (s, i) of-                       ((MainKey, _), PublicKeyPkt pkp) -> ((Revs, Just (TK pkp Nothing [] [] [] [])), [])-                       ((MainKey, _), SecretKeyPkt pkp ska) -> ((Revs, Just (TK pkp (Just ska) [] [] [] [])), [])-                       ((MainKey, _), BrokenPacketPkt _ 6 _) -> ((SkippingBroken, Nothing), [])-                       ((MainKey, _), BrokenPacketPkt _ 5 _) -> ((SkippingBroken, Nothing), [])-                       ((Revs, Just (TK pkp Nothing revs uids uats subs)), SignaturePkt sp) -> ((Revs, Just (TK pkp Nothing (revs ++ [sp]) uids uats subs)), [])-                       ((Revs, Just (TK pkp Nothing revs _ uats subs)), UserIdPkt u) -> ((Uids, Just (TK pkp Nothing revs [(u, [])] uats subs)), [])-                       ((Uids, Just (TK pkp Nothing revs uids uats subs)), SignaturePkt sp) -> ((Uids, Just (TK pkp Nothing revs (addUidSig sp uids) uats subs)), [])-                       ((Uids, Just (TK pkp Nothing revs uids uats subs)), UserIdPkt u) -> ((Uids, Just (TK pkp Nothing revs (uids ++ [(u, [])]) uats subs)), [])-                       ((Uids, Just (TK pkp Nothing revs uids _ subs)), UserAttributePkt u) -> ((UAts, Just (TK pkp Nothing revs uids [(u, [])] subs)), [])-                       ((Uids, Just (TK pkp Nothing revs uids uats _)), PublicSubkeyPkt p) -> ((Subs, Just (TK pkp Nothing revs uids uats [(PublicSubkeyPkt p, SigVOther 0 B.empty, Nothing)])), [])-                       ((Uids, Just (TK pkp Nothing revs uids uats subs)), PublicKeyPkt p) -> ((Revs, Just (TK p Nothing [] [] [] [])), [TK pkp Nothing revs uids uats subs])-                       ((Uids, Just (TK pkp Nothing revs uids uats subs)), BrokenPacketPkt _ 6 _) -> ((SkippingBroken, Nothing), [TK pkp Nothing revs uids uats subs])-                       ((UAts, Just (TK pkp Nothing revs uids uats subs)), SignaturePkt sp) -> ((UAts, Just (TK pkp Nothing revs uids (addUAtSig sp uats) subs)), [])-                       ((UAts, Just (TK pkp Nothing revs uids uats subs)), UserAttributePkt u) -> ((UAts, Just (TK pkp Nothing revs uids (uats ++ [(u, [])]) subs)), [])-                       ((UAts, Just (TK pkp Nothing revs uids uats subs)), UserIdPkt u) -> ((Uids, Just (TK pkp Nothing revs (uids ++ [(u, [])]) uats subs)), [])-                       ((UAts, Just (TK pkp Nothing revs uids uats _)), PublicSubkeyPkt p) -> ((Subs, Just (TK pkp Nothing revs uids uats [(PublicSubkeyPkt p, SigVOther 0 B.empty, Nothing)])), [])-                       ((UAts, Just (TK pkp Nothing revs uids uats subs)), PublicKeyPkt p) -> ((Revs, Just (TK p Nothing [] [] [] [])), [TK pkp Nothing revs uids uats subs])-                       ((UAts, Just (TK pkp Nothing revs uids uats subs)), BrokenPacketPkt _ 6 _) -> ((SkippingBroken, Nothing), [TK pkp Nothing revs uids uats subs])-                       ((Subs, Just (TK pkp Nothing revs uids uats subs)), PublicSubkeyPkt p) -> ((Subs, Just (TK pkp Nothing revs uids uats (subs ++ [(PublicSubkeyPkt p, SigVOther 0 B.empty, Nothing)]))), [])-                       ((Subs, Just (TK pkp Nothing revs uids uats subs)), SignaturePkt sp) -> case sigType sp of-                                                                                Just SubkeyBindingSig -> ((Subs, Just (TK pkp Nothing revs uids uats (setBSig sp subs))), [])-                                                                                Just SubkeyRevocationSig -> ((Subs, Just (TK pkp Nothing revs uids uats (setRSig sp subs))), [])-                                                                                _ -> dropOrError intolerant s $ "Unexpected subkey sig: " ++ show (fst s) ++ "/" ++ show i-                       ((Subs, Just (TK pkp Nothing revs uids uats subs)), PublicKeyPkt p) -> ((Revs, Just (TK p Nothing [] [] [] [])), [TK pkp Nothing revs uids uats subs])-                       ((Subs, Just (TK pkp Nothing revs uids uats subs)), BrokenPacketPkt _ 6 _) -> ((SkippingBroken, Nothing), [TK pkp Nothing revs uids uats subs])-                       ((Revs, Just (TK pkp mska revs uids uats subs)), SignaturePkt sp) -> ((Revs, Just (TK pkp mska (revs ++ [sp]) uids uats subs)), [])-                       ((Revs, Just (TK pkp mska revs _ uats subs)), UserIdPkt u) -> ((Uids, Just (TK pkp mska revs [(u, [])] uats subs)), [])-                       ((Uids, Just (TK pkp mska revs uids uats subs)), SignaturePkt sp) -> ((Uids, Just (TK pkp mska revs (addUidSig sp uids) uats subs)), [])-                       ((Uids, Just (TK pkp mska revs uids uats subs)), UserIdPkt u) -> ((Uids, Just (TK pkp mska revs (uids ++ [(u, [])]) uats subs)), [])-                       ((Uids, Just (TK pkp mska revs uids _ subs)), UserAttributePkt u) -> ((UAts, Just (TK pkp mska revs uids [(u, [])] subs)), [])-                       ((Uids, Just (TK pkp mska revs uids uats _)), SecretSubkeyPkt p ss) -> ((Subs, Just (TK pkp mska revs uids uats [(SecretSubkeyPkt p ss, SigVOther 0 B.empty, Nothing)])), [])-                       ((Uids, Just (TK pkp mska revs uids uats subs)), SecretKeyPkt p sk) -> ((Revs, Just (TK p (Just sk) [] [] [] [])), [TK pkp mska revs uids uats subs])-                       ((Uids, Just (TK pkp mska revs uids uats subs)), BrokenPacketPkt _ 5 _) -> ((SkippingBroken, Nothing), [TK pkp mska revs uids uats subs])-                       ((UAts, Just (TK pkp mska revs uids uats subs)), SignaturePkt sp) -> ((UAts, Just (TK pkp mska revs uids (addUAtSig sp uats) subs)), [])-                       ((UAts, Just (TK pkp mska revs uids uats subs)), UserAttributePkt u) -> ((UAts, Just (TK pkp mska revs uids (uats ++ [(u, [])]) subs)), [])-                       ((UAts, Just (TK pkp mska revs uids uats subs)), UserIdPkt u) -> ((Uids, Just (TK pkp mska revs (uids ++ [(u, [])]) uats subs)), [])-                       ((UAts, Just (TK pkp mska revs uids uats _)), SecretSubkeyPkt p ss) -> ((Subs, Just (TK pkp mska revs uids uats [(SecretSubkeyPkt p ss, SigVOther 0 B.empty, Nothing)])), [])-                       ((UAts, Just (TK pkp mska revs uids uats subs)), SecretKeyPkt p ss) -> ((Revs, Just (TK p (Just ss) [] [] [] [])), [TK pkp mska revs uids uats subs])-                       ((UAts, Just (TK pkp mska revs uids uats subs)), BrokenPacketPkt _ 5 _) -> ((SkippingBroken, Nothing), [TK pkp mska revs uids uats subs])-                       ((Subs, Just (TK pkp mska revs uids uats subs)), SecretSubkeyPkt p ss) -> ((Subs, Just (TK pkp mska revs uids uats (subs ++ [(SecretSubkeyPkt p ss, SigVOther 0 B.empty, Nothing)]))), [])-                       ((Subs, Just (TK pkp mska revs uids uats subs)), SignaturePkt sp) -> case sigType sp of-                                                                                Just SubkeyBindingSig -> ((Subs, Just (TK pkp mska revs uids uats (setBSig sp subs))), [])-                                                                                Just SubkeyRevocationSig -> ((Subs, Just (TK pkp mska revs uids uats (setRSig sp subs))), [])-                                                                                _ -> dropOrError intolerant s $ "Unexpected subkey sig: " ++ show (fst s) ++ "/" ++ show i-                       ((Subs, Just tk), SecretKeyPkt p sk) -> ((Revs, Just (TK p (Just sk) [] [] [] [])), [tk])-                       ((Subs, Just tk), BrokenPacketPkt _ 5 _) -> ((SkippingBroken, Nothing), [tk])-                       ((SkippingBroken, _), PublicKeyPkt pkp) -> ((Revs, Just (TK pkp Nothing [] [] [] [])), [])-                       ((SkippingBroken, _), SecretKeyPkt pkp ska) -> ((Revs, Just (TK pkp (Just ska) [] [] [] [])), [])-                       ((SkippingBroken, _), _) -> (s, [])-                       ((_,_), TrustPkt _) -> (s, [])-                       _ -> dropOrError intolerant s $ "Unexpected packet: " ++ show (fst s) ++ "/" ++ show i-        addUidSig s uids = init uids ++ [(\(u, us) -> (u, us ++ [s])) (last uids)]-        addUAtSig s uats = init uats ++ [(\(u, us) -> (u, us ++ [s])) (last uats)]-        setBSig s subs = init subs ++ [(\(p, _, r) -> (p, s, r)) (last subs)]-        setRSig s subs = init subs ++ [(\(p, b, _) -> (p, b, Just s)) (last subs)]-        dropOrError :: Bool -> (Phase, Maybe TK) -> String -> ((Phase, Maybe TK), [TK])-        dropOrError True _ e = error e-        dropOrError False s _ = (s, [])+        notTrustPacket (TrustPkt _) = False+        notTrustPacket _ = True++parseAChunk :: (Monoid s, Show s) => Parser s r -> s -> ([(r, s)], Maybe (Maybe (r -> r), Parser s r)) -> (([(r, s)], Maybe (Maybe (r -> r), Parser s r)), [r])+parseAChunk op a ([], Nothing) = error $ "Failure before " ++ show a+parseAChunk op a (cr, Nothing) = (inspect (feed (mconcat (map snd cr) <> a) op), map fst cr)+parseAChunk _ a (cr, Just (_, p)) = (inspect (feed a p), [])++finalizeParsing :: Monoid s => ([(r, s)], Maybe (Maybe (r -> r), Parser s r)) -> (([(r, s)], Maybe (Maybe (r -> r), Parser s r)), [r])+finalizeParsing ([], Nothing) = error $ "Unexpected finalization failure"+finalizeParsing (cr, Nothing) = (([], Nothing), map fst cr)+finalizeParsing (cr, Just (_, p)) = finalizeParsing (inspect (feedEof p))++parseTK :: Bool -> Parser [Pkt] (Maybe TK)+parseTK True = publictk True <|> secrettk True+parseTK False = publictk False <|> secrettk False <|> brokentk 6 <|> brokentk 5++(.::.) = (.) . (.) . (.) . (.) . (.)++publictk, secrettk :: Bool -> Parser [Pkt] (Maybe TK)+publictk intolerant = (Just .::. TK) <$> pkpayload <*> concatMany (signature intolerant [KeyRevocationSig,SignatureDirectlyOnAKey]) <*> (if intolerant then some else many) (signeduid intolerant) <*> many (signeduat intolerant) <*> many (signedorrevokedpubsubkey intolerant)+secrettk intolerant = (Just .::. TK) <$> skpayload <*> concatMany (signature intolerant [KeyRevocationSig,SignatureDirectlyOnAKey]) <*> (if intolerant then some else many) (signeduid intolerant) <*> many (signeduat intolerant) <*> many (raworsignedorrevokedsecsubkey intolerant)++brokentk :: Int -> Parser [Pkt] (Maybe TK)+brokentk 6 = const Nothing <$> broken 6 <* many (signature False [KeyRevocationSig,SignatureDirectlyOnAKey]) <* many (signeduid False) <* many (signeduat False) <* many (signedorrevokedpubsubkey False)+brokentk 5 = const Nothing <$> broken 5 <* many (signature False [KeyRevocationSig,SignatureDirectlyOnAKey]) <* many (signeduid False) <* many (signeduat False) <* many (raworsignedorrevokedsecsubkey False)+brokentk _ = fail "Unexpected broken packet type"++pkpayload :: Parser [Pkt] (PKPayload, Maybe SKAddendum)+pkpayload = do [PublicKeyPkt p] <- satisfy isPKP+               return (p, Nothing)+    where+        isPKP [PublicKeyPkt _] = True+        isPKP _ = False++signature :: Bool -> [SigType] -> Parser [Pkt] [SignaturePayload]+signature intolerant rts = if intolerant then signature' else (signature' <|> brokensig')+    where+        signature' = do [SignaturePkt sp] <- satisfy (isSP intolerant)+                        return $! (if intolerant then id else filter isSP') [sp]+        brokensig' = const [] <$> broken 2+        isSP True [SignaturePkt sp@(SigV3 {})] = isSP' sp+        isSP True [SignaturePkt sp@(SigV4 {})] = isSP' sp+        isSP False [SignaturePkt _] = True+        isSP _ _ = False+	isSP' (SigV3 st _ _ _ _ _ _) = st `elem` rts+	isSP' (SigV4 st _ _ _ _ _ _) = st `elem` rts+	isSP' _ = False++signeduid :: Bool -> Parser [Pkt] (String, [SignaturePayload])+signeduid intolerant = do [UserIdPkt u] <- satisfy isUID+                          sigs <- concatMany (signature intolerant [GenericCert, PersonaCert, CasualCert, PositiveCert, CertRevocationSig])+                          return (u, sigs)+    where+        isUID [UserIdPkt _] = True+        isUID _ = False++signeduat :: Bool -> Parser [Pkt] ([UserAttrSubPacket], [SignaturePayload])+signeduat intolerant = do [UserAttributePkt us] <- satisfy isUAt+                          sigs <- concatMany (signature intolerant [GenericCert, PersonaCert, CasualCert, PositiveCert, CertRevocationSig])+                          return (us, sigs)+    where+        isUAt [UserAttributePkt _] = True+        isUAt _ = False++signedorrevokedpubsubkey :: Bool -> Parser [Pkt] (Pkt, [SignaturePayload])+signedorrevokedpubsubkey intolerant = do [p] <- satisfy isPSKP+                                         sigs <- concatMany (signature intolerant [SubkeyBindingSig, SubkeyRevocationSig])+                                         return (p, sigs)+    where+        isPSKP [PublicSubkeyPkt _] = True+        isPSKP _ = False++raworsignedorrevokedsecsubkey :: Bool -> Parser [Pkt] (Pkt, [SignaturePayload])+raworsignedorrevokedsecsubkey intolerant = do [p] <- satisfy isSSKP+                                              sigs <- concatMany (signature intolerant [SubkeyBindingSig, SubkeyRevocationSig])+                                              return (p, sigs)+    where+        isSSKP [SecretSubkeyPkt _ _] = True+        isSSKP _ = False++skpayload :: Parser [Pkt] (PKPayload, Maybe SKAddendum)+skpayload = do [SecretKeyPkt p ska] <- satisfy isSKP+               return (p, Just ska)+    where+        isSKP [SecretKeyPkt _ _] = True+        isSKP _ = False++broken :: Int -> Parser [Pkt] Pkt+broken t = do [bp] <- satisfy isBroken+              return bp+    where+        isBroken [BrokenPacketPkt _ a _] = t == fromIntegral a+        isBroken _ = False  sinkKeyringMap :: MonadResource m => Sink TK m Keyring sinkKeyringMap = CL.fold (flip insert) empty
hOpenPGP.cabal view
@@ -1,5 +1,5 @@ Name:                hOpenPGP-Version:             0.14+Version:             1.0 Synopsis:            native Haskell implementation of OpenPGP (RFC4880) Description:         native Haskell implementation of OpenPGP (RFC4880) Homepage:            http://floss.scru.org/hOpenPGP/@@ -180,6 +180,7 @@                , cryptohash                , data-default                , errors+               , incremental-parser                , ixset                 >= 1.0                , lens                  >= 3.0                , monad-loops@@ -216,6 +217,7 @@                , cryptohash                , data-default                , errors+               , incremental-parser                , ixset                 >= 1.0                , lens                  >= 3.0                , monad-loops@@ -242,4 +244,4 @@ source-repository this   type:     git   location: git://git.debian.org/users/clint/hOpenPGP.git-  tag:      v0.14+  tag:      v1.0