diff --git a/Codec/Encryption/OpenPGP/Arbitrary.hs b/Codec/Encryption/OpenPGP/Arbitrary.hs
--- a/Codec/Encryption/OpenPGP/Arbitrary.hs
+++ b/Codec/Encryption/OpenPGP/Arbitrary.hs
@@ -151,6 +151,12 @@
 instance Arbitrary ThirtyTwoBitDuration where
     arbitrary = liftM ThirtyTwoBitDuration arbitrary
 
+instance Arbitrary NotationName where
+    arbitrary = liftM NotationName arbitrary
+
+instance Arbitrary NotationValue where
+    arbitrary = liftM NotationValue arbitrary
+
 -- FIXME: this should be elsewhere
 instance Arbitrary a => Arbitrary (NE.NonEmpty a) where
     arbitrary = NE.fromList `liftM` listOf1 arbitrary
diff --git a/Codec/Encryption/OpenPGP/SecretKey.hs b/Codec/Encryption/OpenPGP/SecretKey.hs
--- a/Codec/Encryption/OpenPGP/SecretKey.hs
+++ b/Codec/Encryption/OpenPGP/SecretKey.hs
@@ -15,13 +15,12 @@
 import Codec.Encryption.OpenPGP.CFB (decryptNoNonce, encryptNoNonce)
 import Codec.Encryption.OpenPGP.Serialize (getSecretKey)
 import Codec.Encryption.OpenPGP.S2K (skesk2Key, string2Key)
-import Control.Monad ((>=>))
 import qualified Crypto.Hash.SHA1 as SHA1
 import Crypto.Random (createEntropyPool, cprgCreate, cprgGenerateWithEntropy, SystemRNG)
 import qualified Data.ByteString as B
 import qualified Data.ByteString.Lazy as BL
 import Data.Binary (put)
-import Data.Binary.Get (getLazyByteString, remaining, getWord16be, runGetOrFail)
+import Data.Binary.Get (getRemainingLazyByteString, getWord16be, runGetOrFail)
 import Data.Binary.Put (runPut)
 import Data.Bifunctor (bimap)
 import qualified Crypto.PubKey.RSA as R
@@ -48,7 +47,7 @@
     let checksum = sum . map fromIntegral . B.unpack . B.take (B.length p - 20) $ p
     return $ SUUnencrypted s checksum  -- FIXME: is this the correct checksum?
     where
-        getSecretKeyAndChecksum p = bimap (\(_,_,x) -> x) (\(_,_,x) -> x) (runGetOrFail (getSecretKey pkp >>= \sk -> remaining >>= (getLazyByteString >=> \csum -> return (sk, csum))) (BL.fromStrict p))
+        getSecretKeyAndChecksum p = bimap (\(_,_,x) -> x) (\(_,_,x) -> x) (runGetOrFail (getSecretKey pkp >>= \sk -> getRemainingLazyByteString >>= \csum -> return (sk, csum)) (BL.fromStrict p))
 decryptSKA _ _ = Left "Unexpected codepath"
 
 -- |generates pseudo-random salt and IV
diff --git a/Codec/Encryption/OpenPGP/Serialize.hs b/Codec/Encryption/OpenPGP/Serialize.hs
--- a/Codec/Encryption/OpenPGP/Serialize.hs
+++ b/Codec/Encryption/OpenPGP/Serialize.hs
@@ -8,9 +8,9 @@
  , getSecretKey
 ) where
 
-import Control.Applicative ((<$>),(<*>), many, some)
+import Control.Applicative ((<$>), many, some)
 import Control.Lens ((^.), _1)
-import Control.Monad (guard, liftM, mplus, replicateM, replicateM_)
+import Control.Monad (guard, liftM, replicateM, replicateM_)
 import qualified Crypto.PubKey.RSA as R
 import qualified Crypto.PubKey.DSA as D
 import Data.Bits ((.&.), (.|.), shiftL, shiftR, testBit)
@@ -20,7 +20,7 @@
 import Data.List (mapAccumL)
 import qualified Data.List.NonEmpty as NE
 import Data.Binary (Binary, get, put)
-import Data.Binary.Get (Get, getWord8, getWord16be, getWord32be, getByteString, getLazyByteString, getWord16le, runGetOrFail, remaining, ByteOffset)
+import Data.Binary.Get (Get, getByteString, getLazyByteString, getRemainingLazyByteString, getWord8, getWord16be, getWord32be, getWord16le, runGetOrFail, ByteOffset)
 import Data.Binary.Put (Put, putWord8, putWord16be, putWord32be, putByteString, putLazyByteString, putWord16le, runPut)
 import qualified Data.Foldable as F
 import Data.Monoid (mempty)
@@ -215,9 +215,9 @@
                        flags <- getLazyByteString 4
                        nl <- getWord16be
                        vl <- getWord16be
-                       nd <- getLazyByteString (fromIntegral nl)
+                       nn <- getLazyByteString (fromIntegral nl)
                        nv <- getLazyByteString (fromIntegral vl)
-                       return $ SigSubPacket crit (NotationData (bsToFFSet flags) nd nv)
+                       return $ SigSubPacket crit (NotationData (bsToFFSet flags) (NotationName nn) (NotationValue nv))
             | pt == 21 = do
                        ha <- replicateM (fromIntegral (l - 1)) get
                        return $ SigSubPacket crit (PreferredHashAlgorithms ha)
@@ -302,17 +302,17 @@
 putSigSubPacket (SigSubPacket crit (RevocationKey rclass algid fp)) = do
     putSubPacketLength 23
     putSigSubPacketType crit 12
-    putLazyByteString . ffSetToFixedLengthBS 1 $ Set.insert (RClOther 0) rclass
+    putLazyByteString . ffSetToFixedLengthBS (1 :: Int) $ Set.insert (RClOther 0) rclass
     put algid
     putLazyByteString (unTOF fp) -- 20 octets
 putSigSubPacket (SigSubPacket crit (Issuer keyid)) = do
     putSubPacketLength 9
     putSigSubPacketType crit 16
     putLazyByteString (unEOKI keyid) -- 8 octets
-putSigSubPacket (SigSubPacket crit (NotationData nfs nn nv)) = do
+putSigSubPacket (SigSubPacket crit (NotationData nfs (NotationName nn) (NotationValue nv))) = do
     putSubPacketLength . fromIntegral $ (9 + BL.length nn + BL.length nv)
     putSigSubPacketType crit 20
-    putLazyByteString . ffSetToFixedLengthBS 4 $ nfs
+    putLazyByteString . ffSetToFixedLengthBS (4 :: Int) $ nfs
     putWord16be . fromIntegral . BL.length $ nn
     putWord16be . fromIntegral . BL.length $ nv
     putLazyByteString nn
