diff --git a/Crypto/Classes.hs b/Crypto/Classes.hs
--- a/Crypto/Classes.hs
+++ b/Crypto/Classes.hs
@@ -126,23 +126,12 @@
 blockSizeBytes = fmap (`div` 8) blockSize
 
 -- |Asymetric ciphers (common ones being RSA or EC based)
-class (Serialize p) => AsymCipher p where
-  buildKeyPair :: CryptoRandomGen g => g -> BitLength -> Maybe ((p,p),g) -- ^ build a public/private key pair using the provided generator
-  encryptAsym     :: p -> B.ByteString -> B.ByteString	-- ^ Asymetric encryption
-  decryptAsym     :: p -> B.ByteString -> B.ByteString  -- ^ Asymetric decryption
-  asymKeyLength   :: p -> BitLength
-
--- | `signUsing d k msg` Returns a signature (not a message + signature) for `msg`
--- by hashing into a digest asTypeOf `d` and encrypting using the asymetric key `k`.
---
--- Expect a "Signature" class to appear in a future crypto-api
--- (this function might become depricated pending discussion)
-signUsing :: (Hash c d, AsymCipher p) => d -> p -> L.ByteString -> B.ByteString
-signUsing d p = encryptAsym p . Data.Serialize.encode . hashFunc d
-
--- | Like `signUsing` but for strict ByteStrings.
-signUsing' :: (Hash c d, AsymCipher p) => d -> p -> B.ByteString -> B.ByteString
-signUsing' d p = encryptAsym p . Data.Serialize.encode . hashFunc' d
+class (Serialize p, Serialize v) => AsymCipher p v where
+  buildKeyPair :: CryptoRandomGen g => g -> BitLength -> Either GenError ((p,v),g) -- ^ build a public/private key pair using the provided generator
+  encryptAsym      :: (CryptoRandomGen g) => g -> p -> B.ByteString -> Either GenError (B.ByteString,g)	-- ^ Asymetric encryption
+  decryptAsym      :: v -> B.ByteString -> Maybe B.ByteString  -- ^ Asymetric decryption
+  publicKeyLength  :: p -> BitLength
+  privateKeyLength :: v -> BitLength
 
 -- | A stream cipher class.  Instance are expected to work on messages as small as one byte
 -- The length of the resulting cipher text should be equal
@@ -156,8 +145,8 @@
 -- | A class for signing operations which inherently can not be as generic
 -- as asymetric ciphers (ex: DSA).
 class (Serialize p, Serialize v) => Signing p v | p -> v, v -> p  where
-  sign	 :: v -> L.ByteString -> B.ByteString
+  sign	 :: CryptoRandomGen g => g -> v -> L.ByteString -> Either GenError (B.ByteString, g)
   verify :: p -> L.ByteString -> B.ByteString -> Bool
-  buildSigningPair :: CryptoRandomGen g => g -> BitLength -> Maybe ((p, v), g)
+  buildSigningPair :: CryptoRandomGen g => g -> BitLength -> Either GenError ((p, v), g)
   signingKeyLength :: v -> BitLength
   verifyingKeyLength :: p -> BitLength
diff --git a/Crypto/Modes.hs b/Crypto/Modes.hs
--- a/Crypto/Modes.hs
+++ b/Crypto/Modes.hs
@@ -8,7 +8,12 @@
   Be aware there are no tests for CFB mode yet.  See "Test.Crypto".
 -}
 module Crypto.Modes
