diff --git a/Crypto/Cipher/AES.hs b/Crypto/Cipher/AES.hs
--- a/Crypto/Cipher/AES.hs
+++ b/Crypto/Cipher/AES.hs
@@ -11,15 +11,17 @@
 import Data.Word
 import Data.Vector.Unboxed (Vector, (//))
 import qualified Data.Vector.Unboxed as V
+import Data.List (foldl')
 import Data.Bits
 import Data.ByteString (ByteString)
 import qualified Data.ByteString as B
 import qualified Data.ByteString.Unsafe as B
-import Control.Monad.State.Strict
 
-newtype Key = Key (Int, Vector Word8)
+newtype Key = Key (Vector Word8)
 	deriving (Show,Eq)
 
+type AESState = Vector Word8
+
 {- | encrypt with the key a bytestring and returns the encrypted bytestring -}
 encrypt :: Key -> B.ByteString -> B.ByteString
 encrypt key b
@@ -59,29 +61,17 @@
 	| B.length b == sz = Right $ coreExpandKey nbr (V.generate sz $ B.unsafeIndex b)
 	| otherwise        = Left "wrong key size"
 
-aesMain :: Int -> Key -> Vector Word8 -> Vector Word8
-aesMain nbr key block = flip execState block $ do
-	addRoundKey $ createRoundKey key 0
-
-	forM_ [1..nbr-1] $ \i -> do
-		modify shiftRows
-		mixColumns
-		addRoundKey $ createRoundKey key i
-
-        modify shiftRows
-        addRoundKey $ createRoundKey key nbr
-
-aesMainInv :: Int -> Key -> Vector Word8 -> Vector Word8
-aesMainInv nbr key block = flip execState block $ do
-	addRoundKey $ createRoundKey key nbr
-        
-	forM_ (reverse [1..nbr-1]) $ \i -> do
-		modify shiftRowsInv
-		addRoundKey $ createRoundKey key i
-		mixColumnsInv
+aesMain :: Int -> Key -> AESState -> AESState
+aesMain nbr key block =
+	addRoundKey key nbr $! shiftRows $! mrounds $! addRoundKey key 0 block
+	where
+		mrounds b = foldl' (\bk i -> addRoundKey key i $! mixColumns $! shiftRows bk) b [1..nbr-1]
 
-        modify shiftRowsInv
-        addRoundKey $ createRoundKey key 0
+aesMainInv :: Int -> Key -> AESState -> AESState
+aesMainInv nbr key block =
+	addRoundKey key 0 $! shiftRowsInv $! mrounds $! addRoundKey key nbr block
+	where
+		mrounds b = foldl' (\bk i -> mixColumnsInv $! addRoundKey key i $! shiftRowsInv bk) b (reverse [1..nbr-1])
 
 {- 0 -> 0, 1 -> 4, ... -}
 swapIndexes :: Vector Int
@@ -90,7 +80,7 @@
 swapIndex i = V.unsafeIndex swapIndexes i
 
 coreExpandKey :: Int -> Vector Word8 -> Key
-coreExpandKey nbr vkey = Key (nbr, V.concat (ek0 : ekN))
+coreExpandKey nbr vkey = Key (V.concat (ek0 : ekN))
 	where
 		ek0 = vkey
 		ekN = reverse $ snd $ foldl generateFold (ek0, []) [1..nbr]
@@ -117,7 +107,7 @@
 		cR0 it r0 r1 r2 r3 =
 			(mSbox r1 `xor` mRcon it, mSbox r2, mSbox r3, mSbox r0)
 
-shiftRows :: Vector Word8 -> Vector Word8
+shiftRows :: AESState -> AESState
 shiftRows ost =
 	let st = V.map mSbox ost in
 	st // [ (7, V.unsafeIndex st 4), (4, V.unsafeIndex st 5), (5, V.unsafeIndex st 6), (6, V.unsafeIndex st 7)
@@ -125,33 +115,40 @@
 	      , (13, V.unsafeIndex st 12), (14, V.unsafeIndex st 13), (15, V.unsafeIndex st 14), (12, V.unsafeIndex st 15)
 	      ]
 
-addRoundKey :: Vector Word8 -> State (Vector Word8) ()
-addRoundKey rk = modify (\state -> V.zipWith (\v1 v2 -> v1 `xor` v2) state rk)
+addRoundKey :: Key -> Int -> AESState -> AESState
+addRoundKey (Key key) i = V.zipWith (\v1 v2 -> v1 `xor` v2) rk
+	where
+		rk = V.generate 16 (\n -> V.unsafeIndex key (16 * i + swapIndex n))
 
-mixColumns :: State (Vector Word8) ()
-mixColumns =
-	forM_ [0..3] $ \i -> do
-		state <- get
-		let cpy0 = V.unsafeIndex state (0 * 4 + i)
-		let cpy1 = V.unsafeIndex state (1 * 4 + i)
-		let cpy2 = V.unsafeIndex state (2 * 4 + i)
-		let cpy3 = V.unsafeIndex state (3 * 4 + i)
 
-		let state0  = gm2 cpy0 `xor` gm1 cpy3 `xor` gm1 cpy2 `xor` gm3 cpy1
-                let state4  = gm2 cpy1 `xor` gm1 cpy0 `xor` gm1 cpy3 `xor` gm3 cpy2
-                let state8  = gm2 cpy2 `xor` gm1 cpy1 `xor` gm1 cpy0 `xor` gm3 cpy3
-                let state12 = gm2 cpy3 `xor` gm1 cpy2 `xor` gm1 cpy1 `xor` gm3 cpy0
-
-		put (state // [ (i, state0), (4+i, state4), (8+i, state8), (12+i, state12) ])
+mixColumns :: AESState -> AESState
+mixColumns state =
+	let (state0, state4, state8, state12)  = pr 0 in
+	let (state1, state5, state9, state13)  = pr 1 in
+	let (state2, state6, state10, state14) = pr 2 in
+	let (state3, state7, state11, state15) = pr 3 in
+	state //
+		[ (0,state0), (1,state1), (2,state2), (3,state3)
+		, (4,state4), (5,state5), (6,state6), (7,state7)
+		, (8,state8), (9,state9), (10,state10), (11,state11)
+		, (12,state12), (13,state13), (14,state14), (15,state15)
+		]
 	where
+		pr i =
+			let cpy0 = V.unsafeIndex state (0 * 4 + i) in
+			let cpy1 = V.unsafeIndex state (1 * 4 + i) in
+			let cpy2 = V.unsafeIndex state (2 * 4 + i) in
+			let cpy3 = V.unsafeIndex state (3 * 4 + i) in
+
+			(gm2 cpy0 `xor` gm1 cpy3 `xor` gm1 cpy2 `xor` gm3 cpy1
+			,gm2 cpy1 `xor` gm1 cpy0 `xor` gm1 cpy3 `xor` gm3 cpy2
+			,gm2 cpy2 `xor` gm1 cpy1 `xor` gm1 cpy0 `xor` gm3 cpy3
+			,gm2 cpy3 `xor` gm1 cpy2 `xor` gm1 cpy1 `xor` gm3 cpy0)
 		gm1 a = a
 		gm2 a = V.unsafeIndex gmtab2 $ fromIntegral a
 		gm3 a = V.unsafeIndex gmtab3 $ fromIntegral a
 
-createRoundKey :: Key -> Int -> Vector Word8
-createRoundKey (Key (_, key)) i = V.generate 16 (\n -> V.unsafeIndex key (16 * i + swapIndex n))
-
-shiftRowsInv :: Vector Word8 -> Vector Word8
+shiftRowsInv :: AESState -> AESState
 shiftRowsInv st =
 	let nst = st //
 		[ (5, V.unsafeIndex st 4), (6, V.unsafeIndex st 5), (7, V.unsafeIndex st 6), (4, V.unsafeIndex st 7)
@@ -160,31 +157,38 @@
 		] in
 	V.map mRsbox nst
 
-mixColumnsInv :: State (Vector Word8) ()
-mixColumnsInv =
-	forM_ [0..3] $ \i -> do
-		state <- get
-		let cpy0 = V.unsafeIndex state (0 * 4 + i)
-		let cpy1 = V.unsafeIndex state (1 * 4 + i)
-		let cpy2 = V.unsafeIndex state (2 * 4 + i)
-		let cpy3 = V.unsafeIndex state (3 * 4 + i)
-
-		let state0  = gm14 cpy0 `xor` gm9 cpy3 `xor` gm13 cpy2 `xor` gm11 cpy1
-		let state4  = gm14 cpy1 `xor` gm9 cpy0 `xor` gm13 cpy3 `xor` gm11 cpy2
-		let state8  = gm14 cpy2 `xor` gm9 cpy1 `xor` gm13 cpy0 `xor` gm11 cpy3
-		let state12 = gm14 cpy3 `xor` gm9 cpy2 `xor` gm13 cpy1 `xor` gm11 cpy0
-
-		put (state // [ (i, state0), (4+i, state4), (8+i, state8), (12+i, state12) ])
+mixColumnsInv :: AESState -> AESState
+mixColumnsInv state =
+	let (state0, state4, state8, state12)  = pr 0 in
+	let (state1, state5, state9, state13)  = pr 1 in
+	let (state2, state6, state10, state14) = pr 2 in
+	let (state3, state7, state11, state15) = pr 3 in
+	state //
+		[ (0,state0), (1,state1), (2,state2), (3,state3)
+		, (4,state4), (5,state5), (6,state6), (7,state7)
+		, (8,state8), (9,state9), (10,state10), (11,state11)
+		, (12,state12), (13,state13), (14,state14), (15,state15)
+		]
 	where
+		pr i = 
+			let cpy0 = V.unsafeIndex state (0 * 4 + i) in
+			let cpy1 = V.unsafeIndex state (1 * 4 + i) in
+			let cpy2 = V.unsafeIndex state (2 * 4 + i) in
+			let cpy3 = V.unsafeIndex state (3 * 4 + i) in
+
+			(gm14 cpy0 `xor` gm9 cpy3 `xor` gm13 cpy2 `xor` gm11 cpy1
+			,gm14 cpy1 `xor` gm9 cpy0 `xor` gm13 cpy3 `xor` gm11 cpy2
+			,gm14 cpy2 `xor` gm9 cpy1 `xor` gm13 cpy0 `xor` gm11 cpy3
+			,gm14 cpy3 `xor` gm9 cpy2 `xor` gm13 cpy1 `xor` gm11 cpy0)
 		gm14 a = V.unsafeIndex gmtab14 $ fromIntegral a
 		gm13 a = V.unsafeIndex gmtab13 $ fromIntegral a
 		gm11 a = V.unsafeIndex gmtab11 $ fromIntegral a
 		gm9 a  = V.unsafeIndex gmtab9 $ fromIntegral a
 
-swapBlock :: ByteString -> Vector Word8
+swapBlock :: ByteString -> AESState
 swapBlock b = V.generate 16 (\i -> B.unsafeIndex b $ swapIndex i)
 
-swapBlockInv :: Vector Word8 -> ByteString
+swapBlockInv :: AESState -> ByteString
 swapBlockInv v = B.pack $ map (V.unsafeIndex v . swapIndex) [0..15]
 
 mSbox :: Word8 -> Word8
diff --git a/Crypto/Cipher/RSA.hs b/Crypto/Cipher/RSA.hs
--- a/Crypto/Cipher/RSA.hs
+++ b/Crypto/Cipher/RSA.hs
@@ -20,7 +20,6 @@
 	) where
 
 import Control.Arrow (first)
-import Control.Monad.Error ()
 import Crypto.Random
 import Data.ByteString (ByteString)
 import qualified Data.ByteString as B
@@ -56,14 +55,12 @@
 type HashF = ByteString -> ByteString
 type HashASN1 = ByteString
 
-{-
 #if ! (MIN_VERSION_base(4,3,0))
 instance Monad (Either Error) where
 	return          = Right
 	(Left x) >>= _  = Left x
 	(Right x) >>= f = f x
 #endif
--}
 
 padPKCS1 :: CryptoRandomGen g => g -> Int -> ByteString -> Either Error (ByteString, g)
 padPKCS1 rng len m = do
diff --git a/cryptocipher.cabal b/cryptocipher.cabal
--- a/cryptocipher.cabal
+++ b/cryptocipher.cabal
@@ -1,5 +1,5 @@
 Name:                cryptocipher
-Version:             0.2.3
+Version:             0.2.4
 Description:         Symmetrical Block, Stream and PubKey Ciphers
 License:             BSD3
 License-file:        LICENSE
@@ -21,7 +21,6 @@
                    , bytestring
                    , vector
                    , crypto-api >= 0.2
-                   , mtl
   Exposed-modules:   Crypto.Cipher.RC4
                      Crypto.Cipher.AES
                      Crypto.Cipher.Camellia