@@ -375,10 +375,7 @@
     putSubPacketLength . fromIntegral $ (1 + BL.length spb)
     putSigSubPacketType crit 32
     putLazyByteString spb
-putSigSubPacket (SigSubPacket crit (UserDefinedSigSub ptype payload)) = do
-    putSubPacketLength . fromIntegral $ (1 + BL.length payload)
-    putSigSubPacketType crit ptype
-    putLazyByteString payload
+putSigSubPacket (SigSubPacket crit (UserDefinedSigSub ptype payload)) = putSigSubPacket (SigSubPacket crit (OtherSigSub ptype payload))
 putSigSubPacket (SigSubPacket crit (OtherSigSub ptype payload)) = do
     putSubPacketLength . fromIntegral $ (1 + BL.length payload)
     putSigSubPacketType crit ptype
@@ -415,7 +412,9 @@
 putSigSubPacketType True sst = putWord8 (sst .|. 0x80)
 
 bsToFFSet :: FutureFlag a => ByteString -> Set a
-bsToFFSet bs = Set.fromAscList .  concat . snd $ mapAccumL (\acc y -> (acc+8, concatMap (\x -> if y .&. shiftR 128 x == shiftR 128 x then [toFFlag (acc + x)] else []) [0..7])) 0 (BL.unpack bs)
+bsToFFSet bs = Set.fromAscList .  concat . snd $ mapAccumL (\acc y -> (acc+8, concatMap (shifty acc y) [0..7])) 0 (BL.unpack bs)
+    where
+        shifty acc y x = [toFFlag (acc + x) | y .&. shiftR 128 x == shiftR 128 x]
 
 ffSetToFixedLengthBS :: (Integral a, FutureFlag b) => a -> Set b -> ByteString
 ffSetToFixedLengthBS len ffs = BL.take (fromIntegral len) (BL.append (ffSetToBS ffs) (BL.pack (replicate 5 0)))
@@ -480,8 +479,7 @@
                           count <- getWord8
                           return $ IteratedSalted (toFVal ha) (Salt salt) (decodeIterationCount count)
             | otherwise = do
-                          len <- remaining
-                          bs <- getLazyByteString len
+                          bs <- getRemainingLazyByteString
                           return $ OtherS2K t bs
 
 putS2K :: S2K -> Put
@@ -511,8 +509,7 @@
                        2 -> do len <- getWord32be
                                bs <- getLazyByteString (fromIntegral len)
                                return (t, bs)
-                       3 -> do len <- remaining
-                               bs <- getLazyByteString len
+                       3 -> do bs <- getRemainingLazyByteString
                                return (t, bs)
                        _ -> error "This should never happen (getPacketTypeAndPayload/0x00)."
         0x40 -> do
@@ -533,15 +530,13 @@
             | t == 1 = do
                           pv <- getWord8
                           eokeyid <- getLazyByteString 8
-                          pkalgo <- getWord8
-                          remainder <- remaining
-                          mpib <- getLazyByteString remainder
+                          pka <- getWord8
+                          mpib <- getRemainingLazyByteString
                           case runGetOrFail (some getMPI) mpib of
                               Left (_, _, e) -> fail ("PKESK MPIs " ++ e)
-                              Right (_, _, sk) -> return $ PKESKPkt pv (EightOctetKeyId eokeyid) (toFVal pkalgo) (NE.fromList sk)
+                              Right (_, _, sk) -> return $ PKESKPkt pv (EightOctetKeyId eokeyid) (toFVal pka) (NE.fromList sk)
             | t == 2 = do
-                          remainder <- remaining
-                          bs <- getLazyByteString remainder
+                          bs <- getRemainingLazyByteString
                           case runGetOrFail get bs of
                               Left (_, _, e) -> fail ("signature packet " ++ e)
                               Right (_, _, sp) -> return $ SignaturePkt sp
@@ -549,8 +544,7 @@
                           pv <- getWord8
                           symalgo <- getWord8
                           s2k <- getS2K
-                          remainder <- remaining
-                          esk <- getLazyByteString remainder
+                          esk <- getRemainingLazyByteString
                           return $ SKESKPkt pv (toFVal symalgo) s2k (if BL.null esk then Nothing else Just esk)
             | t == 4 = do
                           pv <- getWord8
@@ -630,7 +624,7 @@
             getUserAttrSubPacket' :: Word8 -> ByteOffset -> Get UserAttrSubPacket
             getUserAttrSubPacket' t l
                 | t == 1 = do
-                              ihlen <- getWord16le
+                              _ <- getWord16le -- ihlen
                               hver <- getWord8 -- should be 1
                               iformat <- getWord8
                               nuls <- getLazyByteString 12 -- should be NULs
@@ -658,19 +652,18 @@
             putLazyByteString bs
 
 putPkt :: Pkt -> Put
-putPkt (PKESKPkt pv eokeyid pkalgo mpis) = do
+putPkt (PKESKPkt pv eokeyid pka mpis) = do
     putWord8 (0xc0 .|. 1)
     let bsk = runPut $ F.mapM_ put mpis
     putPacketLength . fromIntegral $ 10 + BL.length bsk
     putWord8 pv -- must be 3
     putLazyByteString (unEOKI eokeyid) -- must be 8 octets
-    putWord8 $ fromIntegral . fromFVal $ pkalgo
+    putWord8 $ fromIntegral . fromFVal $ pka
     putLazyByteString bsk
 putPkt (SignaturePkt sp) = do
     putWord8 (0xc0 .|. 2)
     let bs = runPut $ put sp
-    putPacketLength . fromIntegral . BL.length $ bs
-    putLazyByteString bs
+    putLengthThenPayload bs
 putPkt (SKESKPkt pv symalgo s2k mesk) = do
     putWord8 (0xc0 .|. 3)
     let bs2k = fromS2K s2k
@@ -689,38 +682,31 @@
                 putWord8 $ fromIntegral . fromFVal $ pka
                 putLazyByteString (unEOKI skeyid)
                 putWord8 . fromIntegral . fromEnum $ not nested -- FIXME: what do other values mean?
-    putPacketLength . fromIntegral $ BL.length bs
-    putLazyByteString bs
+    putLengthThenPayload bs
 putPkt (SecretKeyPkt pkp ska) = do
     putWord8 (0xc0 .|. 5)
     let bs = runPut (putPKPayload pkp >> putSKAddendum ska)
-    putPacketLength . fromIntegral $ BL.length bs
-    putLazyByteString bs
+    putLengthThenPayload bs
 putPkt (PublicKeyPkt pkp) = do
     putWord8 (0xc0 .|. 6)
     let bs = runPut $ putPKPayload pkp