-	( ecb, unEcb
+	(
+	-- * Initialization Vector Type (for all ciphers for all modes that use IVs)
+	  IV
+	, getIV, getIVIO
+	-- * Blockcipher modes of operation.  Note name' (with a prime) means strict, without a prime means lazy bytestrings.
+	, ecb, unEcb
 	, cbc, unCbc
 	, cfb, unCfb
 	, ofb, unOfb
@@ -16,8 +21,9 @@
 	, cbc', unCbc'
 	, cfb', unCfb'
 	, ofb', unOfb'
-	, IV
-	, getIV, getIVIO
+	-- * Authentication modes
+	, cbcMac', cbcMac
+	-- * Combined modes (nothing here yet)
 	-- , gmc
 	-- , xts
 	-- , ccm
@@ -37,7 +43,9 @@
 import Control.Monad (liftM)
 
 -- |Initilization Vectors for BlockCipher implementations (IV k) are used
--- for various modes and guarrenteed to be blockSize bits long.
+-- for various modes and guarrenteed to be blockSize bits long.  The common
+-- ways to obtain an IV are to generate one ('getIV' or 'getIVIO') or to
+-- use one provided with the ciphertext (using the 'Serialize' instance of IV).
 data IV k = IV { initializationVector :: B.ByteString } deriving (Eq, Ord, Show)
 
 -- gather a specified number of bytes from the list of bytestrings
@@ -105,6 +113,12 @@
 	let c = encryptBlock k (zwp' iv b)
 	    (cs, ivFinal) = go bs c
 	in (c:cs, ivFinal)
+
+cbcMac' :: BlockCipher k => k -> B.ByteString -> B.ByteString
+cbcMac' k pt = encode $ snd $ cbc' k (IV (B.replicate (blockSize `for` k) 0)) pt
+
+cbcMac :: BlockCipher k => k -> L.ByteString -> L.ByteString
+cbcMac k pt = L.fromChunks [encode $ snd $ cbc k (IV (B.replicate (blockSize `for` k) 0)) pt]
 
 -- |Cipher block chaining decryption for strict bytestrings
 unCbc' :: BlockCipher k => k -> IV k -> B.ByteString -> (B.ByteString, IV k)
diff --git a/Crypto/Padding.hs b/Crypto/Padding.hs
--- a/Crypto/Padding.hs
+++ b/Crypto/Padding.hs
@@ -74,7 +74,7 @@
   pLen = fromIntegral padLen
   (msg,pad) = B.splitAt (bsLen - pLen) bs
 
--- unpad a strict bytestring without checking the pad bytes and length any more than necessary.
+-- |unpad a strict bytestring without checking the pad bytes and length any more than necessary.
 unpadPKCS5 :: B.ByteString -> B.ByteString
 unpadPKCS5 bs = if bsLen == 0 then bs else msg
   where
diff --git a/Crypto/Random.hs b/Crypto/Random.hs
--- a/Crypto/Random.hs
+++ b/Crypto/Random.hs
@@ -152,7 +152,7 @@
                         then Right (B.concat $ L.toChunks rnd, SysRandom rest)
                         else Left $ GenErrorOther "Error obtaining enough bytes from system random for given request"
         reseed _ _ = Left NeedsInfiniteSeed
-	newGenIO = getSystemGen
+        newGenIO = getSystemGen
 
 -- | While the safety and wisdom of a splitting function depends on the properties of the generator being split,
 -- several arguments from informed people indicate such a function is safe for NIST SP 800-90 generators.
diff --git a/crypto-api.cabal b/crypto-api.cabal
--- a/crypto-api.cabal
+++ b/crypto-api.cabal
@@ -1,5 +1,5 @@
 name:           crypto-api
-version:        0.3.1
+version:        0.4
 license:        BSD3
 license-file:   LICENSE
 copyright:      Thomas DuBuisson <thomas.dubuisson@gmail.com>, Dominic Steinitz (see Data.LargeWord module)
@@ -52,7 +52,7 @@
   Build-Depends: base == 4.*,
                  bytestring >= 0.9 && < 0.10,
                  cereal >= 0.2 && < 0.4,
-                 tagged == 0.1.*
+                 tagged >= 0.1 && < 0.3
   ghc-options:   -O2
   hs-source-dirs:
   exposed-modules: Crypto.Classes, Crypto.Types, Crypto.HMAC, Data.LargeWord, Crypto.Modes, System.Crypto.Random, Crypto.Random, Crypto.Padding
