diff --git a/Benchmarks/Benchmarks.hs b/Benchmarks/Benchmarks.hs
--- a/Benchmarks/Benchmarks.hs
+++ b/Benchmarks/Benchmarks.hs
@@ -4,14 +4,15 @@
 
 import qualified Data.ByteString as B
 import Crypto.Random.AESCtr
+import Crypto.Random
 import System.IO.Unsafe (unsafePerformIO)
 import Data.IORef
 
-gen rng n = fst (genRandomBytes rng n)
+gen rng n = fst (cprgGenerate n rng)
 
 gen2 rngref n = unsafePerformIO $ do
     rng <- readIORef rngref
-    let (b, rng2) = genRandomBytes rng n
+    let (b, rng2) = cprgGenerate n rng
     writeIORef rngref rng2
     return b
 
diff --git a/Crypto/Random/AESCtr.hs b/Crypto/Random/AESCtr.hs
--- a/Crypto/Random/AESCtr.hs
+++ b/Crypto/Random/AESCtr.hs
@@ -12,142 +12,62 @@
 -- each block are generated the following way:
 --   aes (IV `xor` counter) -> 16 bytes output
 --
-{-# LANGUAGE CPP, PackageImports #-}
+{-# LANGUAGE CPP #-}
+{-# LANGUAGE BangPatterns #-}
 module Crypto.Random.AESCtr
     ( AESRNG
     , make
     , makeSystem
-    , genRandomBytes
     ) where
 
-import Control.Applicative ((<$>))
-
 import Crypto.Random
-import System.Random (RandomGen(..))
-import System.Entropy (getEntropy)
-#ifdef CIPHER_AES
-import qualified "cipher-aes" Crypto.Cipher.AES as AES
-#else
-import qualified "cryptocipher" Crypto.Cipher.AES as AES
-#endif
+import Crypto.Random.AESCtr.Internal
+import Control.Arrow (second)
 
 import Data.ByteString (ByteString)
 import qualified Data.ByteString as B
 
-import Data.Word
+import Data.Byteable
 import Data.Bits (xor, (.&.))
 
-#ifdef USE_CEREAL
-import Data.Serialize
-#else
-import Foreign.Ptr
-import Foreign.ForeignPtr.Unsafe (unsafeForeignPtrToPtr)
-import Foreign.Storable
-import qualified Data.ByteString.Internal as B
-#endif
-
-data Word128 = Word128 {-# UNPACK #-} !Word64 {-# UNPACK #-} !Word64
-
-{-| An opaque object containing an AES CPRNG -}
-data RNG = RNG
-    {-# UNPACK #-} !Word128
-    {-# UNPACK #-} !Word128
-    {-# UNPACK #-} !AES.Key
-
-data AESRNG = AESRNG { aesrngState :: RNG
-                     , aesrngCache :: ByteString }
+-- | AES Counter mode Pseudo random generator.
+--
+-- Provide a very good Cryptographic pseudo random generator
+-- that create pseudo random output based an AES cipher
+-- used in counter mode, initialized from random key, random IV
+-- and random nonce.
+--
+-- This CPRG uses 64 bytes of pure entropy to create its random state.
+--
+-- By default, this generator will automatically reseed after generating
+-- 1 megabyte of data.
+data AESRNG = AESRNG { aesrngState     :: !RNG
+                     , aesrngEntropy   :: EntropyPool
+                     , aesrngThreshold :: !Int -- ^ in number of generated block
+                     , aesrngCache     :: !ByteString }
 
 instance Show AESRNG where
     show _ = "aesrng[..]"
 
--- using serialize to grab a w128 as a non-negligeable cost,
--- the Bytestring pointer manipulation are much faster.
-#if USE_CEREAL
-
-put128 :: Word128 -> ByteString
-put128 (Word128 a b) = runPut (putWord64host a >> putWord64host b)
-
-get128 :: ByteString -> Word128
-get128 = either (\_ -> Word128 0 0) id . runGet (getWord64host >>= \a -> (getWord64host >>= \b -> return $ Word128 a b))
-
-#else
-
-put128 :: Word128 -> ByteString
-put128 (Word128 a b) = B.unsafeCreate 16 (write64 . castPtr)
-    where write64 :: Ptr Word64 -> IO ()
-          write64 ptr = poke ptr a >> poke (ptr `plusPtr` 8) b
-
-get128 :: ByteString -> Word128
-get128 (B.PS ps s _) = B.inlinePerformIO $ do
-    let ptr = castPtr (unsafeForeignPtrToPtr ps `plusPtr` s) :: Ptr Word64
-    a <- peek ptr
-    b <- peek (ptr `plusPtr` 8)
-    return $ Word128 a b
-#endif
-
-xor128 :: Word128 -> Word128 -> Word128
-xor128 (Word128 a1 b1) (Word128 a2 b2) = Word128 (a1 `xor` a2) (b1 `xor` b2)
-
-#ifdef CIPHER_AES
-add64 :: Word128 -> Word128
-add64 (Word128 a b) = if b >= (0xffffffffffffffff-63) then Word128 (a+1) (b+64) else Word128 a (b+64)
-#else
-add1 :: Word128 -> Word128
-add1 (Word128 a b) = if b == 0xffffffffffffffff then Word128 (a+1) 0 else Word128 a (b+1)
-#endif
-
-makeParams :: ByteString -> (AES.Key, ByteString, ByteString)
-makeParams b = (key, cnt, iv)
-    where
-#ifdef CIPHER_AES
-        key          = AES.initKey $ B.take 32 left2
-#else
-        (Right key)  = AES.initKey256 $ B.take 32 left2
-#endif
-        (cnt, left2) = B.splitAt 16 left1
-        (iv, left1)  = B.splitAt 16 b
+makeFrom :: EntropyPool -> B.ByteString -> AESRNG
+makeFrom entPool b = AESRNG
+    { aesrngState        = rng
+    , aesrngEntropy      = entPool
+    , aesrngThreshold    = 1024 -- in blocks generated, so 1mb
+    , aesrngCache        = B.empty }
+  where rng = makeRNG b
 
--- | make an AES RNG from a bytestring seed. the bytestring need to be at least 64 bytes.
--- if the bytestring is longer, the extra bytes will be ignored and will not take part in
--- the initialization.
+-- | make an AES RNG from an EntropyPool.
 --
--- use `makeSystem` to not have to deal with the generator seed.
-make :: B.ByteString -> Either GenError AESRNG
-make b
-    | B.length b < 64 = Left NotEnoughEntropy
-    | otherwise       = Right $ AESRNG { aesrngState = rng, aesrngCache = B.empty }
-        where
-            rng            = RNG (get128 iv) (get128 cnt) key
-            (key, cnt, iv) = makeParams b
-
-#ifdef CIPHER_AES
-chunkSize :: Int
-chunkSize = 1024
-
-genNextChunk :: RNG -> (ByteString, RNG)
-genNextChunk (RNG iv counter key) = (chunk, newrng)
-    where
-        newrng = RNG (get128 chunk) (add64 counter) key
-        chunk  = AES.genCTR key (AES.IV bytes) 1024
-        bytes  = put128 (iv `xor128` counter)
-#else
-chunkSize :: Int
-chunkSize = 16
-
-genNextChunk :: RNG -> (ByteString, RNG)
-genNextChunk (RNG iv counter key) = (chunk, newrng)
-    where
-        newrng = RNG (get128 chunk) (add1 counter) key
-        chunk  = AES.encrypt key bytes
-        bytes  = put128 (iv `xor128` counter)
-#endif
+-- use `makeSystem` to not have to deal with the entropy pool.
+make :: EntropyPool -> AESRNG
+make entPool = makeFrom entPool b
+  where !b = toBytes $ grabEntropy 64 entPool
 
 -- | Initialize a new AES RNG using the system entropy.
+-- {-# DEPRECATED makeSystem "use cprgCreate with an entropy pool" #-}
 makeSystem :: IO AESRNG
-makeSystem = ofRight . make <$> getEntropy 64
-    where
-        ofRight (Left _)  = error "ofRight on a Left value"
-        ofRight (Right x) = x
+makeSystem = make `fmap` createEntropyPool
 
 -- | get a Random number of bytes from the RNG.
 -- it generate randomness by block of chunkSize bytes and will returns
@@ -157,42 +77,53 @@
     | n <= chunkSize = genNextChunk rng
     | otherwise      = let (bs, rng') = acc 0 [] rng
                         in (B.concat bs, rng')
-    where
-        acc l bs g
+  where acc l bs g
             | l * chunkSize >= n = (bs, g)
             | otherwise          = let (b, g') = genNextChunk g
                                     in acc (l+1) (b:bs) g'
 
-genRandomBytes :: AESRNG -> Int -> (ByteString, AESRNG)
-genRandomBytes rng n
+genRanBytesNoCheck :: AESRNG -> Int -> (ByteString, AESRNG)
+genRanBytesNoCheck rng n
     | B.length (aesrngCache rng) >= n = let (b1,b2) = B.splitAt n (aesrngCache rng)
                                          in (b1, rng { aesrngCache = b2 })
     | otherwise                       =
-            let (b, rng') = genRandomBytesState (aesrngState rng) n
-                (b1, b2)  = B.splitAt n b
-             in (b1, rng { aesrngState = rng', aesrngCache = b2 })
+        let (b, rng') = genRandomBytesState (aesrngState rng) n
+            (b1, b2)  = B.splitAt n b
+         in (b1, rng { aesrngState = rng', aesrngCache = b2 })
 
-reseedState b rng@(RNG _ cnt1 _) = RNG (get128 r16 `xor128` get128 iv2) (cnt1 `xor128` get128 cnt2) key2
-    where (r16, _)          = genNextChunk rng
-          (key2, cnt2, iv2) = makeParams b
+-- | generate a random set of bytes
+genRanBytes :: AESRNG -> Int -> (ByteString, AESRNG)
+genRanBytes rng n = second reseedThreshold $ genRanBytesNoCheck rng n
 
-instance CryptoRandomGen AESRNG where
-    newGen           = make
-    genSeedLength    = 64
-    genBytes len rng = Right $ genRandomBytes rng len
-    reseed b rng
-        | B.length b < 64 = Left NotEnoughEntropy
-        | otherwise       = Right $ rng { aesrngState = reseedState b (aesrngState rng) }
+reseedThreshold :: AESRNG -> AESRNG
+reseedThreshold rng
+    | getNbChunksGenerated (aesrngState rng) >= lvl =
+         let newRngState = makeRNG $ toBytes $ grabEntropy 64 (aesrngEntropy rng)
+          in rng { aesrngState = newRngState }
+    | otherwise  = rng
+  where lvl = aesrngThreshold rng
 
+instance CPRG AESRNG where
+    cprgCreate                      = make
+    cprgSetReseedThreshold lvl rng  = reseedThreshold (rng { aesrngThreshold = if nbChunks > 0 then nbChunks else 1 })
+      where nbChunks = lvl `div` chunkSize
+    cprgGenerate len rng            = genRanBytes rng len
+    cprgGenerateWithEntropy len rng =
+        let ent        = toBytes $ grabEntropy len (aesrngEntropy rng)
+            (bs, rng') = genRanBytes rng len
+         in (B.pack $ B.zipWith xor ent bs, rng')
+    cprgFork rng = let (b,rng') = genRanBytes rng 64
+                    in (rng', makeFrom (aesrngEntropy rng) b)
+
+{-
 instance RandomGen AESRNG where
     next rng =
-        let (bs, rng') = genRandomBytes rng 16 in
+        let (bs, rng') = genRanBytes rng 16 in
         let (Word128 a _) = get128 bs in
         let n = fromIntegral (a .&. 0x7fffffff) in
         (n, rng')
     split rng =
-        let (bs, rng') = genRandomBytes rng 64 in
-        case make bs of
-            Left _      -> error "assert"
-            Right rng'' -> (rng', rng'')
+        let rng' = make (aesrngEntropy rng)
+         in (rng, rng')
     genRange _ = (0, 0x7fffffff)
+-}
diff --git a/Crypto/Random/AESCtr/Internal.hs b/Crypto/Random/AESCtr/Internal.hs
new file mode 100644
--- /dev/null
+++ b/Crypto/Random/AESCtr/Internal.hs
@@ -0,0 +1,42 @@
+-- |
+-- Module      : Crypto.Random.AESCtr.Internal
+-- License     : BSD-style
+-- Maintainer  : Vincent Hanquez <vincent@snarc.org>
+-- Stability   : stable
+-- Portability : unknown
+--
+{-# LANGUAGE CPP #-}
+{-# LANGUAGE BangPatterns #-}
+module Crypto.Random.AESCtr.Internal where
+
+import qualified Crypto.Cipher.AES as AES
+
+import Data.ByteString (ByteString)
+import qualified Data.ByteString as B
+
+{-| An opaque object containing an AES CPRNG -}
+data RNG = RNG !AES.AESIV !Int !AES.AES
+
+getNbChunksGenerated :: RNG -> Int
+getNbChunksGenerated (RNG _ c _) = c
+
+makeParams :: ByteString -> (AES.AES, AES.AESIV)
+makeParams b = key `seq` iv `seq` (key, iv)
+  where (keyBS, r1) = B.splitAt 32 b
+        (cnt, _)    = B.splitAt 16 r1
+        !key        = AES.initAES keyBS
+        !iv         = AES.aesIV_ $ B.copy cnt
+
+makeRNG :: ByteString -> RNG
+makeRNG b = RNG iv 0 key
+  where (key,iv) = makeParams b
+
+chunkSize :: Int
+chunkSize = 1024
+
+genNextChunk :: RNG -> (ByteString, RNG)
+genNextChunk (RNG counter nbChunks key) =
+    chunk `seq` newrng `seq` (chunk, newrng)
+  where
+        newrng = RNG newCounter (nbChunks+1) key
+        (chunk,newCounter) = AES.genCounter key counter chunkSize
diff --git a/cprng-aes.cabal b/cprng-aes.cabal
--- a/cprng-aes.cabal
+++ b/cprng-aes.cabal
@@ -1,5 +1,5 @@
 Name:                cprng-aes
-Version:             0.2.5
+Version:             0.6.1
 Description:         
     Simple crypto pseudo-random-number-generator with really good randomness property.
     .
@@ -30,37 +30,24 @@
 Homepage:            http://github.com/vincenthz/hs-cprng-aes
 data-files:          README.md
 
-Flag fastaes
-  Description:       Use fast AES if available
-  Default:           True
-
-Flag cereal
-  Description:       Use cereal
-  Default:           False
-
 Library
   Build-Depends:     base >= 3 && < 5
                    , bytestring
-                   , random
-                   , crypto-api >= 0.8
-                   , entropy >= 0.2
+                   , byteable
+                   , crypto-random >= 0.0.7 && < 0.1
+                   , cipher-aes >= 0.2.9 && < 0.3
+
   Exposed-modules:   Crypto.Random.AESCtr
+  Other-modules:     Crypto.Random.AESCtr.Internal
   ghc-options:       -Wall
 
-  if flag(fastaes) && (arch(i386) || arch(x86_64))
-    cpp-options:     -DCIPHER_AES
-    Build-Depends:   cipher-aes >= 0.1 && < 0.2
-  else
-    Build-Depends:   cryptocipher
-  if flag(cereal)
-    Build-Depends:   cereal >= 0.3.0 && < 0.4.0
-
 Benchmark bench-cprng-aes
   hs-source-dirs:    Benchmarks
   Main-Is:           Benchmarks.hs
   type:              exitcode-stdio-1.0
   Build-depends:     base >= 4 && < 5
                    , bytestring
+                   , crypto-random
                    , cprng-aes
                    , criterion
                    , mtl