-    putPacketLength . fromIntegral $ BL.length bs
-    putLazyByteString bs
+    putLengthThenPayload bs
 putPkt (SecretSubkeyPkt pkp ska) = do
     putWord8 (0xc0 .|. 7)
     let bs = runPut (putPKPayload pkp >> putSKAddendum ska)
-    putPacketLength . fromIntegral $ BL.length bs
-    putLazyByteString bs
+    putLengthThenPayload bs
 putPkt (CompressedDataPkt ca cdata) = do
     putWord8 (0xc0 .|. 8)
     let bs = runPut $ do
                          putWord8 $ fromIntegral . fromFVal $ ca
                          putLazyByteString cdata
-    putPacketLength . fromIntegral $ BL.length bs
-    putLazyByteString bs
+    putLengthThenPayload bs
 putPkt (SymEncDataPkt b) = do
     putWord8 (0xc0 .|. 9)
-    putPacketLength . fromIntegral $ BL.length b
-    putLazyByteString b
+    putLengthThenPayload b
 putPkt (MarkerPkt b) = do
     putWord8 (0xc0 .|. 10)
-    putPacketLength . fromIntegral $ BL.length b
-    putLazyByteString b
+    putLengthThenPayload b
 putPkt (LiteralDataPkt dt fn ts b) = do
     putWord8 (0xc0 .|. 11)
     let bs = runPut $ do
@@ -729,12 +715,10 @@
                         putLazyByteString fn
                         putWord32be . unThirtyTwoBitTimeStamp $ ts
                         putLazyByteString b
-    putPacketLength . fromIntegral $ BL.length bs
-    putLazyByteString bs
+    putLengthThenPayload bs
 putPkt (TrustPkt b) = do
     putWord8 (0xc0 .|. 12)
-    putPacketLength . fromIntegral . BL.length $ b
-    putLazyByteString b
+    putLengthThenPayload b
 putPkt (UserIdPkt u) = do
     putWord8 (0xc0 .|. 13)
     let bs = encodeUtf8 u
@@ -743,13 +727,11 @@
 putPkt (PublicSubkeyPkt pkp) = do
     putWord8 (0xc0 .|. 14)
     let bs = runPut $ putPKPayload pkp
-    putPacketLength . fromIntegral $ BL.length bs
-    putLazyByteString bs
+    putLengthThenPayload bs
 putPkt (UserAttributePkt us) = do
     putWord8 (0xc0 .|. 17)
     let bs = runPut $ mapM_ put us
-    putPacketLength . fromIntegral $ BL.length bs
-    putLazyByteString bs
+    putLengthThenPayload bs
 putPkt (SymEncIntegrityProtectedDataPkt pv b) = do
     putWord8 (0xc0 .|. 18)
     putPacketLength . fromIntegral $ BL.length b + 1
@@ -757,14 +739,17 @@
     putLazyByteString b
 putPkt (ModificationDetectionCodePkt hash) = do
     putWord8 (0xc0 .|. 19)
-    putPacketLength . fromIntegral . BL.length $ hash
-    putLazyByteString hash
+    putLengthThenPayload hash
 putPkt (OtherPacketPkt t payload) = do
     putWord8 (0xc0 .|. t) -- FIXME: restrict t
-    putPacketLength . fromIntegral . BL.length $ payload
-    putLazyByteString payload
+    putLengthThenPayload payload
 putPkt (BrokenPacketPkt _ t payload) = putPkt (OtherPacketPkt t payload)
 
+putLengthThenPayload :: ByteString -> Put
+putLengthThenPayload bs = do
+    putPacketLength . fromIntegral $ BL.length bs
+    putLazyByteString bs
+
 getMPI :: Get MPI
 getMPI = do mpilen <- getWord16be
             bs <- getLazyByteString (fromIntegral (mpilen + 7) `div` 8)
@@ -786,7 +771,7 @@
                                 MPI g <- get
                                 MPI y <- get
                                 return $ ElGamalPubKey [p,g,y]
-getPubkey _ = UnknownPKey <$> (getLazyByteString =<< remaining)
+getPubkey _ = UnknownPKey <$> getRemainingLazyByteString
 
 putPubkey :: PKey -> Put
 putPubkey (UnknownPKey bs) = put bs
@@ -799,8 +784,7 @@
            MPI p <- get
            MPI q <- get
            MPI _ <- get -- u
-           let n = p * q
-               dP = 0
+           let dP = 0
                dQ = 0
                qinv = 0
                pub = (\(RSAPubKey (RSA_PublicKey x)) -> x) (pkp^.pubkey)
@@ -861,8 +845,7 @@
                       OtherS2K _ _ -> return $ SUS16bit (toFVal symenc) s2k mempty BL.empty
                       _ -> do
                               iv <- getByteString (symEncBlockSize . toFVal $ symenc)
-                              remainder <- remaining
-                              encryptedblock <- getLazyByteString remainder
+                              encryptedblock <- getRemainingLazyByteString
                               return $ SUS16bit (toFVal symenc) s2k (IV iv) encryptedblock
         254 -> do symenc <- getWord8
                   s2k <- getS2K
@@ -870,12 +853,10 @@
                       OtherS2K _ _ -> return $ SUSSHA1 (toFVal symenc) s2k mempty BL.empty
                       _ -> do
                               iv <- getByteString (symEncBlockSize . toFVal $ symenc)
-                              remainder <- remaining
-                              encryptedblock <- getLazyByteString remainder
+                              encryptedblock <- getRemainingLazyByteString
                               return $ SUSSHA1 (toFVal symenc) s2k (IV iv) encryptedblock
         symenc -> do iv <- getByteString (symEncBlockSize . toFVal $ symenc)
-                     remainder <- remaining
-                     encryptedblock <- getLazyByteString remainder
+                     encryptedblock <- getRemainingLazyByteString
                      return $ SUSym (toFVal symenc) (IV iv) encryptedblock
 
 putSKAddendum :: SKAddendum -> Put
@@ -1178,8 +1159,7 @@
             pka <- get
             ha <- get
             left16 <- getWord16be
-            remainder <- remaining
-            mpib <- getLazyByteString remainder
+            mpib <- getRemainingLazyByteString
             case runGetOrFail (some getMPI) mpib of
                 Left (_, _, e) -> fail ("v3 sig MPIs " ++ e)
                 Right (_, _, mpis) -> return $ SigV3 (toFVal st) ctime (EightOctetKeyId eok) (toFVal pka) (toFVal ha) left16 (NE.fromList mpis)
@@ -1198,14 +1178,12 @@
                             Left (_, _, err) -> fail ("v4 sig unhasheds " ++ err)
                             Right (_, _, u) -> u
             left16 <- getWord16be
