diff --git a/changes.md b/changes.md
--- a/changes.md
+++ b/changes.md
@@ -1,3 +1,7 @@
+# 0.3.0.0
+    - Better exception type (does no longer leak private information)
+    - 'Data.CryptoID.Poly' now supports padding the plaintext to a certain length before encryption
+
 # 0.2.0.0
     - Rename 'Data.CryptoID.Poly' to 'Data.CryptoID.ByteString'
     - Introduce 'Data.CryptoID.Poly' doing actual serialization
@@ -12,3 +16,4 @@
 # 0.0.0
 
 First published version
+
diff --git a/cryptoids.cabal b/cryptoids.cabal
--- a/cryptoids.cabal
+++ b/cryptoids.cabal
@@ -1,5 +1,5 @@
 name: cryptoids
-version: 0.2.0.0
+version: 0.3.0.0
 cabal-version: >=1.10
 build-type: Simple
 license: BSD3
diff --git a/src/Data/CryptoID/ByteString.hs b/src/Data/CryptoID/ByteString.hs
--- a/src/Data/CryptoID/ByteString.hs
+++ b/src/Data/CryptoID/ByteString.hs
@@ -29,6 +29,7 @@
 import Data.Binary.Get
 
 import Data.ByteString (ByteString)
+import qualified Data.ByteString as ByteString
 import qualified Data.ByteString.Char8 as ByteString.Char
 
 import qualified Data.ByteString.Lazy as Lazy (ByteString)
@@ -100,10 +101,19 @@
 
 
 -- | Error cases that can be encountered during 'encrypt' and 'decrypt'
+--
+-- Care has been taken to ensure that presenting values of 'CryptoIDError' to an
+-- attacker leaks no plaintext (it does leak information about the length of the
+-- plaintext).
 data CryptoIDError
   = AlgorithmError CryptoError
     -- ^ One of the underlying cryptographic algorithms
     --   ('CryptoHash' or 'CryptoCipher') failed.
+  | PlaintextIsWrongLength Int
+    -- ^ The length of the plaintext is not a multiple of the block size of
+    --   'CryptoCipher'
+    --
+    -- The length of the offending plaintext is included.
   | NamespaceHashIsWrongLength ByteString
     -- ^ The length of the digest produced by 'CryptoHash' does
     --   not match the block size of 'CryptoCipher'.
@@ -112,10 +122,12 @@
     --
     -- This error should not occur and is included primarily
     -- for sake of totality.
-  | CiphertextConversionFailed
-    -- ^ The produced 'ByteString' is the wrong length for conversion into a
-    --   ciphertext.
-  | DeserializationError (Lazy.ByteString, ByteOffset, String)
+  | CiphertextConversionFailed ByteString
+    -- ^ The produced 'ByteString' is the wrong length for deserialization into
+    --   a ciphertext.
+    --
+    -- The offending 'ByteString' is included.
+  | DeserializationError
     -- ^ The plaintext obtained by decrypting a ciphertext with the given
     --   'CryptoIDKey' in the context of the @namespace@ could not be
     --   deserialized into a value of the expected @payload@-type.
@@ -183,8 +195,8 @@
 encrypt (keyMaterial -> key) plaintext = do
   cipher <- cryptoFailable (cipherInit key :: CryptoFailable CryptoCipher)
   namespace <- namespace' (Proxy :: Proxy namespace)
-  when (ByteArray.length plaintext `mod` blockSize cipher /= 0) $
-    throwM CiphertextConversionFailed
+  when (ByteString.length plaintext `mod` blockSize cipher /= 0) $
+    throwM . PlaintextIsWrongLength $ ByteString.length plaintext
   return . CryptoID $ cbcEncrypt cipher namespace plaintext
 
 
diff --git a/src/Data/CryptoID/Poly.hs b/src/Data/CryptoID/Poly.hs
--- a/src/Data/CryptoID/Poly.hs
+++ b/src/Data/CryptoID/Poly.hs
@@ -33,11 +33,15 @@
 
 import Data.Binary
 
+import Data.Monoid
+
 import Data.ByteString (ByteString)
+import qualified Data.ByteString as ByteString
 import qualified Data.ByteString.Lazy as Lazy.ByteString
 
 import GHC.TypeLits
 
+import Control.Monad
 import Control.Monad.Catch (MonadThrow(..))
   
 
@@ -50,10 +54,22 @@
            ( KnownSymbol namespace
            , MonadThrow m
            , Binary a
-           ) => (ByteString -> m c) -> CryptoIDKey -> a -> m (CryptoID namespace c)
-encrypt encode' key plaintext = do
-  cID <- ByteString.encrypt key . Lazy.ByteString.toStrict $ encode plaintext
+           ) => Maybe Int -- ^ Ensure the resulting ciphertext is of this size (needs to be a multiple of the block size of 'CryptoCipher' in bytes, otherwise an exception will be thrown at runtime)
+        -> (ByteString -> m c)
+        -> CryptoIDKey
+        -> a
+        -> m (CryptoID namespace c)
+encrypt pLength encode' key plaintext = do
+  cID <- ByteString.encrypt key <=< pad . Lazy.ByteString.toStrict $ encode plaintext
   _ciphertext encode' cID
+  where
+    pad str
+      | Just l <- pLength
+      , l' <= l           = return $ str <> ByteString.replicate (l - l') 0
+      | Just _ <- pLength = throwM $ CiphertextConversionFailed str
+      | otherwise         = return str
+      where
+        l' = ByteString.length str
 
 
 -- | Decrypt a serialized value
@@ -67,7 +83,7 @@
   plaintext <- Lazy.ByteString.fromStrict <$> ByteString.decrypt key cID'
 
   case decodeOrFail plaintext of
-    Left err -> throwM $ DeserializationError err
+    Left _ -> throwM DeserializationError
     Right (rem, _, res)
       | Lazy.ByteString.all (== 0) rem -> return res
       | otherwise -> throwM InvalidNamespaceDetected
