diff --git a/Data/SecureMem.hs b/Data/SecureMem.hs
--- a/Data/SecureMem.hs
+++ b/Data/SecureMem.hs
@@ -25,90 +25,70 @@
     , withSecureMemCopy
     -- * convertion
     , secureMemFromByteString
+    , secureMemFromByteable
     ) where
 
-import Foreign.C.Types
-import Foreign.ForeignPtr (withForeignPtr, finalizeForeignPtr)
-import Foreign.Ptr
-#if MIN_VERSION_base(4,6,0)
-import GHC.Types (Int(..))
-import GHC.ForeignPtr (ForeignPtr(..), ForeignPtrContents(..), mallocForeignPtrBytes, addForeignPtrConcFinalizer)
-import GHC.Prim (sizeofMutableByteArray#)
-import GHC.Ptr (Ptr(..))
+import           Foreign.ForeignPtr (withForeignPtr)
+import           Foreign.Ptr
+import           Data.Word (Word8)
+#if MIN_VERSION_base(4,9,0)
+import           Data.Semigroup
+import           Data.Foldable (toList)
 #else
-import Foreign.ForeignPtr (ForeignPtr, mallocForeignPtrBytes)
+import           Data.Monoid
 #endif
-import Data.Word (Word8)
-import Data.Monoid
-import Control.Applicative
-import Control.Monad (foldM, void)
-import Data.ByteString (ByteString)
-import Data.Byteable
-import qualified Data.ByteString.Internal as B
+import           Control.Applicative
+import           Data.Byteable
 
+import           Data.ByteString (ByteString)
+import           Data.ByteArray  (ScrubbedBytes)
+import qualified Data.ByteArray as B
+import qualified Data.Memory.PtrMethods as B (memSet)
+
+import qualified Data.ByteString.Internal as BS
+
+#if MIN_VERSION_base(4,4,0)
+import System.IO.Unsafe (unsafeDupablePerformIO)
+#else
+import System.IO.Unsafe (unsafePerformIO)
+#endif
+
+pureIO :: IO a -> a
+#if MIN_VERSION_base(4,4,0)
+pureIO = unsafeDupablePerformIO
+#else
+pureIO = unsafePerformIO
+#endif
+
 -- | SecureMem is a memory chunk which have the properties of:
 --
 -- * Being scrubbed after its goes out of scope.
+--
 -- * A Show instance that doesn't actually show any content
+--
 -- * A Eq instance that is constant time
-#if MIN_VERSION_base(4,6,0)
-newtype SecureMem = SecureMem { getForeignPtr :: ForeignPtr Word8 }
-#else
-data SecureMem = SecureMem { getForeignPtr :: ForeignPtr Word8, secureMemGetSize :: Int }
-#endif
+--
+newtype SecureMem = SecureMem ScrubbedBytes
 
-#if MIN_VERSION_base(4,6,0)
--- | Return the size of the memory allocated by this secure mem.
 secureMemGetSize :: SecureMem -> Int
-secureMemGetSize (SecureMem (ForeignPtr _ fpc)) =
-    case fpc of
-        MallocPtr mba _ -> I# (sizeofMutableByteArray# mba)
-        _               -> error "cannot happen"
-#endif
+secureMemGetSize (SecureMem scrubbedBytes) = B.length scrubbedBytes
 
 secureMemEq :: SecureMem -> SecureMem -> Bool
-secureMemEq sm1 sm2 = sz1 == sz2 && B.inlinePerformIO meq
-  where meq = withSecureMemPtr sm1 $ \ptr1 ->
-              withSecureMemPtr sm2 $ \ptr2 ->
-              feq ptr1 ptr2
-        !sz1 = secureMemGetSize sm1
-        !sz2 = secureMemGetSize sm2
-        feq | sz1 == 8   = compareEq8
-            | sz1 == 16  = compareEq16
-            | sz1 == 24  = compareEq24
-            | sz1 == 32  = compareEq32
-            | sz1 == 64  = compareEq64
-            | sz1 == 128 = compareEq128
-            | sz1 == 256 = compareEq256
-            | otherwise  = compareEq (fromIntegral sz1)
+secureMemEq (SecureMem sm1) (SecureMem sm2) = sm1 == sm2
 
 secureMemAppend :: SecureMem -> SecureMem -> SecureMem
-secureMemAppend s1 s2 =
-    unsafeCreateSecureMem (sz1+sz2) $ \dst -> do
-        withSecureMemPtr s1 $ \sp1 -> B.memcpy dst sp1 (fromIntegral sz1)
-        withSecureMemPtr s2 $ \sp2 -> B.memcpy (dst `plusPtr` sz1) sp2 (fromIntegral sz2)
-  where !sz1 = secureMemGetSize s1
-        !sz2 = secureMemGetSize s2
+secureMemAppend (SecureMem s1) (SecureMem s2) = SecureMem (s1 `mappend` s2)
 
 secureMemConcat :: [SecureMem] -> SecureMem
-secureMemConcat l = unsafeCreateSecureMem total $ \dst -> void $ foldM copy dst l
-  where total = sum $ map secureMemGetSize l
-        copy dst s = withSecureMemPtr s $ \sp -> do
-                    B.memcpy dst sp (fromIntegral sz)
-                    return (dst `plusPtr` sz)
-          where sz = secureMemGetSize s
+secureMemConcat = SecureMem . mconcat . map unSecureMem
+  where unSecureMem (SecureMem sb) = sb
 
 secureMemCopy :: SecureMem -> IO SecureMem
-secureMemCopy src =
-    createSecureMem sz $ \dst ->
-    withSecureMemPtr src $ \s -> B.memcpy dst s (fromIntegral sz)
-  where sz = secureMemGetSize src
+secureMemCopy (SecureMem src) =
+    SecureMem `fmap` B.copy src (\_ -> return ())
 
 withSecureMemCopy :: SecureMem -> (Ptr Word8 -> IO ()) -> IO SecureMem
-withSecureMemCopy sm f = do
-    sm2 <- secureMemCopy sm
-    withSecureMemPtr sm2 f
-    return sm2
+withSecureMemCopy (SecureMem src) f = SecureMem `fmap` B.copy src f
 
 instance Show SecureMem where
     show _ = "<secure-mem>"
@@ -121,13 +101,18 @@
 instance Eq SecureMem where
     (==) = secureMemEq
 
+#if MIN_VERSION_base(4,9,0)
+instance Semigroup SecureMem where
+    (<>)    = secureMemAppend
+    sconcat = secureMemConcat . toList
+#endif
+
 instance Monoid SecureMem where
     mempty  = unsafeCreateSecureMem 0 (\_ -> return ())
+#if !(MIN_VERSION_base(4,11,0))
     mappend = secureMemAppend
     mconcat = secureMemConcat
-
-type Finalizer = Ptr Word8 -> IO ()
-type FinalizerWithSize = CInt -> Ptr Word8 -> IO ()
+#endif
 
 -- | Types that can be converted to a secure mem object.
 class ToSecureMem a where
@@ -138,76 +123,22 @@
 instance ToSecureMem ByteString where
     toSecureMem bs = secureMemFromByteString bs
 
--- | Generic eq function
-foreign import ccall "compare_eq"    compareEq    :: CInt -> Ptr Word8 -> Ptr Word8 -> IO Bool
-
--- | Specialized eq functions which are much faster
-foreign import ccall "compare_eq8"   compareEq8   :: Ptr Word8 -> Ptr Word8 -> IO Bool
-foreign import ccall "compare_eq16"  compareEq16  :: Ptr Word8 -> Ptr Word8 -> IO Bool
-foreign import ccall "compare_eq24"  compareEq24  :: Ptr Word8 -> Ptr Word8 -> IO Bool
-foreign import ccall "compare_eq32"  compareEq32  :: Ptr Word8 -> Ptr Word8 -> IO Bool
-foreign import ccall "compare_eq64"  compareEq64  :: Ptr Word8 -> Ptr Word8 -> IO Bool
-foreign import ccall "compare_eq128" compareEq128 :: Ptr Word8 -> Ptr Word8 -> IO Bool
-foreign import ccall "compare_eq256" compareEq256 :: Ptr Word8 -> Ptr Word8 -> IO Bool
-
-#if MIN_VERSION_base(4,6,0)
--- | Scruber finalizers
-foreign import ccall "finalizer_scrub8" finalizerScrub8     :: Finalizer
-foreign import ccall "finalizer_scrub16" finalizerScrub16   :: Finalizer
-foreign import ccall "finalizer_scrub24" finalizerScrub24   :: Finalizer
-foreign import ccall "finalizer_scrub32" finalizerScrub32   :: Finalizer
-foreign import ccall "finalizer_scrub64" finalizerScrub64   :: Finalizer
-foreign import ccall "finalizer_scrub128" finalizerScrub128 :: Finalizer
-foreign import ccall "finalizer_scrub256" finalizerScrub256 :: Finalizer
-foreign import ccall "finalizer_scrubvar" finalizerScrubVar :: FinalizerWithSize
-
-szToScruber :: Int -> Ptr Word8 -> IO ()
-szToScruber 0   = \_ -> return ()
-szToScruber 8   = finalizerScrub8
-szToScruber 16  = finalizerScrub16
-szToScruber 24  = finalizerScrub24
-szToScruber 32  = finalizerScrub32
-szToScruber 64  = finalizerScrub64
-szToScruber 128 = finalizerScrub128
-szToScruber 256 = finalizerScrub256
-szToScruber n   = finalizerScrubVar (fromIntegral n)
-#endif
-
--- | Allocate a foreign ptr which will be scrubed before memory free.
--- the memory is allocated on the haskell heap
-allocateScrubedForeignPtr :: Int -> IO (ForeignPtr a)
-allocateScrubedForeignPtr sz = do
-#if MIN_VERSION_base(4,6,0)
-    fptr@(ForeignPtr addr _) <- mallocForeignPtrBytes sz
-    addForeignPtrConcFinalizer fptr (scruber (Ptr addr))
-    return fptr
-  where !scruber = szToScruber sz
-#else
-    mallocForeignPtrBytes sz
-#endif
-
 -- | Allocate a new SecureMem
 --
 -- The memory is allocated on the haskell heap, and will be scrubed
 -- before being released.
 allocateSecureMem :: Int -> IO SecureMem
-#if MIN_VERSION_base(4,6,0)
-allocateSecureMem sz = SecureMem <$> allocateScrubedForeignPtr sz
-#else
-allocateSecureMem sz = SecureMem <$> allocateScrubedForeignPtr sz <*> pure sz
-#endif
+allocateSecureMem sz = SecureMem <$> B.create sz (\_ -> return ())
 
 -- | Create a new secure mem and running an initializer function
 createSecureMem :: Int -> (Ptr Word8 -> IO ()) -> IO SecureMem
-createSecureMem sz f = do
-    sm <- allocateSecureMem sz
-    withSecureMemPtr sm f
-    return sm
+createSecureMem sz f = SecureMem `fmap` B.create sz f
 
 -- | Create a new secure mem using inline perform IO to create a pure
 -- result.
 unsafeCreateSecureMem :: Int -> (Ptr Word8 -> IO ()) -> SecureMem
-unsafeCreateSecureMem sz f = B.inlinePerformIO (createSecureMem sz f)
+unsafeCreateSecureMem sz f = pureIO (createSecureMem sz f)
+{-# NOINLINE unsafeCreateSecureMem #-}
 
 -- | This is a way to look at the pointer living inside a foreign object. This
 -- function takes a function which is applied to that pointer. The resulting IO
@@ -215,29 +146,40 @@
 --
 -- this is similary to withForeignPtr for a ForeignPtr
 withSecureMemPtr :: SecureMem -> (Ptr Word8 -> IO b) -> IO b
-withSecureMemPtr sm f = withForeignPtr (getForeignPtr sm) f
+withSecureMemPtr (SecureMem sm) f = B.withByteArray sm f
 
 -- | similar to withSecureMem but also include the size of the pointed memory.
 withSecureMemPtrSz :: SecureMem -> (Int -> Ptr Word8 -> IO b) -> IO b
-withSecureMemPtrSz sm f = withForeignPtr (getForeignPtr sm) (f (secureMemGetSize sm))
+withSecureMemPtrSz (SecureMem sm) f = B.withByteArray sm (f (B.length sm))
 
 -- | Finalize a SecureMem early
 finalizeSecureMem :: SecureMem -> IO ()
-finalizeSecureMem sm = finalizeForeignPtr $ getForeignPtr sm
+finalizeSecureMem (SecureMem sb) = B.withByteArray sb $ \p ->
+    B.memSet p 0 (B.length sb)
 
 -- | Create a bytestring from a Secure Mem
 secureMemToByteString :: SecureMem -> ByteString
 secureMemToByteString sm =
-    B.unsafeCreate sz $ \dst ->
+    BS.unsafeCreate sz $ \dst ->
     withSecureMemPtr sm $ \src ->
-    B.memcpy dst src (fromIntegral sz)
+    BS.memcpy dst src (fromIntegral sz)
   where !sz = secureMemGetSize sm
 
 -- | Create a SecureMem from a bytestring
 secureMemFromByteString :: ByteString -> SecureMem
-secureMemFromByteString b = B.inlinePerformIO $ do
-    sm <- allocateSecureMem len 
-    withSecureMemPtr sm $ \dst -> withBytestringPtr $ \src -> B.memcpy dst src (fromIntegral len)
+secureMemFromByteString b = pureIO $ do
+    sm <- allocateSecureMem len
+    withSecureMemPtr sm $ \dst -> withBytestringPtr $ \src -> BS.memcpy dst src (fromIntegral len)
     return sm
-  where (fp, off, !len) = B.toForeignPtr b
+  where (fp, off, !len) = BS.toForeignPtr b
         withBytestringPtr f = withForeignPtr fp $ \p -> f (p `plusPtr` off)
+{-# NOINLINE secureMemFromByteString #-}
+
+-- | Create a SecureMem from any byteable object
+secureMemFromByteable :: Byteable b => b -> SecureMem
+secureMemFromByteable bs = pureIO $ do
+    sm <- allocateSecureMem len
+    withSecureMemPtr sm $ \dst -> withBytePtr bs $ \src -> BS.memcpy dst src (fromIntegral len)
+    return sm
+  where len = byteableLength bs
+{-# NOINLINE secureMemFromByteable #-}
diff --git a/LICENSE b/LICENSE
--- a/LICENSE
+++ b/LICENSE
@@ -1,4 +1,4 @@
-Copyright (c) 2013 Vincent Hanquez <vincent@snarc.org>
+Copyright (c) 2013-2018 Vincent Hanquez <vincent@snarc.org>
 
 All rights reserved.
 
diff --git a/README.md b/README.md
deleted file mode 100644
--- a/README.md
+++ /dev/null
@@ -1,9 +0,0 @@
-securemem
-=======
-
-Documentation: [securemem on hackage](http://hackage.haskell.org/package/securemem)
-
-older base
-----------
-
-An older base, the memory is not scrubed: upgrade your GHC to 7.6.0 or above.
diff --git a/cbits/utils.c b/cbits/utils.c
--- a/cbits/utils.c
+++ b/cbits/utils.c
@@ -70,16 +70,12 @@
 	memset(ptr, 0xa5, sz);
 }
 
-int constant_memeq16(uint8_t *p1, uint8_t *p2)
-{
-}
-
 int compare_eq(uint32_t size, uint8_t *p1, uint8_t *p2)
 {
 	uint32_t i;
 	int acc = 1;
 
-	for (i = 0; i < size / 8; i++)
+	for (i = 0; i < size; i++)
 		acc &= (p1[i] == p2[i]);
 	return acc;
 }
diff --git a/securemem.cabal b/securemem.cabal
--- a/securemem.cabal
+++ b/securemem.cabal
@@ -1,5 +1,5 @@
 Name:                securemem
-Version:             0.1.3
+Version:             0.1.10
 Synopsis:            abstraction to an auto scrubbing and const time eq, memory chunk.
 Description:
     SecureMem is similar to ByteString, except that it provides a memory chunk that
@@ -12,19 +12,19 @@
 Category:            Data
 Stability:           experimental
 Build-Type:          Simple
-Homepage:            http://github.com/vincenthz/hs-securemem
+Homepage:            https://github.com/vincenthz/hs-securemem
 Cabal-Version:       >=1.8
-data-files:          README.md
 
 Library
   Exposed-modules:   Data.SecureMem
   Build-depends:     base >= 4 && < 5
                    , bytestring
                    , byteable >= 0.1.1
+                   , memory >= 0.7
                    , ghc-prim
   C-sources:         cbits/utils.c
   ghc-options:       -Wall -fwarn-tabs
 
 source-repository head
   type: git
-  location: git://github.com/vincenthz/hs-securemem
+  location: https://github.com/vincenthz/hs-securemem