-            remainder <- remaining
-            mpib <- getLazyByteString remainder
+            mpib <- getRemainingLazyByteString
             case runGetOrFail (some getMPI) mpib of
                     Left (_, _, e) -> fail ("v4 sig MPIs " ++ e)
                     Right (_, _, mpis) -> return $ SigV4 (toFVal st) (toFVal pka) (toFVal ha) hashed unhashed left16 (NE.fromList mpis)
         _ -> do
-            remainder <- remaining
-            bs <- getLazyByteString remainder
+            bs <- getRemainingLazyByteString
             return $ SigVOther pv bs
 
 putSignaturePayload :: SignaturePayload -> Put
diff --git a/Codec/Encryption/OpenPGP/Types.hs b/Codec/Encryption/OpenPGP/Types.hs
--- a/Codec/Encryption/OpenPGP/Types.hs
+++ b/Codec/Encryption/OpenPGP/Types.hs
@@ -15,8 +15,10 @@
 
 import GHC.Generics (Generic)
 
+import Control.Applicative ((<$>), (<|>))
 import Control.Arrow ((***))
 import Control.Lens (makeLenses)
+import Control.Monad (mzero)
 import Control.Newtype (Newtype(..))
 import qualified Crypto.PubKey.RSA as RSA
 import qualified Crypto.PubKey.DSA as DSA
@@ -35,6 +37,7 @@
 import Data.List.NonEmpty (NonEmpty)
 import qualified Data.List.NonEmpty as NE
 import Data.List.Split (chunksOf)
+import Data.Maybe (fromMaybe)
 import Data.Monoid ((<>), Monoid, mempty)
 import Data.Ord (comparing)
 import Data.Set (Set)
@@ -45,7 +48,7 @@
 import Data.Time.Format (formatTime)
 import Data.Typeable (Typeable)
 import Data.Word (Word8, Word16, Word32)
-import Network.URI (URI(..), uriToString)
+import Network.URI (URI(..), uriToString, nullURI, parseURI)
 import Numeric (readHex, showHex)
 import System.Locale (defaultTimeLocale)
 import Text.PrettyPrint.Free (Pretty(..), (<+>), char, hsep, punctuate, space, text, tupled)
@@ -57,8 +60,6 @@
 type Revocability = Bool
 type RevocationReason = Text
 type KeyServer = ByteString
-type NotationName = ByteString
-type NotationValue = ByteString
 type SignatureHash = ByteString
 type PacketVersion = Word8
 type V3Expiration = Word16
@@ -85,7 +86,7 @@
     (==) a b = fromFVal a == fromFVal b
 
 instance Ord SymmetricAlgorithm where
-    compare a b = fromFVal a `compare` fromFVal b
+    compare = comparing fromFVal
 
 instance FutureVal SymmetricAlgorithm where
     fromFVal Plaintext = 0
@@ -130,6 +131,7 @@
     pretty (OtherSA sa) = text "unknown symmetric algorithm" <+> (text . show) sa
 
 instance A.ToJSON SymmetricAlgorithm
+instance A.FromJSON SymmetricAlgorithm
 
 data NotationFlag = HumanReadable
                   | OtherNF Word8 -- FIXME: this should be constrained to 4 bits?
@@ -139,7 +141,7 @@
     (==) a b = fromFFlag a == fromFFlag b
 
 instance Ord NotationFlag where
-    compare a b = fromFFlag a `compare` fromFFlag b
+    compare = comparing fromFFlag
 
 instance FutureFlag NotationFlag where
     fromFFlag HumanReadable = 0
@@ -155,6 +157,7 @@
     pretty (OtherNF o) = text "unknown notation flag type" <+> pretty o
 
 instance A.ToJSON NotationFlag
+instance A.FromJSON NotationFlag
 
 data SigSubPacket = SigSubPacket {
     _sspCriticality :: Bool
@@ -167,6 +170,7 @@
 instance Hashable SigSubPacket
 
 instance A.ToJSON SigSubPacket
+instance A.FromJSON SigSubPacket
 
 newtype ThirtyTwoBitTimeStamp = ThirtyTwoBitTimeStamp {unThirtyTwoBitTimeStamp :: Word32}
     deriving (Bounded, Data, Enum, Eq, Generic, Hashable, Integral, Num, Ord, Real, Show, Typeable)
@@ -179,6 +183,7 @@
     pretty = text . formatTime defaultTimeLocale "%Y%m%d-%H%M%S" . posixSecondsToUTCTime . realToFrac
 
 instance A.ToJSON ThirtyTwoBitTimeStamp
+instance A.FromJSON ThirtyTwoBitTimeStamp
 
 newtype ThirtyTwoBitDuration = ThirtyTwoBitDuration {unThirtyTwoBitDuration :: Word32}
     deriving (Bounded, Data, Enum, Eq, Generic, Hashable, Integral, Num, Ord, Real, Show, Typeable)
@@ -191,6 +196,7 @@
     pretty = text . concat . unfoldr durU . unpack
 
 instance A.ToJSON ThirtyTwoBitDuration
+instance A.FromJSON ThirtyTwoBitDuration
 
 durU :: (Integral a, Show a) => a -> Maybe (String, a)
 durU x
@@ -214,8 +220,40 @@
     pretty = pretty . (\uri -> uriToString id uri "") . unpack
 
 instance A.ToJSON URL where
-    toJSON = A.toJSON . (\uri -> uriToString id uri "") . unpack
+    toJSON u = object [T.pack "uri" .= (\uri -> uriToString id uri "") (unpack u)]
+instance A.FromJSON URL where
+    parseJSON (A.Object v) = URL . fromMaybe nullURI . parseURI <$>
+                                      v A..: T.pack "uri"
+    parseJSON _            = mzero
 
+newtype NotationName = NotationName {unNotationName :: ByteString}
+    deriving (Data, Eq, Generic, Hashable, Ord, Pretty, Show, Typeable)
+
+instance Newtype NotationName ByteString where
+    pack = NotationName
+    unpack (NotationName nn) = nn
+
+instance A.ToJSON NotationName where
+    toJSON nn = object [T.pack "notationname" .= show (unpack nn)]
+instance A.FromJSON NotationName where
+    parseJSON (A.Object v) = NotationName . read <$>
+                                      v A..: T.pack "notationname"
+    parseJSON _            = mzero
+
+newtype NotationValue = NotationValue {unNotationValue :: ByteString}
+    deriving (Data, Eq, Generic, Hashable, Ord, Pretty, Show, Typeable)
+
+instance Newtype NotationValue ByteString where
+    pack = NotationValue
+    unpack (NotationValue nv) = nv
+
+instance A.ToJSON NotationValue where
+    toJSON nv = object [T.pack "notationvalue" .= show (unpack nv)]
+instance A.FromJSON NotationValue where
+    parseJSON (A.Object v) = NotationValue . read <$>
+                                      v A..: T.pack "notationvalue"
+    parseJSON _            = mzero
+
 data SigSubPacketPayload = SigCreationTime ThirtyTwoBitTimeStamp
                   | SigExpirationTime ThirtyTwoBitDuration
                   | ExportableCertification Exportability
@@ -273,32 +311,49 @@
     pretty (OtherSigSub t bs) = text "unknown signature subpacket type" <+> pretty t <+> pretty bs
 
 instance A.ToJSON SigSubPacketPayload where
-    toJSON (SigCreationTime ts) = A.toJSON ts
-    toJSON (SigExpirationTime d) = A.toJSON d
-    toJSON (ExportableCertification e) = A.toJSON e
-    toJSON (TrustSignature tl ta) = A.toJSON (tl, ta)
-    toJSON (RegularExpression apdre) = A.toJSON (BL.unpack apdre)
-    toJSON (Revocable r) = A.toJSON r
-    toJSON (KeyExpirationTime d) = A.toJSON d
-    toJSON (PreferredSymmetricAlgorithms sas) = A.toJSON sas
-    toJSON (RevocationKey rcs pka tof) = A.toJSON (rcs, pka, tof)
-    toJSON (Issuer eoki) = A.toJSON eoki
-    toJSON (NotationData nfs nn nv) = A.toJSON (nfs, BL.unpack nn, BL.unpack nv)
-    toJSON (PreferredHashAlgorithms phas) = A.toJSON phas
-    toJSON (PreferredCompressionAlgorithms pcas) = A.toJSON pcas
-    toJSON (KeyServerPreferences kspfs) = A.toJSON kspfs
-    toJSON (PreferredKeyServer ks) = A.toJSON (show ks)
-    toJSON (PrimaryUserId p) = A.toJSON p
-    toJSON (PolicyURL u) = A.toJSON u
-    toJSON (KeyFlags kfs) = A.toJSON kfs
-    toJSON (SignersUserId u) = A.toJSON u
-    toJSON (ReasonForRevocation rc rr) = A.toJSON (rc, rr)
-    toJSON (Features ffs) = A.toJSON ffs
-    toJSON (SignatureTarget pka ha sh) = A.toJSON (pka, ha, BL.unpack sh)
-    toJSON (EmbeddedSignature sp) = A.toJSON sp
-    toJSON (UserDefinedSigSub t bs) = A.toJSON (t, BL.unpack bs)
-    toJSON (OtherSigSub t bs) = A.toJSON (t, BL.unpack bs)
+    toJSON (SigCreationTime ts) = object [T.pack "sigCreationTime" .= ts]
+    toJSON (SigExpirationTime d) = object [T.pack "sigExpirationTime" .= d]
+    toJSON (ExportableCertification e) = object [T.pack "exportableCertification" .= e]
+    toJSON (TrustSignature tl ta) = object [T.pack "trustSignature" .= (tl, ta)]
+    toJSON (RegularExpression apdre) = object [T.pack "regularExpression" .= (BL.unpack apdre)]
+    toJSON (Revocable r) = object [T.pack "revocable" .= r]
+    toJSON (KeyExpirationTime d) = object [T.pack "keyExpirationTime" .= d]
+    toJSON (PreferredSymmetricAlgorithms sas) = object [T.pack "preferredSymmetricAlgorithms" .= sas]
+    toJSON (RevocationKey rcs pka tof) = object [T.pack "revocationKey" .= (rcs, pka, tof)]
+    toJSON (Issuer eoki) = object [T.pack "issuer" .= eoki]
+    toJSON (NotationData nfs (NotationName nn) (NotationValue nv)) = object [T.pack "notationData" .= (nfs, BL.unpack nn, BL.unpack nv)]
+    toJSON (PreferredHashAlgorithms phas) = object [T.pack "preferredHashAlgorithms" .= phas]
+    toJSON (PreferredCompressionAlgorithms pcas) = object [T.pack "preferredCompressionAlgorithms" .=  pcas]
+    toJSON (KeyServerPreferences kspfs) = object [T.pack "keyServerPreferences" .= kspfs]
+    toJSON (PreferredKeyServer ks) = object [T.pack "preferredKeyServer" .= (show ks)]
+    toJSON (PrimaryUserId p) = object [T.pack "primaryUserId" .= p]
+    toJSON (PolicyURL u) = object [T.pack "policyURL" .= u]
+    toJSON (KeyFlags kfs) = object [T.pack "keyFlags" .= kfs]
+    toJSON (SignersUserId u) = object [T.pack "signersUserId" .= u]
+    toJSON (ReasonForRevocation rc rr) = object [T.pack "reasonForRevocation" .= (rc, rr)]
+    toJSON (Features ffs) = object [T.pack "features" .= ffs]
+    toJSON (SignatureTarget pka ha sh) = object [T.pack "signatureTarget" .= (pka, ha, BL.unpack sh)]
+    toJSON (EmbeddedSignature sp) = object [T.pack "embeddedSignature" .= sp]
+    toJSON (UserDefinedSigSub t bs) = object [T.pack "userDefinedSigSub" .= (t, BL.unpack bs)]
+    toJSON (OtherSigSub t bs) = object [T.pack "otherSigSub" .= (t, BL.unpack bs)]
 
+instance A.FromJSON SigSubPacketPayload where
+    parseJSON (A.Object v) = (SigCreationTime <$> v A..: T.pack "sigCreationTime")
+                         <|> (SigExpirationTime <$> v A..: T.pack "sigExpirationTime")
+                         <|> (ExportableCertification <$> v A..: T.pack "exportableCertification")
+                         <|> (uncurry TrustSignature <$> v A..: T.pack "trustSignature")
+                         <|> (RegularExpression . BL.pack <$> v A..: T.pack "regularExpression")
+                         <|> (Revocable <$> v A..: T.pack "revocable")
+                         <|> (KeyExpirationTime <$> v A..: T.pack "keyExpirationTime")
+                         <|> (PreferredSymmetricAlgorithms <$> v A..: T.pack "preferredSymmetricAlgorithms")
+                         <|> (uc3 RevocationKey <$> v A..: T.pack "revocationKey")
+                         <|> (Issuer <$> v A..: T.pack "issuer")
+                         <|> (uc3 NotationData <$> v A..: T.pack "notationData")
+    parseJSON _            = mzero
+
+uc3 :: (a -> b -> c -> d) -> ((a, b, c) -> d)
+uc3 f ~(a,b,c) = f a b c
+
 data HashAlgorithm = DeprecatedMD5
                    | SHA1
                    | RIPEMD160
@@ -313,7 +368,7 @@
     (==) a b = fromFVal a == fromFVal b
 
 instance Ord HashAlgorithm where
-    compare a b = fromFVal a `compare` fromFVal b
+    compare = comparing fromFVal
 
 instance FutureVal HashAlgorithm where
     fromFVal DeprecatedMD5 = 1
@@ -346,6 +401,7 @@
     pretty (OtherHA ha) = text "unknown hash algorithm type" <+> (text . show) ha
 
 instance A.ToJSON HashAlgorithm
+instance A.FromJSON HashAlgorithm
 
 data CompressionAlgorithm = Uncompressed
                           | ZIP
@@ -358,7 +414,7 @@
     (==) a b = fromFVal a == fromFVal b
 
 instance Ord CompressionAlgorithm where
-    compare a b = fromFVal a `compare` fromFVal b
+    compare = comparing fromFVal
 
 instance FutureVal CompressionAlgorithm where
     fromFVal Uncompressed = 0
@@ -382,6 +438,7 @@
     pretty (OtherCA ca) = text "unknown compression algorithm type" <+> (text . show) ca
 
 instance A.ToJSON CompressionAlgorithm
+instance A.FromJSON CompressionAlgorithm
 
 class (Eq a, Ord a) => FutureVal a where
    fromFVal :: a -> Word8
@@ -403,7 +460,7 @@
     (==) a b = fromFVal a == fromFVal b
 
 instance Ord PubKeyAlgorithm where
-    compare a b = fromFVal a `compare` fromFVal b
+    compare = comparing fromFVal
 
 instance FutureVal PubKeyAlgorithm where
     fromFVal RSA = 1
@@ -442,6 +499,7 @@
     pretty pka = text "unknown pubkey algorithm type" <+> (text . show) pka
 
 instance A.ToJSON PubKeyAlgorithm
+instance A.FromJSON PubKeyAlgorithm
 
 class (Eq a, Ord a) => FutureFlag a where
     fromFFlag :: a -> Int
@@ -455,7 +513,7 @@
     (==) a b = fromFFlag a == fromFFlag b
 
 instance Ord KSPFlag where
-    compare a b = fromFFlag a `compare` fromFFlag b
+    compare = comparing fromFFlag
 
 instance FutureFlag KSPFlag where
     fromFFlag NoModify = 0
@@ -471,6 +529,7 @@
     pretty (KSPOther o) = text "unknown keyserver preference flag type" <+> pretty o
 
 instance A.ToJSON KSPFlag
+instance A.FromJSON KSPFlag
 
 data KeyFlag = GroupKey
              | AuthKey
@@ -486,7 +545,7 @@
     (==) a b = fromFFlag a == fromFFlag b
 
 instance Ord KeyFlag where
-    compare a b = fromFFlag a `compare` fromFFlag b
+    compare = comparing fromFFlag
 
 instance FutureFlag KeyFlag where
     fromFFlag GroupKey = 0
@@ -520,6 +579,7 @@
     pretty (KFOther o) = text "unknown key flag type" <+> pretty o
 
 instance A.ToJSON KeyFlag
+instance A.FromJSON KeyFlag
 
 data RevocationClass = SensitiveRK
                      | RClOther Word8 -- FIXME: this should be constrained to 3 bits
@@ -529,7 +589,7 @@
     (==) a b = fromFFlag a == fromFFlag b
 
 instance Ord RevocationClass where
-    compare a b = fromFFlag a `compare` fromFFlag b
+    compare = comparing fromFFlag
 
 instance FutureFlag RevocationClass where
     fromFFlag SensitiveRK = 1
@@ -545,6 +605,7 @@
     pretty (RClOther o) = text "unknown revocation class" <+> pretty o
 
 instance A.ToJSON RevocationClass
+instance A.FromJSON RevocationClass
 
 data RevocationCode = NoReason
                     | KeySuperseded
@@ -558,7 +619,7 @@
     (==) a b = fromFVal a == fromFVal b
 
 instance Ord RevocationCode where
-    compare a b = fromFVal a `compare` fromFVal b
+    compare = comparing fromFVal
 
 instance FutureVal RevocationCode where
     fromFVal NoReason = 0
@@ -585,6 +646,7 @@
     pretty (RCoOther o) = text "unknown revocation code" <+> pretty o
 
 instance A.ToJSON RevocationCode
+instance A.FromJSON RevocationCode
 
 data FeatureFlag = ModificationDetection
                  | FeatureOther Int
@@ -594,7 +656,7 @@
     (==) a b = fromFFlag a == fromFFlag b
 
 instance Ord FeatureFlag where
-    compare a b = fromFFlag a `compare` fromFFlag b
+    compare = comparing fromFFlag
 
 instance FutureFlag FeatureFlag where
     fromFFlag ModificationDetection = 7
@@ -612,6 +674,7 @@
     pretty (FeatureOther o) = text "unknown feature flag type" <+> pretty o
 
 instance A.ToJSON FeatureFlag
+instance A.FromJSON FeatureFlag
 
 newtype MPI = MPI {unMPI :: Integer}
     deriving (Data, Eq, Generic, Show, Typeable)
@@ -626,6 +689,7 @@
     pretty = pretty . unpack
 
 instance A.ToJSON MPI
+instance A.FromJSON MPI
 
 data SignaturePayload = SigV3 SigType ThirtyTwoBitTimeStamp EightOctetKeyId PubKeyAlgorithm HashAlgorithm Word16 (NonEmpty MPI)
                       | SigV4 SigType PubKeyAlgorithm HashAlgorithm [SigSubPacket] [SigSubPacket] Word16 (NonEmpty MPI)
@@ -654,6 +718,7 @@
     pretty V4 = text "v4"
 
 instance A.ToJSON KeyVersion
+instance A.FromJSON KeyVersion
 
 data PKPayload = PKPayload {
       _keyVersion :: KeyVersion
@@ -664,7 +729,7 @@
     } deriving (Data, Eq, Generic, Show, Typeable)
 
 instance Ord PKPayload where
-    compare = comparing _keyVersion <> comparing _timestamp <> comparing _v3exp <> comparing _pkalgo <> comparing (show . _pubkey) -- FIXME: this is suboptimal
+    compare = comparing _keyVersion <> comparing _timestamp <> comparing _v3exp <> comparing _pkalgo <> comparing _pubkey
 
 instance Hashable PKPayload
 
@@ -721,7 +786,7 @@
     (==) a b = fromFVal a == fromFVal b
 
 instance Ord DataType where
-    compare a b = fromFVal a `compare` fromFVal b
+    compare = comparing fromFVal
 
 instance FutureVal DataType where
     fromFVal BinaryData = fromIntegral . fromEnum $ 'b'
@@ -741,6 +806,7 @@
     pretty (OtherData o) = text "other data type " <+> (text . show) o
 
 instance A.ToJSON DataType
+instance A.FromJSON DataType
 
 newtype Salt = Salt {unSalt :: B.ByteString}
     deriving (Byteable, Data, Eq, Generic, Hashable, Show, Typeable)
@@ -766,6 +832,7 @@
     pretty = pretty . unpack
 
 instance A.ToJSON IterationCount
+instance A.FromJSON IterationCount
 
 data S2K = Simple HashAlgorithm
          | Salted HashAlgorithm Salt
@@ -819,6 +886,7 @@
     pretty (ImageHV1 f) = text "imghdr v1" <+> pretty f
 
 instance A.ToJSON ImageHeader
+instance A.FromJSON ImageHeader
 
 data ImageFormat = JPEG
                  | OtherImage Word8
@@ -828,7 +896,7 @@
     (==) a b = fromFVal a == fromFVal b
 
 instance Ord ImageFormat where
-    compare a b = fromFVal a `compare` fromFVal b
+    compare = comparing fromFVal
 
 instance FutureVal ImageFormat where
     fromFVal JPEG = 1
@@ -844,6 +912,7 @@
     pretty (OtherImage o) = text "unknown image format" <+> pretty o
 
 instance A.ToJSON ImageFormat
+instance A.FromJSON ImageFormat
 
 data SigType = BinarySig
              | CanonicalTextSig
@@ -867,7 +936,7 @@
     (==) a b = fromFVal a == fromFVal b
 
 instance Ord SigType where
-    compare a b = fromFVal a `compare` fromFVal b
+    compare = comparing fromFVal
 
 instance FutureVal SigType where
     fromFVal BinarySig = 0x00
@@ -925,6 +994,7 @@
     pretty (OtherSig o) = text "unknown signature type" <+> pretty o
 
 instance A.ToJSON SigType
+instance A.FromJSON SigType
 
 newtype DSA_PublicKey = DSA_PublicKey {unDSA_PublicKey :: DSA.PublicKey}
     deriving (Data, Eq, Generic, Show, Typeable)
@@ -1069,8 +1139,13 @@
 instance Hashable EightOctetKeyId
 
 instance A.ToJSON EightOctetKeyId where
-    toJSON = A.toJSON . w8sToHex . BL.unpack . unpack
+    toJSON e = object [T.pack "eoki" .= (w8sToHex . BL.unpack . unpack) e]
 
+instance A.FromJSON EightOctetKeyId where
+    parseJSON (A.Object v) = EightOctetKeyId . read <$>
+                                      v A..: T.pack "eoki"
+    parseJSON _            = mzero
+
 newtype TwentyOctetFingerprint = TwentyOctetFingerprint {unTOF :: ByteString}
     deriving (Data, Eq, Generic, Ord, Show, Typeable)
 
@@ -1088,7 +1163,11 @@
     pretty = text . take 40 . w8sToHex . BL.unpack . unTOF
 
 instance A.ToJSON TwentyOctetFingerprint where
-    toJSON = A.toJSON . show . pretty
+    toJSON e = object [T.pack "fpr" .= (A.toJSON . show . pretty) e]
+instance A.FromJSON TwentyOctetFingerprint where
+    parseJSON (A.Object v) = TwentyOctetFingerprint . read <$>
+                                      v A..: T.pack "fpr"
+    parseJSON _            = mzero
 
 newtype SpacedFingerprint = SpacedFingerprint { unSpacedFingerprint :: TwentyOctetFingerprint }
 
@@ -1111,11 +1190,13 @@
   , _tkUIDs :: [(Text, [SignaturePayload])]
   , _tkUAts :: [([UserAttrSubPacket], [SignaturePayload])]
   , _tkSubs :: [(Pkt, [SignaturePayload])]
-  } deriving (Data, Eq, Show, Typeable)
+  } deriving (Data, Eq, Generic, Show, Typeable)
 
 instance Ord TK where
     compare = comparing _tkKey -- FIXME: is this ridiculous?
 
+instance A.ToJSON TK
+
 type Keyring = IxSet TK
 
 class Packet a where
@@ -1218,7 +1299,7 @@
     { _pkeskPacketVersion :: PacketVersion
     , _pkeskEightOctetKeyId :: EightOctetKeyId
     , _pkeskPubKeyAlgorithm :: PubKeyAlgorithm
-    , _pkeskMPIs :: (NonEmpty MPI)
+    , _pkeskMPIs :: NonEmpty MPI
     } deriving (Data, Eq, Show, Typeable)
 instance Packet PKESK where
     data PacketType PKESK = PKESKType deriving (Show, Eq)
@@ -1226,6 +1307,7 @@
     packetCode _ = 1
     toPkt (PKESK a b c d) = PKESKPkt a b c d
     fromPkt (PKESKPkt a b c d) = PKESK a b c d
+    fromPkt _ = error "Cannot coerce non-PKESK packet"
 
 instance Pretty PKESK where
     pretty = pretty . toPkt
@@ -1237,8 +1319,9 @@
     data PacketType Signature = SignatureType deriving (Show, Eq)
     packetType _ = SignatureType
     packetCode _ = 2
-    toPkt (Signature a ) = SignaturePkt a
+    toPkt (Signature a) = SignaturePkt a
     fromPkt (SignaturePkt a) = Signature a
+    fromPkt _ = error "Cannot coerce non-Signature packet"
 
 instance Pretty Signature where
     pretty = pretty . toPkt
@@ -1255,6 +1338,7 @@
     packetCode _ = 3
     toPkt (SKESK a b c d) = SKESKPkt a b c d
     fromPkt (SKESKPkt a b c d) = SKESK a b c d
+    fromPkt _ = error "Cannot coerce non-SKESK packet"
 
 instance Pretty SKESK where
     pretty = pretty . toPkt
@@ -1273,6 +1357,7 @@
     packetCode _ = 4
     toPkt (OnePassSignature a b c d e f) = OnePassSignaturePkt a b c d e f
     fromPkt (OnePassSignaturePkt a b c d e f) = OnePassSignature a b c d e f
+    fromPkt _ = error "Cannot coerce non-OnePassSignature packet"
 
 instance Pretty OnePassSignature where
     pretty = pretty . toPkt
@@ -1287,6 +1372,7 @@
     packetCode _ = 5
     toPkt (SecretKey a b) = SecretKeyPkt a b
     fromPkt (SecretKeyPkt a b) = SecretKey a b
+    fromPkt _ = error "Cannot coerce non-SecretKey packet"
 
 instance Pretty SecretKey where
     pretty = pretty . toPkt
@@ -1300,6 +1386,7 @@
     packetCode _ = 6
     toPkt (PublicKey a) = PublicKeyPkt a
     fromPkt (PublicKeyPkt a) = PublicKey a
+    fromPkt _ = error "Cannot coerce non-PublicKey packet"
 
 instance Pretty PublicKey where
     pretty = pretty . toPkt
@@ -1314,6 +1401,7 @@
     packetCode _ = 7
     toPkt (SecretSubkey a b) = SecretSubkeyPkt a b
     fromPkt (SecretSubkeyPkt a b) = SecretSubkey a b
+    fromPkt _ = error "Cannot coerce non-SecretSubkey packet"
 
 instance Pretty SecretSubkey where
     pretty = pretty . toPkt
@@ -1328,6 +1416,7 @@
     packetCode _ = 8
     toPkt (CompressedData a b) = CompressedDataPkt a b
     fromPkt (CompressedDataPkt a b) = CompressedData a b
+    fromPkt _ = error "Cannot coerce non-CompressedData packet"
 
 instance Pretty CompressedData where
     pretty = pretty . toPkt
@@ -1341,6 +1430,7 @@
     packetCode _ = 9
     toPkt (SymEncData a) = SymEncDataPkt a
     fromPkt (SymEncDataPkt a) = SymEncData a
+    fromPkt _ = error "Cannot coerce non-SymEncData packet"
 
 instance Pretty SymEncData where
     pretty = pretty . toPkt
@@ -1354,6 +1444,7 @@
     packetCode _ = 10
     toPkt (Marker a) = MarkerPkt a
     fromPkt (MarkerPkt a) = Marker a
+    fromPkt _ = error "Cannot coerce non-Marker packet"
 
 instance Pretty Marker where
     pretty = pretty . toPkt
@@ -1370,6 +1461,7 @@
     packetCode _ = 11
     toPkt (LiteralData a b c d) = LiteralDataPkt a b c d
     fromPkt (LiteralDataPkt a b c d) = LiteralData a b c d
+    fromPkt _ = error "Cannot coerce non-LiteralData packet"
 
 instance Pretty LiteralData where
     pretty = pretty . toPkt
@@ -1383,6 +1475,7 @@
     packetCode _ = 12
     toPkt (Trust a) = TrustPkt a
     fromPkt (TrustPkt a) = Trust a
+    fromPkt _ = error "Cannot coerce non-Trust packet"
 
 instance Pretty Trust where
     pretty = pretty . toPkt
@@ -1396,6 +1489,7 @@
     packetCode _ = 13
     toPkt (UserId a) = UserIdPkt a
     fromPkt (UserIdPkt a) = UserId a
+    fromPkt _ = error "Cannot coerce non-UserId packet"
 
 instance Pretty UserId where
     pretty = pretty . toPkt
@@ -1409,6 +1503,7 @@
     packetCode _ = 14
     toPkt (PublicSubkey a) = PublicSubkeyPkt a
     fromPkt (PublicSubkeyPkt a) = PublicSubkey a
+    fromPkt _ = error "Cannot coerce non-PublicSubkey packet"
 
 instance Pretty PublicSubkey where
     pretty = pretty . toPkt
@@ -1422,6 +1517,7 @@
     packetCode _ = 17
     toPkt (UserAttribute a) = UserAttributePkt a
     fromPkt (UserAttributePkt a) = UserAttribute a
+    fromPkt _ = error "Cannot coerce non-UserAttribute packet"
 
 instance Pretty UserAttribute where
     pretty = pretty . toPkt
@@ -1436,6 +1532,7 @@
     packetCode _ = 18
     toPkt (SymEncIntegrityProtectedData a b) = SymEncIntegrityProtectedDataPkt a b
     fromPkt (SymEncIntegrityProtectedDataPkt a b) = SymEncIntegrityProtectedData a b
+    fromPkt _ = error "Cannot coerce non-SymEncIntegrityProtectedData packet"
 
 instance Pretty SymEncIntegrityProtectedData where
     pretty = pretty . toPkt
@@ -1449,6 +1546,7 @@
     packetCode _ = 19
     toPkt (ModificationDetectionCode a) = ModificationDetectionCodePkt a
     fromPkt (ModificationDetectionCodePkt a) = ModificationDetectionCode a
+    fromPkt _ = error "Cannot coerce non-ModificationDetectionCode packet"
 
 instance Pretty ModificationDetectionCode where
     pretty = pretty . toPkt
@@ -1463,6 +1561,7 @@
     packetCode _ = undefined -- FIXME
     toPkt (OtherPacket a b) = OtherPacketPkt a b
     fromPkt (OtherPacketPkt a b) = OtherPacket a b
+    fromPkt _ = error "Cannot coerce non-OtherPacket packet"
 
 instance Pretty OtherPacket where
     pretty = pretty . toPkt
@@ -1478,6 +1577,7 @@
     packetCode _ = undefined
     toPkt (BrokenPacket a b c) = BrokenPacketPkt a b c
     fromPkt (BrokenPacketPkt a b c) = BrokenPacket a b c
+    fromPkt _ = error "Cannot coerce non-BrokenPacket packet"
 
 instance Pretty BrokenPacket where
     pretty = pretty . toPkt
diff --git a/hOpenPGP.cabal b/hOpenPGP.cabal
--- a/hOpenPGP.cabal
+++ b/hOpenPGP.cabal
@@ -1,5 +1,5 @@
 Name:                hOpenPGP
-Version:             2.0
+Version:             2.1
 Synopsis:            native Haskell implementation of OpenPGP (RFC4880)
 Description:         native Haskell implementation of OpenPGP (RFC4880)
 Homepage:            http://floss.scru.org/hOpenPGP/
@@ -328,4 +328,4 @@
 source-repository this
   type:     git
   location: git://git.debian.org/users/clint/hOpenPGP.git
-  tag:      v1.11
+  tag:      v2.1
diff --git a/tests/suite.hs b/tests/suite.hs
--- a/tests/suite.hs
+++ b/tests/suite.hs
@@ -117,7 +117,7 @@
 testKeysExpiration expectsuccess keyfile = do
     ks <- runResourceT $ CB.sourceFile ("tests/data/" ++ keyfile) DC.$= conduitGet get DC.$= conduitToTKs DC.$$ CL.consume
     let Right verifieds = mapM (verifyTKWith (verifySigWith (verifyAgainstKeys ks)) Nothing) ks
-        tvalid = all (isTKTimeValid (posixSecondsToUTCTime (realToFrac 1400000000))) verifieds
+        tvalid = all (isTKTimeValid (posixSecondsToUTCTime (realToFrac (1400000000 :: Integer)))) verifieds
     assertEqual (keyfile ++ " key expiration") expectsuccess tvalid
 
 -- This needs a lot of work
