diff --git a/Crypto/Hash/MD2.hs b/Crypto/Hash/MD2.hs
new file mode 100644
--- /dev/null
+++ b/Crypto/Hash/MD2.hs
@@ -0,0 +1,120 @@
+{-# LANGUAGE ForeignFunctionInterface, CPP, MultiParamTypeClasses #-}
+
+-- |
+-- Module      : Crypto.Hash.MD2
+-- License     : BSD-style
+-- Maintainer  : Vincent Hanquez <vincent@snarc.org>
+-- Stability   : experimental
+-- Portability : unknown
+--
+-- A module containing MD2 bindings
+--
+module Crypto.Hash.MD2
+	( Ctx(..)
+	, MD2
+
+	-- * Incremental hashing Functions
+	, init     -- :: Ctx
+	, update   -- :: Ctx -> ByteString -> Ctx
+	, finalize -- :: Ctx -> ByteString
+
+	-- * Single Pass hashing
+	, hash     -- :: ByteString -> ByteString
+	, hashlazy -- :: ByteString -> ByteString
+	) where
+
+import Prelude hiding (init)
+import Foreign
+import Foreign.C.String
+import qualified Data.ByteString as B
+import qualified Data.ByteString.Lazy as L
+import Data.ByteString (ByteString)
+import Data.ByteString.Unsafe (unsafeUseAsCString, unsafeUseAsCStringLen)
+import Data.ByteString.Internal (create, memcpy)
+
+#ifdef HAVE_CRYPTOAPI
+
+import Control.Monad (liftM)
+import Data.Serialize (Serialize(..))
+import Data.Serialize.Get (getByteString)
+import Data.Serialize.Put (putByteString)
+import Data.Tagged (Tagged(..))
+import qualified Crypto.Classes as C (Hash(..))
+
+instance C.Hash Ctx MD2 where
+	outputLength    = Tagged (16 * 8)
+	blockLength     = Tagged (16 * 8)
+	initialCtx      = init
+	updateCtx       = update
+	finalize ctx bs = Digest . finalize $ update ctx bs
+
+instance Serialize MD2 where
+	get            = liftM Digest (getByteString digestSize)
+	put (Digest d) = putByteString d
+
+#endif
+
+data Ctx = Ctx !ByteString
+data MD2 = Digest !ByteString
+	deriving (Eq,Ord,Show)
+
+digestSize, sizeCtx :: Int
+digestSize = 16
+sizeCtx = 96
+
+instance Storable Ctx where
+	sizeOf _    = sizeCtx
+	alignment _ = 16
+	poke ptr (Ctx b) = unsafeUseAsCString b (\cs -> memcpy (castPtr ptr) (castPtr cs) (fromIntegral sizeCtx))
+
+	peek ptr = create sizeCtx (\bptr -> memcpy bptr (castPtr ptr) (fromIntegral sizeCtx)) >>= return . Ctx
+
+foreign import ccall unsafe "md2.h md2_init"
+	c_md2_init :: Ptr Ctx -> IO ()
+
+foreign import ccall "md2.h md2_update"
+	c_md2_update :: Ptr Ctx -> CString -> Word32 -> IO ()
+
+foreign import ccall unsafe "md2.h md2_finalize"
+	c_md2_finalize :: Ptr Ctx -> CString -> IO ()
+
+allocInternal :: (Ptr Ctx -> IO a) -> IO a
+allocInternal = alloca
+
+allocInternalFrom :: Ctx -> (Ptr Ctx -> IO a) -> IO a
+allocInternalFrom ctx f = allocInternal $ \ptr -> (poke ptr ctx >> f ptr)
+
+updateInternalIO :: Ptr Ctx -> ByteString -> IO ()
+updateInternalIO ptr d =
+	unsafeUseAsCStringLen d (\(cs, len) -> c_md2_update ptr cs (fromIntegral len))
+
+finalizeInternalIO :: Ptr Ctx -> IO ByteString
+finalizeInternalIO ptr =
+	allocaBytes digestSize (\cs -> c_md2_finalize ptr cs >> B.packCStringLen (cs, digestSize))
+
+{-# NOINLINE init #-}
+-- | init a context
+init :: Ctx
+init = unsafePerformIO $ allocInternal $ \ptr -> do (c_md2_init ptr >> peek ptr)
+
+{-# NOINLINE update #-}
+-- | update a context with a bytestring
+update :: Ctx -> ByteString -> Ctx
+update ctx d = unsafePerformIO $ allocInternalFrom ctx $ \ptr -> do updateInternalIO ptr d >> peek ptr
+
+{-# NOINLINE finalize #-}
+-- | finalize the context into a digest bytestring
+finalize :: Ctx -> ByteString
+finalize ctx = unsafePerformIO $ allocInternalFrom ctx $ \ptr -> do finalizeInternalIO ptr
+
+{-# NOINLINE hash #-}
+-- | hash a strict bytestring into a digest bytestring
+hash :: ByteString -> ByteString
+hash d = unsafePerformIO $ allocInternal $ \ptr -> do
+	c_md2_init ptr >> updateInternalIO ptr d >> finalizeInternalIO ptr
+
+{-# NOINLINE hashlazy #-}
+-- | hash a lazy bytestring into a digest bytestring
+hashlazy :: L.ByteString -> ByteString
+hashlazy l = unsafePerformIO $ allocInternal $ \ptr -> do
+	c_md2_init ptr >> mapM_ (updateInternalIO ptr) (L.toChunks l) >> finalizeInternalIO ptr
diff --git a/Crypto/Hash/MD4.hs b/Crypto/Hash/MD4.hs
new file mode 100644
--- /dev/null
+++ b/Crypto/Hash/MD4.hs
@@ -0,0 +1,120 @@
+{-# LANGUAGE ForeignFunctionInterface, CPP, MultiParamTypeClasses #-}
+
+-- |
+-- Module      : Crypto.Hash.MD4
+-- License     : BSD-style
+-- Maintainer  : Vincent Hanquez <vincent@snarc.org>
+-- Stability   : experimental
+-- Portability : unknown
+--
+-- A module containing MD4 bindings
+--
+module Crypto.Hash.MD4
+	( Ctx(..)
+	, MD4
+
+	-- * Incremental hashing Functions
+	, init     -- :: Ctx
+	, update   -- :: Ctx -> ByteString -> Ctx
+	, finalize -- :: Ctx -> ByteString
+
+	-- * Single Pass hashing
+	, hash     -- :: ByteString -> ByteString
+	, hashlazy -- :: ByteString -> ByteString
+	) where
+
+import Prelude hiding (init)
+import Foreign
+import Foreign.C.String
+import qualified Data.ByteString as B
+import qualified Data.ByteString.Lazy as L
+import Data.ByteString (ByteString)
+import Data.ByteString.Unsafe (unsafeUseAsCString, unsafeUseAsCStringLen)
+import Data.ByteString.Internal (create, memcpy)
+
+#ifdef HAVE_CRYPTOAPI
+
+import Control.Monad (liftM)
+import Data.Serialize (Serialize(..))
+import Data.Serialize.Get (getByteString)
+import Data.Serialize.Put (putByteString)
+import Data.Tagged (Tagged(..))
+import qualified Crypto.Classes as C (Hash(..))
+
+instance C.Hash Ctx MD4 where
+	outputLength    = Tagged (16 * 8)
+	blockLength     = Tagged (64 * 8)
+	initialCtx      = init
+	updateCtx       = update
+	finalize ctx bs = Digest . finalize $ update ctx bs
+
+instance Serialize MD4 where
+	get            = liftM Digest (getByteString digestSize)
+	put (Digest d) = putByteString d
+
+#endif
+
+data Ctx = Ctx !ByteString
+data MD4 = Digest !ByteString
+	deriving (Eq,Ord,Show)
+
+digestSize, sizeCtx :: Int
+digestSize = 16
+sizeCtx = 96
+
+instance Storable Ctx where
+	sizeOf _    = sizeCtx
+	alignment _ = 16
+	poke ptr (Ctx b) = unsafeUseAsCString b (\cs -> memcpy (castPtr ptr) (castPtr cs) (fromIntegral sizeCtx))
+
+	peek ptr = create sizeCtx (\bptr -> memcpy bptr (castPtr ptr) (fromIntegral sizeCtx)) >>= return . Ctx
+
+foreign import ccall unsafe "md4.h md4_init"
+	c_md4_init :: Ptr Ctx -> IO ()
+
+foreign import ccall "md4.h md4_update"
+	c_md4_update :: Ptr Ctx -> CString -> Word32 -> IO ()
+
+foreign import ccall unsafe "md4.h md4_finalize"
+	c_md4_finalize :: Ptr Ctx -> CString -> IO ()
+
+allocInternal :: (Ptr Ctx -> IO a) -> IO a
+allocInternal = alloca
+
+allocInternalFrom :: Ctx -> (Ptr Ctx -> IO a) -> IO a
+allocInternalFrom ctx f = allocInternal $ \ptr -> (poke ptr ctx >> f ptr)
+
+updateInternalIO :: Ptr Ctx -> ByteString -> IO ()
+updateInternalIO ptr d =
+	unsafeUseAsCStringLen d (\(cs, len) -> c_md4_update ptr cs (fromIntegral len))
+
+finalizeInternalIO :: Ptr Ctx -> IO ByteString
+finalizeInternalIO ptr =
+	allocaBytes digestSize (\cs -> c_md4_finalize ptr cs >> B.packCStringLen (cs, digestSize))
+
+{-# NOINLINE init #-}
+-- | init a context
+init :: Ctx
+init = unsafePerformIO $ allocInternal $ \ptr -> do (c_md4_init ptr >> peek ptr)
+
+{-# NOINLINE update #-}
+-- | update a context with a bytestring
+update :: Ctx -> ByteString -> Ctx
+update ctx d = unsafePerformIO $ allocInternalFrom ctx $ \ptr -> do updateInternalIO ptr d >> peek ptr
+
+{-# NOINLINE finalize #-}
+-- | finalize the context into a digest bytestring
+finalize :: Ctx -> ByteString
+finalize ctx = unsafePerformIO $ allocInternalFrom ctx $ \ptr -> do finalizeInternalIO ptr
+
+{-# NOINLINE hash #-}
+-- | hash a strict bytestring into a digest bytestring
+hash :: ByteString -> ByteString
+hash d = unsafePerformIO $ allocInternal $ \ptr -> do
+	c_md4_init ptr >> updateInternalIO ptr d >> finalizeInternalIO ptr
+
+{-# NOINLINE hashlazy #-}
+-- | hash a lazy bytestring into a digest bytestring
+hashlazy :: L.ByteString -> ByteString
+hashlazy l = unsafePerformIO $ allocInternal $ \ptr -> do
+	c_md4_init ptr >> mapM_ (updateInternalIO ptr) (L.toChunks l) >> finalizeInternalIO ptr
diff --git a/Crypto/Hash/MD5.hs b/Crypto/Hash/MD5.hs
new file mode 100644
--- /dev/null
+++ b/Crypto/Hash/MD5.hs
@@ -0,0 +1,120 @@
+{-# LANGUAGE ForeignFunctionInterface, CPP, MultiParamTypeClasses #-}
+
+-- |
+-- Module      : Crypto.Hash.MD5
+-- License     : BSD-style
+-- Maintainer  : Vincent Hanquez <vincent@snarc.org>
+-- Stability   : experimental
+-- Portability : unknown
+--
+-- A module containing MD5 bindings
+--
+module Crypto.Hash.MD5
+	( Ctx(..)
+	, MD5
+
+	-- * Incremental hashing Functions
+	, init     -- :: Ctx
+	, update   -- :: Ctx -> ByteString -> Ctx
+	, finalize -- :: Ctx -> ByteString
+
+	-- * Single Pass hashing
+	, hash     -- :: ByteString -> ByteString
+	, hashlazy -- :: ByteString -> ByteString
+	) where
+
+import Prelude hiding (init)
+import Foreign
+import Foreign.C.String
+import qualified Data.ByteString as B
+import qualified Data.ByteString.Lazy as L
+import Data.ByteString (ByteString)
+import Data.ByteString.Unsafe (unsafeUseAsCString, unsafeUseAsCStringLen)
+import Data.ByteString.Internal (create, memcpy)
+
+#ifdef HAVE_CRYPTOAPI
+
+import Control.Monad (liftM)
+import Data.Serialize (Serialize(..))
+import Data.Serialize.Get (getByteString)
+import Data.Serialize.Put (putByteString)
+import Data.Tagged (Tagged(..))
+import qualified Crypto.Classes as C (Hash(..))
+
+instance C.Hash Ctx MD5 where
+	outputLength    = Tagged (16 * 8)
+	blockLength     = Tagged (64 * 8)
+	initialCtx      = init
+	updateCtx       = update
+	finalize ctx bs = Digest . finalize $ update ctx bs
+
+instance Serialize MD5 where
+	get            = liftM Digest (getByteString digestSize)
+	put (Digest d) = putByteString d
+
+#endif
+
+data Ctx = Ctx !ByteString
+data MD5 = Digest !ByteString
+	deriving (Eq,Ord,Show)
+
+digestSize, sizeCtx :: Int
+digestSize = 16
+sizeCtx = 96
+
+instance Storable Ctx where
+	sizeOf _    = sizeCtx
+	alignment _ = 16
+	poke ptr (Ctx b) = unsafeUseAsCString b (\cs -> memcpy (castPtr ptr) (castPtr cs) (fromIntegral sizeCtx))
+
+	peek ptr = create sizeCtx (\bptr -> memcpy bptr (castPtr ptr) (fromIntegral sizeCtx)) >>= return . Ctx
+
+foreign import ccall unsafe "md5.h md5_init"
+	c_md5_init :: Ptr Ctx -> IO ()
+
+foreign import ccall "md5.h md5_update"
+	c_md5_update :: Ptr Ctx -> CString -> Word32 -> IO ()
+
+foreign import ccall unsafe "md5.h md5_finalize"
+	c_md5_finalize :: Ptr Ctx -> CString -> IO ()
+
+allocInternal :: (Ptr Ctx -> IO a) -> IO a
+allocInternal = alloca
+
+allocInternalFrom :: Ctx -> (Ptr Ctx -> IO a) -> IO a
+allocInternalFrom ctx f = allocInternal $ \ptr -> (poke ptr ctx >> f ptr)
+
+updateInternalIO :: Ptr Ctx -> ByteString -> IO ()
+updateInternalIO ptr d =
+	unsafeUseAsCStringLen d (\(cs, len) -> c_md5_update ptr cs (fromIntegral len))
+
+finalizeInternalIO :: Ptr Ctx -> IO ByteString
+finalizeInternalIO ptr =
+	allocaBytes digestSize (\cs -> c_md5_finalize ptr cs >> B.packCStringLen (cs, digestSize))
+
+{-# NOINLINE init #-}
+-- | init a context
+init :: Ctx
+init = unsafePerformIO $ allocInternal $ \ptr -> do (c_md5_init ptr >> peek ptr)
+
+{-# NOINLINE update #-}
+-- | update a context with a bytestring
+update :: Ctx -> ByteString -> Ctx
+update ctx d = unsafePerformIO $ allocInternalFrom ctx $ \ptr -> do updateInternalIO ptr d >> peek ptr
+
+{-# NOINLINE finalize #-}
+-- | finalize the context into a digest bytestring
+finalize :: Ctx -> ByteString
+finalize ctx = unsafePerformIO $ allocInternalFrom ctx $ \ptr -> do finalizeInternalIO ptr
+
+{-# NOINLINE hash #-}
+-- | hash a strict bytestring into a digest bytestring
+hash :: ByteString -> ByteString
+hash d = unsafePerformIO $ allocInternal $ \ptr -> do
+	c_md5_init ptr >> updateInternalIO ptr d >> finalizeInternalIO ptr
+
+{-# NOINLINE hashlazy #-}
+-- | hash a lazy bytestring into a digest bytestring
+hashlazy :: L.ByteString -> ByteString
+hashlazy l = unsafePerformIO $ allocInternal $ \ptr -> do
+	c_md5_init ptr >> mapM_ (updateInternalIO ptr) (L.toChunks l) >> finalizeInternalIO ptr
diff --git a/Crypto/Hash/RIPEMD160.hs b/Crypto/Hash/RIPEMD160.hs
new file mode 100644
--- /dev/null
+++ b/Crypto/Hash/RIPEMD160.hs
@@ -0,0 +1,120 @@
+{-# LANGUAGE ForeignFunctionInterface, CPP, MultiParamTypeClasses #-}
+
+-- |
+-- Module      : Crypto.Hash.RIPEMD160
+-- License     : BSD-style
+-- Maintainer  : Vincent Hanquez <vincent@snarc.org>
+-- Stability   : experimental
+-- Portability : unknown
+--
+-- A module containing RIPEMD160 bindings
+--
+module Crypto.Hash.RIPEMD160
+	( Ctx(..)
+	, RIPEMD160
+
+	-- * Incremental hashing Functions
+	, init     -- :: Ctx
+	, update   -- :: Ctx -> ByteString -> Ctx
+	, finalize -- :: Ctx -> ByteString
+
+	-- * Single Pass hashing
+	, hash     -- :: ByteString -> ByteString
+	, hashlazy -- :: ByteString -> ByteString
+	) where
+
+import Prelude hiding (init)
+import Foreign
+import Foreign.C.String
+import qualified Data.ByteString as B
+import qualified Data.ByteString.Lazy as L
+import Data.ByteString (ByteString)
+import Data.ByteString.Unsafe (unsafeUseAsCString, unsafeUseAsCStringLen)
+import Data.ByteString.Internal (create, memcpy)
+
+#ifdef HAVE_CRYPTOAPI
+
+import Control.Monad (liftM)
+import Data.Serialize (Serialize(..))
+import Data.Serialize.Get (getByteString)
+import Data.Serialize.Put (putByteString)
+import Data.Tagged (Tagged(..))
+import qualified Crypto.Classes as C (Hash(..))
+
+instance C.Hash Ctx RIPEMD160 where
+	outputLength    = Tagged (20 * 8)
+	blockLength     = Tagged (64 * 8)
+	initialCtx      = init
+	updateCtx       = update
+	finalize ctx bs = Digest . finalize $ update ctx bs
+
+instance Serialize RIPEMD160 where
+	get            = liftM Digest (getByteString digestSize)
+	put (Digest d) = putByteString d
+
+#endif
+
+data Ctx = Ctx !ByteString
+data RIPEMD160 = Digest !ByteString
+	deriving (Eq,Ord,Show)
+
+digestSize, sizeCtx :: Int
+digestSize = 20
+sizeCtx = 128
+
+instance Storable Ctx where
+	sizeOf _    = sizeCtx
+	alignment _ = 16
+	poke ptr (Ctx b) = unsafeUseAsCString b (\cs -> memcpy (castPtr ptr) (castPtr cs) (fromIntegral sizeCtx))
+
+	peek ptr = create sizeCtx (\bptr -> memcpy bptr (castPtr ptr) (fromIntegral sizeCtx)) >>= return . Ctx
+
+foreign import ccall unsafe "ripemd.h ripemd160_init"
+	c_ripemd160_init :: Ptr Ctx -> IO ()
+
+foreign import ccall "ripemd.h ripemd160_update"
+	c_ripemd160_update :: Ptr Ctx -> CString -> Word32 -> IO ()
+
+foreign import ccall unsafe "ripemd.h ripemd160_finalize"
+	c_ripemd160_finalize :: Ptr Ctx -> CString -> IO ()
+
+allocInternal :: (Ptr Ctx -> IO a) -> IO a
+allocInternal = alloca
+
+allocInternalFrom :: Ctx -> (Ptr Ctx -> IO a) -> IO a
+allocInternalFrom ctx f = allocInternal $ \ptr -> (poke ptr ctx >> f ptr)
+
+updateInternalIO :: Ptr Ctx -> ByteString -> IO ()
+updateInternalIO ptr d =
+	unsafeUseAsCStringLen d (\(cs, len) -> c_ripemd160_update ptr cs (fromIntegral len))
+
+finalizeInternalIO :: Ptr Ctx -> IO ByteString
+finalizeInternalIO ptr =
+	allocaBytes digestSize (\cs -> c_ripemd160_finalize ptr cs >> B.packCStringLen (cs, digestSize))
+
+{-# NOINLINE init #-}
+-- | init a context
+init :: Ctx
+init = unsafePerformIO $ allocInternal $ \ptr -> do (c_ripemd160_init ptr >> peek ptr)
+
+{-# NOINLINE update #-}
+-- | update a context with a bytestring
+update :: Ctx -> ByteString -> Ctx
+update ctx d = unsafePerformIO $ allocInternalFrom ctx $ \ptr -> do updateInternalIO ptr d >> peek ptr
+
+{-# NOINLINE finalize #-}
+-- | finalize the context into a digest bytestring
+finalize :: Ctx -> ByteString
+finalize ctx = unsafePerformIO $ allocInternalFrom ctx $ \ptr -> do finalizeInternalIO ptr
+
+{-# NOINLINE hash #-}
+-- | hash a strict bytestring into a digest bytestring
+hash :: ByteString -> ByteString
+hash d = unsafePerformIO $ allocInternal $ \ptr -> do
+	c_ripemd160_init ptr >> updateInternalIO ptr d >> finalizeInternalIO ptr
+
+{-# NOINLINE hashlazy #-}
+-- | hash a lazy bytestring into a digest bytestring
+hashlazy :: L.ByteString -> ByteString
+hashlazy l = unsafePerformIO $ allocInternal $ \ptr -> do
+	c_ripemd160_init ptr >> mapM_ (updateInternalIO ptr) (L.toChunks l) >> finalizeInternalIO ptr
diff --git a/Crypto/Hash/SHA1.hs b/Crypto/Hash/SHA1.hs
new file mode 100644
--- /dev/null
+++ b/Crypto/Hash/SHA1.hs
@@ -0,0 +1,120 @@
+{-# LANGUAGE ForeignFunctionInterface, CPP, MultiParamTypeClasses #-}
+
+-- |
+-- Module      : Crypto.Hash.SHA1
+-- License     : BSD-style
+-- Maintainer  : Vincent Hanquez <vincent@snarc.org>
+-- Stability   : experimental
+-- Portability : unknown
+--
+-- A module containing SHA1 bindings
+--
+module Crypto.Hash.SHA1
+	( Ctx(..)
+	, SHA1
+
+	-- * Incremental hashing Functions
+	, init     -- :: Ctx
+	, update   -- :: Ctx -> ByteString -> Ctx
+	, finalize -- :: Ctx -> ByteString
+
+	-- * Single Pass hashing
+	, hash     -- :: ByteString -> ByteString
+	, hashlazy -- :: ByteString -> ByteString
+	) where
+
+import Prelude hiding (init)
+import Foreign
+import Foreign.C.String
+import qualified Data.ByteString as B
+import qualified Data.ByteString.Lazy as L
+import Data.ByteString (ByteString)
+import Data.ByteString.Unsafe (unsafeUseAsCString, unsafeUseAsCStringLen)
+import Data.ByteString.Internal (create, memcpy)
+
+#ifdef HAVE_CRYPTOAPI
+
+import Control.Monad (liftM)
+import Data.Serialize (Serialize(..))
+import Data.Serialize.Get (getByteString)
+import Data.Serialize.Put (putByteString)
+import Data.Tagged (Tagged(..))
+import qualified Crypto.Classes as C (Hash(..))
+
+instance C.Hash Ctx SHA1 where
+	outputLength    = Tagged (20 * 8)
+	blockLength     = Tagged (64 * 8)
+	initialCtx      = init
+	updateCtx       = update
+	finalize ctx bs = Digest . finalize $ update ctx bs
+
+instance Serialize SHA1 where
+	get            = liftM Digest (getByteString digestSize)
+	put (Digest d) = putByteString d
+
+#endif
+
+data Ctx = Ctx !ByteString
+data SHA1 = Digest !ByteString
+	deriving (Eq,Ord,Show)
+
+digestSize, sizeCtx :: Int
+digestSize = 20
+sizeCtx = 96
+
+instance Storable Ctx where
+	sizeOf _    = sizeCtx
+	alignment _ = 16
+	poke ptr (Ctx b) = unsafeUseAsCString b (\cs -> memcpy (castPtr ptr) (castPtr cs) (fromIntegral sizeCtx))
+
+	peek ptr = create sizeCtx (\bptr -> memcpy bptr (castPtr ptr) (fromIntegral sizeCtx)) >>= return . Ctx
+
+foreign import ccall unsafe "sha1.h sha1_init"
+	c_sha1_init :: Ptr Ctx -> IO ()
+
+foreign import ccall "sha1.h sha1_update"
+	c_sha1_update :: Ptr Ctx -> CString -> Word32 -> IO ()
+
+foreign import ccall unsafe "sha1.h sha1_finalize"
+	c_sha1_finalize :: Ptr Ctx -> CString -> IO ()
+
+allocInternal :: (Ptr Ctx -> IO a) -> IO a
+allocInternal = alloca
+
+allocInternalFrom :: Ctx -> (Ptr Ctx -> IO a) -> IO a
+allocInternalFrom ctx f = allocInternal $ \ptr -> (poke ptr ctx >> f ptr)
+
+updateInternalIO :: Ptr Ctx -> ByteString -> IO ()
+updateInternalIO ptr d =
+	unsafeUseAsCStringLen d (\(cs, len) -> c_sha1_update ptr cs (fromIntegral len))
+
+finalizeInternalIO :: Ptr Ctx -> IO ByteString
+finalizeInternalIO ptr =
+	allocaBytes digestSize (\cs -> c_sha1_finalize ptr cs >> B.packCStringLen (cs, digestSize))
+
+{-# NOINLINE init #-}
+-- | init a context
+init :: Ctx
+init = unsafePerformIO $ allocInternal $ \ptr -> do (c_sha1_init ptr >> peek ptr)
+
+{-# NOINLINE update #-}
+-- | update a context with a bytestring
+update :: Ctx -> ByteString -> Ctx
+update ctx d = unsafePerformIO $ allocInternalFrom ctx $ \ptr -> do updateInternalIO ptr d >> peek ptr
+
+{-# NOINLINE finalize #-}
+-- | finalize the context into a digest bytestring
+finalize :: Ctx -> ByteString
+finalize ctx = unsafePerformIO $ allocInternalFrom ctx $ \ptr -> do finalizeInternalIO ptr
+
+{-# NOINLINE hash #-}
+-- | hash a strict bytestring into a digest bytestring
+hash :: ByteString -> ByteString
+hash d = unsafePerformIO $ allocInternal $ \ptr -> do
+	c_sha1_init ptr >> updateInternalIO ptr d >> finalizeInternalIO ptr
+
+{-# NOINLINE hashlazy #-}
+-- | hash a lazy bytestring into a digest bytestring
+hashlazy :: L.ByteString -> ByteString
+hashlazy l = unsafePerformIO $ allocInternal $ \ptr -> do
+	c_sha1_init ptr >> mapM_ (updateInternalIO ptr) (L.toChunks l) >> finalizeInternalIO ptr
diff --git a/Crypto/Hash/SHA224.hs b/Crypto/Hash/SHA224.hs
new file mode 100644
--- /dev/null
+++ b/Crypto/Hash/SHA224.hs
@@ -0,0 +1,120 @@
+{-# LANGUAGE ForeignFunctionInterface, CPP, MultiParamTypeClasses #-}
+
+-- |
+-- Module      : Crypto.Hash.SHA224
+-- License     : BSD-style
+-- Maintainer  : Vincent Hanquez <vincent@snarc.org>
+-- Stability   : experimental
+-- Portability : unknown
+--
+-- A module containing SHA224 bindings
+--
+module Crypto.Hash.SHA224
+	( Ctx(..)
+	, SHA224
+
+	-- * Incremental hashing Functions
+	, init     -- :: Ctx
+	, update   -- :: Ctx -> ByteString -> Ctx
+	, finalize -- :: Ctx -> ByteString
+
+	-- * Single Pass hashing
+	, hash     -- :: ByteString -> ByteString
+	, hashlazy -- :: ByteString -> ByteString
+	) where
+
+import Prelude hiding (init)
+import Foreign
+import Foreign.C.String
+import qualified Data.ByteString as B
+import qualified Data.ByteString.Lazy as L
+import Data.ByteString (ByteString)
+import Data.ByteString.Unsafe (unsafeUseAsCString, unsafeUseAsCStringLen)
+import Data.ByteString.Internal (create, memcpy)
+
+#ifdef HAVE_CRYPTOAPI
+
+import Control.Monad (liftM)
+import Data.Serialize (Serialize(..))
+import Data.Serialize.Get (getByteString)
+import Data.Serialize.Put (putByteString)
+import Data.Tagged (Tagged(..))
+import qualified Crypto.Classes as C (Hash(..))
+
+instance C.Hash Ctx SHA224 where
+	outputLength    = Tagged (28 * 8)
+	blockLength     = Tagged (64 * 8)
+	initialCtx      = init
+	updateCtx       = update
+	finalize ctx bs = Digest . finalize $ update ctx bs
+
+instance Serialize SHA224 where
+	get            = liftM Digest (getByteString digestSize)
+	put (Digest d) = putByteString d
+
+#endif
+
+data Ctx = Ctx !ByteString
+data SHA224 = Digest !ByteString
+	deriving (Eq,Ord,Show)
+
+digestSize, sizeCtx :: Int
+digestSize = 28
+sizeCtx = 192
+
+instance Storable Ctx where
+	sizeOf _    = sizeCtx
+	alignment _ = 16
+	poke ptr (Ctx b) = unsafeUseAsCString b (\cs -> memcpy (castPtr ptr) (castPtr cs) (fromIntegral sizeCtx))
+
+	peek ptr = create sizeCtx (\bptr -> memcpy bptr (castPtr ptr) (fromIntegral sizeCtx)) >>= return . Ctx
+
+foreign import ccall unsafe "sha256.h sha224_init"
+	c_sha224_init :: Ptr Ctx -> IO ()
+
+foreign import ccall "sha256.h sha224_update"
+	c_sha224_update :: Ptr Ctx -> CString -> Word32 -> IO ()
+
+foreign import ccall unsafe "sha256.h sha224_finalize"
+	c_sha224_finalize :: Ptr Ctx -> CString -> IO ()
+
+allocInternal :: (Ptr Ctx -> IO a) -> IO a
+allocInternal = alloca
+
+allocInternalFrom :: Ctx -> (Ptr Ctx -> IO a) -> IO a
+allocInternalFrom ctx f = allocInternal $ \ptr -> (poke ptr ctx >> f ptr)
+
+updateInternalIO :: Ptr Ctx -> ByteString -> IO ()
+updateInternalIO ptr d =
+	unsafeUseAsCStringLen d (\(cs, len) -> c_sha224_update ptr cs (fromIntegral len))
+
+finalizeInternalIO :: Ptr Ctx -> IO ByteString
+finalizeInternalIO ptr =
+	allocaBytes digestSize (\cs -> c_sha224_finalize ptr cs >> B.packCStringLen (cs, digestSize))
+
+{-# NOINLINE init #-}
+-- | init a context
+init :: Ctx
+init = unsafePerformIO $ allocInternal $ \ptr -> do (c_sha224_init ptr >> peek ptr)
+
+{-# NOINLINE update #-}
+-- | update a context with a bytestring
+update :: Ctx -> ByteString -> Ctx
+update ctx d = unsafePerformIO $ allocInternalFrom ctx $ \ptr -> do updateInternalIO ptr d >> peek ptr
+
+{-# NOINLINE finalize #-}
+-- | finalize the context into a digest bytestring
+finalize :: Ctx -> ByteString
+finalize ctx = unsafePerformIO $ allocInternalFrom ctx $ \ptr -> do finalizeInternalIO ptr
+
+{-# NOINLINE hash #-}
+-- | hash a strict bytestring into a digest bytestring
+hash :: ByteString -> ByteString
+hash d = unsafePerformIO $ allocInternal $ \ptr -> do
+	c_sha224_init ptr >> updateInternalIO ptr d >> finalizeInternalIO ptr
+
+{-# NOINLINE hashlazy #-}
+-- | hash a lazy bytestring into a digest bytestring
+hashlazy :: L.ByteString -> ByteString
+hashlazy l = unsafePerformIO $ allocInternal $ \ptr -> do
+	c_sha224_init ptr >> mapM_ (updateInternalIO ptr) (L.toChunks l) >> finalizeInternalIO ptr
diff --git a/Crypto/Hash/SHA256.hs b/Crypto/Hash/SHA256.hs
new file mode 100644
--- /dev/null
+++ b/Crypto/Hash/SHA256.hs
@@ -0,0 +1,120 @@
+{-# LANGUAGE ForeignFunctionInterface, CPP, MultiParamTypeClasses #-}
+
+-- |
+-- Module      : Crypto.Hash.SHA256
+-- License     : BSD-style
+-- Maintainer  : Vincent Hanquez <vincent@snarc.org>
+-- Stability   : experimental
+-- Portability : unknown
+--
+-- A module containing SHA256 bindings
+--
+module Crypto.Hash.SHA256
+	( Ctx(..)
+	, SHA256
+
+	-- * Incremental hashing Functions
+	, init     -- :: Ctx
+	, update   -- :: Ctx -> ByteString -> Ctx
+	, finalize -- :: Ctx -> ByteString
+
+	-- * Single Pass hashing
+	, hash     -- :: ByteString -> ByteString
+	, hashlazy -- :: ByteString -> ByteString
+	) where
+
+import Prelude hiding (init)
+import Foreign
+import Foreign.C.String
+import qualified Data.ByteString as B
+import qualified Data.ByteString.Lazy as L
+import Data.ByteString (ByteString)
+import Data.ByteString.Unsafe (unsafeUseAsCString, unsafeUseAsCStringLen)
+import Data.ByteString.Internal (create, memcpy)
+
+#ifdef HAVE_CRYPTOAPI
+
+import Control.Monad (liftM)
+import Data.Serialize (Serialize(..))
+import Data.Serialize.Get (getByteString)
+import Data.Serialize.Put (putByteString)
+import Data.Tagged (Tagged(..))
+import qualified Crypto.Classes as C (Hash(..))
+
+instance C.Hash Ctx SHA256 where
+	outputLength    = Tagged (32 * 8)
+	blockLength     = Tagged (64 * 8)
+	initialCtx      = init
+	updateCtx       = update
+	finalize ctx bs = Digest . finalize $ update ctx bs
+
+instance Serialize SHA256 where
+	get            = liftM Digest (getByteString digestSize)
+	put (Digest d) = putByteString d
+
+#endif
+
+data Ctx = Ctx !ByteString
+data SHA256 = Digest !ByteString
+	deriving (Eq,Ord,Show)
+
+digestSize, sizeCtx :: Int
+digestSize = 32
+sizeCtx = 192
+
+instance Storable Ctx where
+	sizeOf _    = sizeCtx
+	alignment _ = 16
+	poke ptr (Ctx b) = unsafeUseAsCString b (\cs -> memcpy (castPtr ptr) (castPtr cs) (fromIntegral sizeCtx))
+
+	peek ptr = create sizeCtx (\bptr -> memcpy bptr (castPtr ptr) (fromIntegral sizeCtx)) >>= return . Ctx
+
+foreign import ccall unsafe "sha256.h sha256_init"
+	c_sha256_init :: Ptr Ctx -> IO ()
+
+foreign import ccall "sha256.h sha256_update"
+	c_sha256_update :: Ptr Ctx -> CString -> Word32 -> IO ()
+
+foreign import ccall unsafe "sha256.h sha256_finalize"
+	c_sha256_finalize :: Ptr Ctx -> CString -> IO ()
+
+allocInternal :: (Ptr Ctx -> IO a) -> IO a
+allocInternal = alloca
+
+allocInternalFrom :: Ctx -> (Ptr Ctx -> IO a) -> IO a
+allocInternalFrom ctx f = allocInternal $ \ptr -> (poke ptr ctx >> f ptr)
+
+updateInternalIO :: Ptr Ctx -> ByteString -> IO ()
+updateInternalIO ptr d =
+	unsafeUseAsCStringLen d (\(cs, len) -> c_sha256_update ptr cs (fromIntegral len))
+
+finalizeInternalIO :: Ptr Ctx -> IO ByteString
+finalizeInternalIO ptr =
+	allocaBytes digestSize (\cs -> c_sha256_finalize ptr cs >> B.packCStringLen (cs, digestSize))
+
+{-# NOINLINE init #-}
+-- | init a context
+init :: Ctx
+init = unsafePerformIO $ allocInternal $ \ptr -> do (c_sha256_init ptr >> peek ptr)
+
+{-# NOINLINE update #-}
+-- | update a context with a bytestring
+update :: Ctx -> ByteString -> Ctx
+update ctx d = unsafePerformIO $ allocInternalFrom ctx $ \ptr -> do updateInternalIO ptr d >> peek ptr
+
+{-# NOINLINE finalize #-}
+-- | finalize the context into a digest bytestring
+finalize :: Ctx -> ByteString
+finalize ctx = unsafePerformIO $ allocInternalFrom ctx $ \ptr -> do finalizeInternalIO ptr
+
+{-# NOINLINE hash #-}
+-- | hash a strict bytestring into a digest bytestring
+hash :: ByteString -> ByteString
+hash d = unsafePerformIO $ allocInternal $ \ptr -> do
+	c_sha256_init ptr >> updateInternalIO ptr d >> finalizeInternalIO ptr
+
+{-# NOINLINE hashlazy #-}
+-- | hash a lazy bytestring into a digest bytestring
+hashlazy :: L.ByteString -> ByteString
+hashlazy l = unsafePerformIO $ allocInternal $ \ptr -> do
+	c_sha256_init ptr >> mapM_ (updateInternalIO ptr) (L.toChunks l) >> finalizeInternalIO ptr
diff --git a/Crypto/Hash/SHA384.hs b/Crypto/Hash/SHA384.hs
new file mode 100644
--- /dev/null
+++ b/Crypto/Hash/SHA384.hs
@@ -0,0 +1,120 @@
+{-# LANGUAGE ForeignFunctionInterface, CPP, MultiParamTypeClasses #-}
+
+-- |
+-- Module      : Crypto.Hash.SHA384
+-- License     : BSD-style
+-- Maintainer  : Vincent Hanquez <vincent@snarc.org>
+-- Stability   : experimental
+-- Portability : unknown
+--
+-- A module containing SHA384 bindings
+--
+module Crypto.Hash.SHA384
+	( Ctx(..)
+	, SHA384
+
+	-- * Incremental hashing Functions
+	, init     -- :: Ctx
+	, update   -- :: Ctx -> ByteString -> Ctx
+	, finalize -- :: Ctx -> ByteString
+
+	-- * Single Pass hashing
+	, hash     -- :: ByteString -> ByteString
+	, hashlazy -- :: ByteString -> ByteString
+	) where
+
+import Prelude hiding (init)
+import Foreign
+import Foreign.C.String
+import qualified Data.ByteString as B
+import qualified Data.ByteString.Lazy as L
+import Data.ByteString (ByteString)
+import Data.ByteString.Unsafe (unsafeUseAsCString, unsafeUseAsCStringLen)
+import Data.ByteString.Internal (create, memcpy)
+
+#ifdef HAVE_CRYPTOAPI
+
+import Control.Monad (liftM)
+import Data.Serialize (Serialize(..))
+import Data.Serialize.Get (getByteString)
+import Data.Serialize.Put (putByteString)
+import Data.Tagged (Tagged(..))
+import qualified Crypto.Classes as C (Hash(..))
+
+instance C.Hash Ctx SHA384 where
+	outputLength    = Tagged (48 * 8)
+	blockLength     = Tagged (128 * 8)
+	initialCtx      = init
+	updateCtx       = update
+	finalize ctx bs = Digest . finalize $ update ctx bs
+
+instance Serialize SHA384 where
+	get            = liftM Digest (getByteString digestSize)
+	put (Digest d) = putByteString d
+
+#endif
+
+data Ctx = Ctx !ByteString
+data SHA384 = Digest !ByteString
+	deriving (Eq,Ord,Show)
+
+digestSize, sizeCtx :: Int
+digestSize = 48
+sizeCtx = 256
+
+instance Storable Ctx where
+	sizeOf _    = sizeCtx
+	alignment _ = 16
+	poke ptr (Ctx b) = unsafeUseAsCString b (\cs -> memcpy (castPtr ptr) (castPtr cs) (fromIntegral sizeCtx))
+
+	peek ptr = create sizeCtx (\bptr -> memcpy bptr (castPtr ptr) (fromIntegral sizeCtx)) >>= return . Ctx
+
+foreign import ccall unsafe "sha512.h sha384_init"
+	c_sha384_init :: Ptr Ctx -> IO ()
+
+foreign import ccall "sha512.h sha384_update"
+	c_sha384_update :: Ptr Ctx -> CString -> Word32 -> IO ()
+
+foreign import ccall unsafe "sha512.h sha384_finalize"
+	c_sha384_finalize :: Ptr Ctx -> CString -> IO ()
+
+allocInternal :: (Ptr Ctx -> IO a) -> IO a
+allocInternal = alloca
+
+allocInternalFrom :: Ctx -> (Ptr Ctx -> IO a) -> IO a
+allocInternalFrom ctx f = allocInternal $ \ptr -> (poke ptr ctx >> f ptr)
+
+updateInternalIO :: Ptr Ctx -> ByteString -> IO ()
+updateInternalIO ptr d =
+	unsafeUseAsCStringLen d (\(cs, len) -> c_sha384_update ptr cs (fromIntegral len))
+
+finalizeInternalIO :: Ptr Ctx -> IO ByteString
+finalizeInternalIO ptr =
+	allocaBytes digestSize (\cs -> c_sha384_finalize ptr cs >> B.packCStringLen (cs, digestSize))
+
+{-# NOINLINE init #-}
+-- | init a context
+init :: Ctx
+init = unsafePerformIO $ allocInternal $ \ptr -> do (c_sha384_init ptr >> peek ptr)
+
+{-# NOINLINE update #-}
+-- | update a context with a bytestring
+update :: Ctx -> ByteString -> Ctx
+update ctx d = unsafePerformIO $ allocInternalFrom ctx $ \ptr -> do updateInternalIO ptr d >> peek ptr
+
+{-# NOINLINE finalize #-}
+-- | finalize the context into a digest bytestring
+finalize :: Ctx -> ByteString
+finalize ctx = unsafePerformIO $ allocInternalFrom ctx $ \ptr -> do finalizeInternalIO ptr
+
+{-# NOINLINE hash #-}
+-- | hash a strict bytestring into a digest bytestring
+hash :: ByteString -> ByteString
+hash d = unsafePerformIO $ allocInternal $ \ptr -> do
+	c_sha384_init ptr >> updateInternalIO ptr d >> finalizeInternalIO ptr
+
+{-# NOINLINE hashlazy #-}
+-- | hash a lazy bytestring into a digest bytestring
+hashlazy :: L.ByteString -> ByteString
+hashlazy l = unsafePerformIO $ allocInternal $ \ptr -> do
+	c_sha384_init ptr >> mapM_ (updateInternalIO ptr) (L.toChunks l) >> finalizeInternalIO ptr
diff --git a/Crypto/Hash/SHA512.hs b/Crypto/Hash/SHA512.hs
new file mode 100644
--- /dev/null
+++ b/Crypto/Hash/SHA512.hs
@@ -0,0 +1,120 @@
+{-# LANGUAGE ForeignFunctionInterface, CPP, MultiParamTypeClasses #-}
+
+-- |
+-- Module      : Crypto.Hash.SHA512
+-- License     : BSD-style
+-- Maintainer  : Vincent Hanquez <vincent@snarc.org>
+-- Stability   : experimental
+-- Portability : unknown
+--
+-- A module containing SHA512 bindings
+--
+module Crypto.Hash.SHA512
+	( Ctx(..)
+	, SHA512
+
+	-- * Incremental hashing Functions
+	, init     -- :: Ctx
+	, update   -- :: Ctx -> ByteString -> Ctx
+	, finalize -- :: Ctx -> ByteString
+
+	-- * Single Pass hashing
+	, hash     -- :: ByteString -> ByteString
+	, hashlazy -- :: ByteString -> ByteString
+	) where
+
+import Prelude hiding (init)
+import Foreign
+import Foreign.C.String
+import qualified Data.ByteString as B
+import qualified Data.ByteString.Lazy as L
+import Data.ByteString (ByteString)
+import Data.ByteString.Unsafe (unsafeUseAsCString, unsafeUseAsCStringLen)
+import Data.ByteString.Internal (create, memcpy)
+
+#ifdef HAVE_CRYPTOAPI
+
+import Control.Monad (liftM)
+import Data.Serialize (Serialize(..))
+import Data.Serialize.Get (getByteString)
+import Data.Serialize.Put (putByteString)
+import Data.Tagged (Tagged(..))
+import qualified Crypto.Classes as C (Hash(..))
+
+instance C.Hash Ctx SHA512 where
+	outputLength    = Tagged (64 * 8)
+	blockLength     = Tagged (128 * 8)
+	initialCtx      = init
+	updateCtx       = update
+	finalize ctx bs = Digest . finalize $ update ctx bs
+
+instance Serialize SHA512 where
+	get            = liftM Digest (getByteString digestSize)
+	put (Digest d) = putByteString d
+
+#endif
+
+data Ctx = Ctx !ByteString
+data SHA512 = Digest !ByteString
+	deriving (Eq,Ord,Show)
+
+digestSize, sizeCtx :: Int
+digestSize = 64
+sizeCtx = 256
+
+instance Storable Ctx where
+	sizeOf _    = sizeCtx
+	alignment _ = 16
+	poke ptr (Ctx b) = unsafeUseAsCString b (\cs -> memcpy (castPtr ptr) (castPtr cs) (fromIntegral sizeCtx))
+
+	peek ptr = create sizeCtx (\bptr -> memcpy bptr (castPtr ptr) (fromIntegral sizeCtx)) >>= return . Ctx
+
+foreign import ccall unsafe "sha512.h sha512_init"
+	c_sha512_init :: Ptr Ctx -> IO ()
+
+foreign import ccall "sha512.h sha512_update"
+	c_sha512_update :: Ptr Ctx -> CString -> Word32 -> IO ()
+
+foreign import ccall unsafe "sha512.h sha512_finalize"
+	c_sha512_finalize :: Ptr Ctx -> CString -> IO ()
+
+allocInternal :: (Ptr Ctx -> IO a) -> IO a
+allocInternal = alloca
+
+allocInternalFrom :: Ctx -> (Ptr Ctx -> IO a) -> IO a
+allocInternalFrom ctx f = allocInternal $ \ptr -> (poke ptr ctx >> f ptr)
+
+updateInternalIO :: Ptr Ctx -> ByteString -> IO ()
+updateInternalIO ptr d =
+	unsafeUseAsCStringLen d (\(cs, len) -> c_sha512_update ptr cs (fromIntegral len))
+
+finalizeInternalIO :: Ptr Ctx -> IO ByteString
+finalizeInternalIO ptr =
+	allocaBytes digestSize (\cs -> c_sha512_finalize ptr cs >> B.packCStringLen (cs, digestSize))
+
+{-# NOINLINE init #-}
+-- | init a context
+init :: Ctx
+init = unsafePerformIO $ allocInternal $ \ptr -> do (c_sha512_init ptr >> peek ptr)
+
+{-# NOINLINE update #-}
+-- | update a context with a bytestring
+update :: Ctx -> ByteString -> Ctx
+update ctx d = unsafePerformIO $ allocInternalFrom ctx $ \ptr -> do updateInternalIO ptr d >> peek ptr
+
+{-# NOINLINE finalize #-}
+-- | finalize the context into a digest bytestring
+finalize :: Ctx -> ByteString
+finalize ctx = unsafePerformIO $ allocInternalFrom ctx $ \ptr -> do finalizeInternalIO ptr
+
+{-# NOINLINE hash #-}
+-- | hash a strict bytestring into a digest bytestring
+hash :: ByteString -> ByteString
+hash d = unsafePerformIO $ allocInternal $ \ptr -> do
+	c_sha512_init ptr >> updateInternalIO ptr d >> finalizeInternalIO ptr
+
+{-# NOINLINE hashlazy #-}
+-- | hash a lazy bytestring into a digest bytestring
+hashlazy :: L.ByteString -> ByteString
+hashlazy l = unsafePerformIO $ allocInternal $ \ptr -> do
+	c_sha512_init ptr >> mapM_ (updateInternalIO ptr) (L.toChunks l) >> finalizeInternalIO ptr
diff --git a/Crypto/Hash/Skein256.hs b/Crypto/Hash/Skein256.hs
new file mode 100644
--- /dev/null
+++ b/Crypto/Hash/Skein256.hs
@@ -0,0 +1,127 @@
+{-# LANGUAGE ForeignFunctionInterface, CPP, MultiParamTypeClasses #-}
+
+-- |
+-- Module      : Crypto.Hash.Skein256
+-- License     : BSD-style
+-- Maintainer  : Vincent Hanquez <vincent@snarc.org>
+-- Stability   : experimental
+-- Portability : unknown
+--
+-- A module containing Skein256 bindings
+--
+module Crypto.Hash.Skein256
+	( Ctx(..)
+	, Skein256
+
+	-- * Incremental hashing Functions
+	, init     -- :: Int -> Ctx
+	, update   -- :: Ctx -> ByteString -> Ctx
+	, finalize -- :: Ctx -> ByteString
+
+	-- * Single Pass hashing
+	, hash     -- :: Int -> ByteString -> ByteString
+	, hashlazy -- :: Int -> ByteString -> ByteString
+	) where
+
+import Prelude hiding (init)
+import Foreign
+import Foreign.C.String
+import Foreign.C.Types
+import qualified Data.ByteString as B
+import qualified Data.ByteString.Lazy as L
+import Data.ByteString (ByteString)
+import Data.ByteString.Unsafe (unsafeUseAsCString, unsafeUseAsCStringLen)
+import Data.ByteString.Internal (create, memcpy)
+
+#ifdef HAVE_CRYPTOAPI
+
+import Control.Monad (liftM)
+import Data.Serialize (Serialize(..))
+import Data.Serialize.Get (getByteString)
+import Data.Serialize.Put (putByteString)
+import Data.Tagged (Tagged(..))
+import qualified Crypto.Classes as C (Hash(..))
+
+instance C.Hash Ctx Skein256 where
+	outputLength    = Tagged (32 * 8)
+	blockLength     = Tagged (32 * 8)
+	initialCtx      = init (32 * 8)
+	updateCtx       = update
+	finalize ctx bs = Digest . finalize $ update ctx bs
+
+instance Serialize Skein256 where
+	get            = liftM Digest (getByteString 32)
+	put (Digest d) = putByteString d
+
+#endif
+
+data Ctx = Ctx !ByteString
+data Skein256 = Digest !ByteString
+	deriving (Eq,Ord,Show)
+
+sizeCtx :: Int
+sizeCtx = 100
+
+instance Storable Ctx where
+	sizeOf _    = sizeCtx
+	alignment _ = 16
+	poke ptr (Ctx b) = unsafeUseAsCString b (\cs -> memcpy (castPtr ptr) (castPtr cs) (fromIntegral sizeCtx))
+
+	peek ptr = create sizeCtx (\bptr -> memcpy bptr (castPtr ptr) (fromIntegral sizeCtx)) >>= return . Ctx
+
+poke_hashlen :: Ptr Ctx -> IO Int
+poke_hashlen ptr = do
+	let iptr = castPtr ptr :: Ptr CUInt
+	a <- peek iptr
+	return $ fromIntegral a
+
+foreign import ccall unsafe "skein256.h skein256_init"
+	c_skein256_init :: Ptr Ctx -> CUInt -> IO ()
+
+foreign import ccall "skein256.h skein256_update"
+	c_skein256_update :: Ptr Ctx -> CString -> Word32 -> IO ()
+
+foreign import ccall unsafe "skein256.h skein256_finalize"
+	c_skein256_finalize :: Ptr Ctx -> CString -> IO ()
+
+allocInternal :: (Ptr Ctx -> IO a) -> IO a
+allocInternal = alloca
+
+allocInternalFrom :: Ctx -> (Ptr Ctx -> IO a) -> IO a
+allocInternalFrom ctx f = allocInternal $ \ptr -> (poke ptr ctx >> f ptr)
+
+updateInternalIO :: Ptr Ctx -> ByteString -> IO ()
+updateInternalIO ptr d =
+	unsafeUseAsCStringLen d (\(cs, len) -> c_skein256_update ptr cs (fromIntegral len))
+
+finalizeInternalIO :: Ptr Ctx -> IO ByteString
+finalizeInternalIO ptr = do
+	digestSize <- fmap (\x -> (x + 7) `shiftR` 3) $ poke_hashlen ptr
+	allocaBytes digestSize (\cs -> c_skein256_finalize ptr cs >> B.packCStringLen (cs, digestSize))
+
+{-# NOINLINE init #-}
+-- | init a context
+init :: Int -> Ctx
+init hashlen = unsafePerformIO $ allocInternal $ \ptr -> do (c_skein256_init ptr (fromIntegral hashlen) >> peek ptr)
+
+{-# NOINLINE update #-}
+-- | update a context with a bytestring
+update :: Ctx -> ByteString -> Ctx
+update ctx d = unsafePerformIO $ allocInternalFrom ctx $ \ptr -> do updateInternalIO ptr d >> peek ptr
+
+{-# NOINLINE finalize #-}
+-- | finalize the context into a digest bytestring
+finalize :: Ctx -> ByteString
+finalize ctx = unsafePerformIO $ allocInternalFrom ctx $ \ptr -> do finalizeInternalIO ptr
+
+{-# NOINLINE hash #-}
+-- | hash a strict bytestring into a digest bytestring
+hash :: Int -> ByteString -> ByteString
+hash hashlen d = unsafePerformIO $ allocInternal $ \ptr -> do
+	c_skein256_init ptr (fromIntegral hashlen) >> updateInternalIO ptr d >> finalizeInternalIO ptr
+
+{-# NOINLINE hashlazy #-}
+-- | hash a lazy bytestring into a digest bytestring
+hashlazy :: Int -> L.ByteString -> ByteString
+hashlazy hashlen l = unsafePerformIO $ allocInternal $ \ptr -> do
+	c_skein256_init ptr (fromIntegral hashlen) >> mapM_ (updateInternalIO ptr) (L.toChunks l) >> finalizeInternalIO ptr
diff --git a/Crypto/Hash/Skein512.hs b/Crypto/Hash/Skein512.hs
new file mode 100644
--- /dev/null
+++ b/Crypto/Hash/Skein512.hs
@@ -0,0 +1,127 @@
+{-# LANGUAGE ForeignFunctionInterface, CPP, MultiParamTypeClasses #-}
+
+-- |
+-- Module      : Crypto.Hash.Skein512
+-- License     : BSD-style
+-- Maintainer  : Vincent Hanquez <vincent@snarc.org>
+-- Stability   : experimental
+-- Portability : unknown
+--
+-- A module containing Skein512 bindings
+--
+module Crypto.Hash.Skein512
+	( Ctx(..)
+	, Skein512
+
+	-- * Incremental hashing Functions
+	, init     -- :: Int -> Ctx
+	, update   -- :: Ctx -> ByteString -> Ctx
+	, finalize -- :: Ctx -> ByteString
+
+	-- * Single Pass hashing
+	, hash     -- :: Int -> ByteString -> ByteString
+	, hashlazy -- :: Int -> ByteString -> ByteString
+	) where
+
+import Prelude hiding (init)
+import Foreign
+import Foreign.C.String
+import Foreign.C.Types
+import qualified Data.ByteString as B
+import qualified Data.ByteString.Lazy as L
+import Data.ByteString (ByteString)
+import Data.ByteString.Unsafe (unsafeUseAsCString, unsafeUseAsCStringLen)
+import Data.ByteString.Internal (create, memcpy)
+
+#ifdef HAVE_CRYPTOAPI
+
+import Control.Monad (liftM)
+import Data.Serialize (Serialize(..))
+import Data.Serialize.Get (getByteString)
+import Data.Serialize.Put (putByteString)
+import Data.Tagged (Tagged(..))
+import qualified Crypto.Classes as C (Hash(..))
+
+instance C.Hash Ctx Skein512 where
+	outputLength    = Tagged (64 * 8)
+	blockLength     = Tagged (64 * 8)
+	initialCtx      = init (64 * 8)
+	updateCtx       = update
+	finalize ctx bs = Digest . finalize $ update ctx bs
+
+instance Serialize Skein512 where
+	get            = liftM Digest (getByteString 64)
+	put (Digest d) = putByteString d
+
+#endif
+
+data Ctx = Ctx !ByteString
+data Skein512 = Digest !ByteString
+	deriving (Eq,Ord,Show)
+
+sizeCtx :: Int
+sizeCtx = 160
+
+instance Storable Ctx where
+	sizeOf _    = sizeCtx
+	alignment _ = 16
+	poke ptr (Ctx b) = unsafeUseAsCString b (\cs -> memcpy (castPtr ptr) (castPtr cs) (fromIntegral sizeCtx))
+
+	peek ptr = create sizeCtx (\bptr -> memcpy bptr (castPtr ptr) (fromIntegral sizeCtx)) >>= return . Ctx
+
+poke_hashlen :: Ptr Ctx -> IO Int
+poke_hashlen ptr = do
+	let iptr = castPtr ptr :: Ptr CUInt
+	a <- peek iptr
+	return $ fromIntegral a
+
+foreign import ccall unsafe "skein512.h skein512_init"
+	c_skein512_init :: Ptr Ctx -> CUInt -> IO ()
+
+foreign import ccall "skein512.h skein512_update"
+	c_skein512_update :: Ptr Ctx -> CString -> Word32 -> IO ()
+
+foreign import ccall unsafe "skein512.h skein512_finalize"
+	c_skein512_finalize :: Ptr Ctx -> CString -> IO ()
+
+allocInternal :: (Ptr Ctx -> IO a) -> IO a
+allocInternal = alloca
+
+allocInternalFrom :: Ctx -> (Ptr Ctx -> IO a) -> IO a
+allocInternalFrom ctx f = allocInternal $ \ptr -> (poke ptr ctx >> f ptr)
+
+updateInternalIO :: Ptr Ctx -> ByteString -> IO ()
+updateInternalIO ptr d =
+	unsafeUseAsCStringLen d (\(cs, len) -> c_skein512_update ptr cs (fromIntegral len))
+
+finalizeInternalIO :: Ptr Ctx -> IO ByteString
+finalizeInternalIO ptr = do
+	digestSize <- fmap (\x -> (x + 7) `shiftR` 3) $ poke_hashlen ptr
+	allocaBytes digestSize (\cs -> c_skein512_finalize ptr cs >> B.packCStringLen (cs, digestSize))
+
+{-# NOINLINE init #-}
+-- | init a context
+init :: Int -> Ctx
+init hashlen = unsafePerformIO $ allocInternal $ \ptr -> do (c_skein512_init ptr (fromIntegral hashlen) >> peek ptr)
+
+{-# NOINLINE update #-}
+-- | update a context with a bytestring
+update :: Ctx -> ByteString -> Ctx
+update ctx d = unsafePerformIO $ allocInternalFrom ctx $ \ptr -> do updateInternalIO ptr d >> peek ptr
+
+{-# NOINLINE finalize #-}
+-- | finalize the context into a digest bytestring
+finalize :: Ctx -> ByteString
+finalize ctx = unsafePerformIO $ allocInternalFrom ctx $ \ptr -> do finalizeInternalIO ptr
+
+{-# NOINLINE hash #-}
+-- | hash a strict bytestring into a digest bytestring
+hash :: Int -> ByteString -> ByteString
+hash hashlen d = unsafePerformIO $ allocInternal $ \ptr -> do
+	c_skein512_init ptr (fromIntegral hashlen) >> updateInternalIO ptr d >> finalizeInternalIO ptr
+
+{-# NOINLINE hashlazy #-}
+-- | hash a lazy bytestring into a digest bytestring
+hashlazy :: Int -> L.ByteString -> ByteString
+hashlazy hashlen l = unsafePerformIO $ allocInternal $ \ptr -> do
+	c_skein512_init ptr (fromIntegral hashlen) >> mapM_ (updateInternalIO ptr) (L.toChunks l) >> finalizeInternalIO ptr
diff --git a/Crypto/Hash/Tiger.hs b/Crypto/Hash/Tiger.hs
new file mode 100644
--- /dev/null
+++ b/Crypto/Hash/Tiger.hs
@@ -0,0 +1,120 @@
+{-# LANGUAGE ForeignFunctionInterface, CPP, MultiParamTypeClasses #-}
+
+-- |
+-- Module      : Crypto.Hash.Tiger
+-- License     : BSD-style
+-- Maintainer  : Vincent Hanquez <vincent@snarc.org>
+-- Stability   : experimental
+-- Portability : unknown
+--
+-- A module containing Tiger bindings
+--
+module Crypto.Hash.Tiger
+	( Ctx(..)
+	, Tiger
+
+	-- * Incremental hashing Functions
+	, init     -- :: Ctx
+	, update   -- :: Ctx -> ByteString -> Ctx
+	, finalize -- :: Ctx -> ByteString
+
+	-- * Single Pass hashing
+	, hash     -- :: ByteString -> ByteString
+	, hashlazy -- :: ByteString -> ByteString
+	) where
+
+import Prelude hiding (init)
+import Foreign
+import Foreign.C.String
+import qualified Data.ByteString as B
+import qualified Data.ByteString.Lazy as L
+import Data.ByteString (ByteString)
+import Data.ByteString.Unsafe (unsafeUseAsCString, unsafeUseAsCStringLen)
+import Data.ByteString.Internal (create, memcpy)
+
+#ifdef HAVE_CRYPTOAPI
+
+import Control.Monad (liftM)
+import Data.Serialize (Serialize(..))
+import Data.Serialize.Get (getByteString)
+import Data.Serialize.Put (putByteString)
+import Data.Tagged (Tagged(..))
+import qualified Crypto.Classes as C (Hash(..))
+
+instance C.Hash Ctx Tiger where
+	outputLength    = Tagged (24 * 8)
+	blockLength     = Tagged (64 * 8)
+	initialCtx      = init
+	updateCtx       = update
+	finalize ctx bs = Digest . finalize $ update ctx bs
+
+instance Serialize Tiger where
+	get            = liftM Digest (getByteString digestSize)
+	put (Digest d) = putByteString d
+
+#endif
+
+data Ctx = Ctx !ByteString
+data Tiger = Digest !ByteString
+	deriving (Eq,Ord,Show)
+
+digestSize, sizeCtx :: Int
+digestSize = 24
+sizeCtx = 96
+
+instance Storable Ctx where
+	sizeOf _    = sizeCtx
+	alignment _ = 16
+	poke ptr (Ctx b) = unsafeUseAsCString b (\cs -> memcpy (castPtr ptr) (castPtr cs) (fromIntegral sizeCtx))
+
+	peek ptr = create sizeCtx (\bptr -> memcpy bptr (castPtr ptr) (fromIntegral sizeCtx)) >>= return . Ctx
+
+foreign import ccall unsafe "tiger.h tiger_init"
+	c_tiger_init :: Ptr Ctx -> IO ()
+
+foreign import ccall "tiger.h tiger_update"
+	c_tiger_update :: Ptr Ctx -> CString -> Word32 -> IO ()
+
+foreign import ccall unsafe "tiger.h tiger_finalize"
+	c_tiger_finalize :: Ptr Ctx -> CString -> IO ()
+
+allocInternal :: (Ptr Ctx -> IO a) -> IO a
+allocInternal = alloca
+
+allocInternalFrom :: Ctx -> (Ptr Ctx -> IO a) -> IO a
+allocInternalFrom ctx f = allocInternal $ \ptr -> (poke ptr ctx >> f ptr)
+
+updateInternalIO :: Ptr Ctx -> ByteString -> IO ()
+updateInternalIO ptr d =
+	unsafeUseAsCStringLen d (\(cs, len) -> c_tiger_update ptr cs (fromIntegral len))
+
+finalizeInternalIO :: Ptr Ctx -> IO ByteString
+finalizeInternalIO ptr =
+	allocaBytes digestSize (\cs -> c_tiger_finalize ptr cs >> B.packCStringLen (cs, digestSize))
+
+{-# NOINLINE init #-}
+-- | init a context
+init :: Ctx
+init = unsafePerformIO $ allocInternal $ \ptr -> do (c_tiger_init ptr >> peek ptr)
+
+{-# NOINLINE update #-}
+-- | update a context with a bytestring
+update :: Ctx -> ByteString -> Ctx
+update ctx d = unsafePerformIO $ allocInternalFrom ctx $ \ptr -> do updateInternalIO ptr d >> peek ptr
+
+{-# NOINLINE finalize #-}
+-- | finalize the context into a digest bytestring
+finalize :: Ctx -> ByteString
+finalize ctx = unsafePerformIO $ allocInternalFrom ctx $ \ptr -> do finalizeInternalIO ptr
+
+{-# NOINLINE hash #-}
+-- | hash a strict bytestring into a digest bytestring
+hash :: ByteString -> ByteString
+hash d = unsafePerformIO $ allocInternal $ \ptr -> do
+	c_tiger_init ptr >> updateInternalIO ptr d >> finalizeInternalIO ptr
+
+{-# NOINLINE hashlazy #-}
+-- | hash a lazy bytestring into a digest bytestring
+hashlazy :: L.ByteString -> ByteString
+hashlazy l = unsafePerformIO $ allocInternal $ \ptr -> do
+	c_tiger_init ptr >> mapM_ (updateInternalIO ptr) (L.toChunks l) >> finalizeInternalIO ptr
diff --git a/Data/CryptoHash/MD2.hs b/Data/CryptoHash/MD2.hs
--- a/Data/CryptoHash/MD2.hs
+++ b/Data/CryptoHash/MD2.hs
@@ -1,5 +1,3 @@
-{-# LANGUAGE ForeignFunctionInterface #-}
-
 -- |
 -- Module      : Data.CryptoHash.MD2
 -- License     : BSD-style
@@ -7,7 +5,7 @@
 -- Stability   : experimental
 -- Portability : unknown
 --
--- A module containing MD2 bindings
+-- compatibility module for MD2. use Crypto.Hash.MD2 instead.
 --
 module Data.CryptoHash.MD2 (
 	Ctx(..),
@@ -22,76 +20,28 @@
 	hashlazy   -- :: ByteString -> ByteString
 	) where
 
-import Prelude hiding (init)
-import Foreign
-import Foreign.C.String
-import qualified Data.ByteString as B
-import qualified Data.ByteString.Lazy as L
+import Prelude ()
+import Crypto.Hash.MD2 (Ctx(..))
+import qualified Crypto.Hash.MD2 as R
 import Data.ByteString (ByteString)
-import Data.ByteString.Unsafe (unsafeUseAsCString, unsafeUseAsCStringLen)
-import Data.ByteString.Internal (create, memcpy)
-
-data Ctx = Ctx !ByteString
-
-digestSize :: Int
-sizeCtx :: Int
-
-digestSize = 16
-sizeCtx = 96
-
-instance Storable Ctx where
-	sizeOf _    = sizeCtx
-	alignment _ = 16
-	poke ptr (Ctx b) = unsafeUseAsCString b (\cs -> memcpy (castPtr ptr) (castPtr cs) (fromIntegral sizeCtx))
-
-	peek ptr = create sizeCtx (\bptr -> memcpy bptr (castPtr ptr) (fromIntegral sizeCtx)) >>= return . Ctx
-
-foreign import ccall unsafe "md2.h md2_init"
-	c_md2_init :: Ptr Ctx -> IO ()
-
-foreign import ccall "md2.h md2_update"
-	c_md2_update :: Ptr Ctx -> CString -> Word32 -> IO ()
-
-foreign import ccall unsafe "md2.h md2_finalize"
-	c_md2_finalize :: Ptr Ctx -> CString -> IO ()
-
-allocInternal :: (Ptr Ctx -> IO a) -> IO a
-allocInternal = alloca
-
-allocInternalFrom :: Ctx -> (Ptr Ctx -> IO a) -> IO a
-allocInternalFrom ctx f = allocInternal $ \ptr -> (poke ptr ctx >> f ptr)
-
-updateInternalIO :: Ptr Ctx -> ByteString -> IO ()
-updateInternalIO ptr d =
-	unsafeUseAsCStringLen d (\(cs, len) -> c_md2_update ptr cs (fromIntegral len))
-
-finalizeInternalIO :: Ptr Ctx -> IO ByteString
-finalizeInternalIO ptr =
-	allocaBytes digestSize (\cs -> c_md2_finalize ptr cs >> B.packCStringLen (cs, digestSize))
+import qualified Data.ByteString.Lazy as L (ByteString)
 
-{-# NOINLINE init #-}
--- | init a context
+{-# DEPRECATED init "use crypto.hash.MD2" #-}
 init :: Ctx
-init = unsafePerformIO $ allocInternal $ \ptr -> do (c_md2_init ptr >> peek ptr)
+init = R.init
 
-{-# NOINLINE update #-}
--- | update a context with a bytestring
+{-# DEPRECATED update "use crypto.hash.MD2" #-}
 update :: Ctx -> ByteString -> Ctx
-update ctx d = unsafePerformIO $ allocInternalFrom ctx $ \ptr -> do updateInternalIO ptr d >> peek ptr
+update = R.update
 
-{-# NOINLINE finalize #-}
--- | finalize the context into a digest bytestring
+{-# DEPRECATED finalize "use crypto.hash.MD2" #-}
 finalize :: Ctx -> ByteString
-finalize ctx = unsafePerformIO $ allocInternalFrom ctx $ \ptr -> do finalizeInternalIO ptr
+finalize = R.finalize
 
-{-# NOINLINE hash #-}
--- | hash a strict bytestring into a digest bytestring
+{-# DEPRECATED hash "use crypto.hash.MD2" #-}
 hash :: ByteString -> ByteString
-hash d = unsafePerformIO $ allocInternal $ \ptr -> do
-	c_md2_init ptr >> updateInternalIO ptr d >> finalizeInternalIO ptr
+hash = R.hash
 
-{-# NOINLINE hashlazy #-}
--- | hash a lazy bytestring into a digest bytestring
+{-# DEPRECATED hashlazy "use crypto.hash.MD2" #-}
 hashlazy :: L.ByteString -> ByteString
-hashlazy l = unsafePerformIO $ allocInternal $ \ptr -> do
-	c_md2_init ptr >> mapM_ (updateInternalIO ptr) (L.toChunks l) >> finalizeInternalIO ptr
+hashlazy = R.hashlazy
diff --git a/Data/CryptoHash/MD4.hs b/Data/CryptoHash/MD4.hs
--- a/Data/CryptoHash/MD4.hs
+++ b/Data/CryptoHash/MD4.hs
@@ -1,5 +1,3 @@
-{-# LANGUAGE ForeignFunctionInterface #-}
-
 -- |
 -- Module      : Data.CryptoHash.MD4
 -- License     : BSD-style
@@ -7,7 +5,7 @@
 -- Stability   : experimental
 -- Portability : unknown
 --
--- A module containing MD4 bindings
+-- compatibility module for MD4. use Crypto.Hash.MD4 instead.
 --
 module Data.CryptoHash.MD4 (
 	Ctx(..),
@@ -22,76 +20,28 @@
 	hashlazy   -- :: ByteString -> ByteString
 	) where
 
-import Prelude hiding (init)
-import Foreign
-import Foreign.C.String
-import qualified Data.ByteString as B
-import qualified Data.ByteString.Lazy as L
+import Prelude ()
+import Crypto.Hash.MD4 (Ctx(..))
+import qualified Crypto.Hash.MD4 as R
 import Data.ByteString (ByteString)
-import Data.ByteString.Unsafe (unsafeUseAsCString, unsafeUseAsCStringLen)
-import Data.ByteString.Internal (create, memcpy)
-
-data Ctx = Ctx !ByteString
-
-digestSize :: Int
-sizeCtx :: Int
-
-digestSize = 16
-sizeCtx = 96
-
-instance Storable Ctx where
-	sizeOf _    = sizeCtx
-	alignment _ = 16
-	poke ptr (Ctx b) = unsafeUseAsCString b (\cs -> memcpy (castPtr ptr) (castPtr cs) (fromIntegral sizeCtx))
-
-	peek ptr = create sizeCtx (\bptr -> memcpy bptr (castPtr ptr) (fromIntegral sizeCtx)) >>= return . Ctx
-
-foreign import ccall unsafe "md4.h md4_init"
-	c_md4_init :: Ptr Ctx -> IO ()
-
-foreign import ccall "md4.h md4_update"
-	c_md4_update :: Ptr Ctx -> CString -> Word32 -> IO ()
-
-foreign import ccall unsafe "md4.h md4_finalize"
-	c_md4_finalize :: Ptr Ctx -> CString -> IO ()
-
-allocInternal :: (Ptr Ctx -> IO a) -> IO a
-allocInternal = alloca
-
-allocInternalFrom :: Ctx -> (Ptr Ctx -> IO a) -> IO a
-allocInternalFrom ctx f = allocInternal $ \ptr -> (poke ptr ctx >> f ptr)
-
-updateInternalIO :: Ptr Ctx -> ByteString -> IO ()
-updateInternalIO ptr d =
-	unsafeUseAsCStringLen d (\(cs, len) -> c_md4_update ptr cs (fromIntegral len))
-
-finalizeInternalIO :: Ptr Ctx -> IO ByteString
-finalizeInternalIO ptr =
-	allocaBytes digestSize (\cs -> c_md4_finalize ptr cs >> B.packCStringLen (cs, digestSize))
+import qualified Data.ByteString.Lazy as L (ByteString)
 
-{-# NOINLINE init #-}
--- | init a context
+{-# DEPRECATED init "use crypto.hash.MD4" #-}
 init :: Ctx
-init = unsafePerformIO $ allocInternal $ \ptr -> do (c_md4_init ptr >> peek ptr)
+init = R.init
 
-{-# NOINLINE update #-}
--- | update a context with a bytestring
+{-# DEPRECATED update "use crypto.hash.MD4" #-}
 update :: Ctx -> ByteString -> Ctx
-update ctx d = unsafePerformIO $ allocInternalFrom ctx $ \ptr -> do updateInternalIO ptr d >> peek ptr
+update = R.update
 
-{-# NOINLINE finalize #-}
--- | finalize the context into a digest bytestring
+{-# DEPRECATED finalize "use crypto.hash.MD4" #-}
 finalize :: Ctx -> ByteString
-finalize ctx = unsafePerformIO $ allocInternalFrom ctx $ \ptr -> do finalizeInternalIO ptr
+finalize = R.finalize
 
-{-# NOINLINE hash #-}
--- | hash a strict bytestring into a digest bytestring
+{-# DEPRECATED hash "use crypto.hash.MD4" #-}
 hash :: ByteString -> ByteString
-hash d = unsafePerformIO $ allocInternal $ \ptr -> do
-	c_md4_init ptr >> updateInternalIO ptr d >> finalizeInternalIO ptr
+hash = R.hash
 
-{-# NOINLINE hashlazy #-}
--- | hash a lazy bytestring into a digest bytestring
+{-# DEPRECATED hashlazy "use crypto.hash.MD4" #-}
 hashlazy :: L.ByteString -> ByteString
-hashlazy l = unsafePerformIO $ allocInternal $ \ptr -> do
-	c_md4_init ptr >> mapM_ (updateInternalIO ptr) (L.toChunks l) >> finalizeInternalIO ptr
+hashlazy = R.hashlazy
diff --git a/Data/CryptoHash/MD5.hs b/Data/CryptoHash/MD5.hs
--- a/Data/CryptoHash/MD5.hs
+++ b/Data/CryptoHash/MD5.hs
@@ -1,5 +1,3 @@
-{-# LANGUAGE ForeignFunctionInterface #-}
-
 -- |
 -- Module      : Data.CryptoHash.MD5
 -- License     : BSD-style
@@ -7,7 +5,7 @@
 -- Stability   : experimental
 -- Portability : unknown
 --
--- A module containing MD5 bindings
+-- compatibility module for MD5. use Crypto.Hash.MD5 instead.
 --
 module Data.CryptoHash.MD5 (
 	Ctx(..),
@@ -22,76 +20,28 @@
 	hashlazy   -- :: ByteString -> ByteString
 	) where
 
-import Prelude hiding (init)
-import Foreign
-import Foreign.C.String
-import qualified Data.ByteString as B
-import qualified Data.ByteString.Lazy as L
+import Prelude ()
+import Crypto.Hash.MD5 (Ctx(..))
+import qualified Crypto.Hash.MD5 as R
 import Data.ByteString (ByteString)
-import Data.ByteString.Unsafe (unsafeUseAsCString, unsafeUseAsCStringLen)
-import Data.ByteString.Internal (create, memcpy)
-
-data Ctx = Ctx !ByteString
-
-digestSize :: Int
-sizeCtx :: Int
-
-digestSize = 16
-sizeCtx = 96
-
-instance Storable Ctx where
-	sizeOf _    = sizeCtx
-	alignment _ = 16
-	poke ptr (Ctx b) = unsafeUseAsCString b (\cs -> memcpy (castPtr ptr) (castPtr cs) (fromIntegral sizeCtx))
-
-	peek ptr = create sizeCtx (\bptr -> memcpy bptr (castPtr ptr) (fromIntegral sizeCtx)) >>= return . Ctx
-
-foreign import ccall unsafe "md5.h md5_init"
-	c_md5_init :: Ptr Ctx -> IO ()
-
-foreign import ccall "md5.h md5_update"
-	c_md5_update :: Ptr Ctx -> CString -> Word32 -> IO ()
-
-foreign import ccall unsafe "md5.h md5_finalize"
-	c_md5_finalize :: Ptr Ctx -> CString -> IO ()
-
-allocInternal :: (Ptr Ctx -> IO a) -> IO a
-allocInternal = alloca
-
-allocInternalFrom :: Ctx -> (Ptr Ctx -> IO a) -> IO a
-allocInternalFrom ctx f = allocInternal $ \ptr -> (poke ptr ctx >> f ptr)
-
-updateInternalIO :: Ptr Ctx -> ByteString -> IO ()
-updateInternalIO ptr d =
-	unsafeUseAsCStringLen d (\(cs, len) -> c_md5_update ptr cs (fromIntegral len))
-
-finalizeInternalIO :: Ptr Ctx -> IO ByteString
-finalizeInternalIO ptr =
-	allocaBytes digestSize (\cs -> c_md5_finalize ptr cs >> B.packCStringLen (cs, digestSize))
+import qualified Data.ByteString.Lazy as L (ByteString)
 
-{-# NOINLINE init #-}
--- | init a context
+{-# DEPRECATED init "use crypto.hash.MD5" #-}
 init :: Ctx
-init = unsafePerformIO $ allocInternal $ \ptr -> do (c_md5_init ptr >> peek ptr)
+init = R.init
 
-{-# NOINLINE update #-}
--- | update a context with a bytestring
+{-# DEPRECATED update "use crypto.hash.MD5" #-}
 update :: Ctx -> ByteString -> Ctx
-update ctx d = unsafePerformIO $ allocInternalFrom ctx $ \ptr -> do updateInternalIO ptr d >> peek ptr
+update = R.update
 
-{-# NOINLINE finalize #-}
--- | finalize the context into a digest bytestring
+{-# DEPRECATED finalize "use crypto.hash.MD5" #-}
 finalize :: Ctx -> ByteString
-finalize ctx = unsafePerformIO $ allocInternalFrom ctx $ \ptr -> do finalizeInternalIO ptr
+finalize = R.finalize
 
-{-# NOINLINE hash #-}
--- | hash a strict bytestring into a digest bytestring
+{-# DEPRECATED hash "use crypto.hash.MD5" #-}
 hash :: ByteString -> ByteString
-hash d = unsafePerformIO $ allocInternal $ \ptr -> do
-	c_md5_init ptr >> updateInternalIO ptr d >> finalizeInternalIO ptr
+hash = R.hash
 
-{-# NOINLINE hashlazy #-}
--- | hash a lazy bytestring into a digest bytestring
+{-# DEPRECATED hashlazy "use crypto.hash.MD5" #-}
 hashlazy :: L.ByteString -> ByteString
-hashlazy l = unsafePerformIO $ allocInternal $ \ptr -> do
-	c_md5_init ptr >> mapM_ (updateInternalIO ptr) (L.toChunks l) >> finalizeInternalIO ptr
+hashlazy = R.hashlazy
diff --git a/Data/CryptoHash/RIPEMD160.hs b/Data/CryptoHash/RIPEMD160.hs
--- a/Data/CryptoHash/RIPEMD160.hs
+++ b/Data/CryptoHash/RIPEMD160.hs
@@ -1,5 +1,3 @@
-{-# LANGUAGE ForeignFunctionInterface #-}
-
 -- |
 -- Module      : Data.CryptoHash.RIPEMD160
 -- License     : BSD-style
@@ -7,7 +5,7 @@
 -- Stability   : experimental
 -- Portability : unknown
 --
--- A module containing RIPEMD160 bindings
+-- compatibility module for RIPEMD160. use Crypto.Hash.RIPEMD160 instead.
 --
 module Data.CryptoHash.RIPEMD160 (
 	Ctx(..),
@@ -22,76 +20,28 @@
 	hashlazy   -- :: ByteString -> ByteString
 	) where
 
-import Prelude hiding (init)
-import Foreign
-import Foreign.C.String
-import qualified Data.ByteString as B
-import qualified Data.ByteString.Lazy as L
+import Prelude ()
+import Crypto.Hash.RIPEMD160 (Ctx(..))
+import qualified Crypto.Hash.RIPEMD160 as R
 import Data.ByteString (ByteString)
-import Data.ByteString.Unsafe (unsafeUseAsCString, unsafeUseAsCStringLen)
-import Data.ByteString.Internal (create, memcpy)
-
-data Ctx = Ctx !ByteString
-
-digestSize :: Int
-sizeCtx :: Int
-
-digestSize = 20
-sizeCtx = 128
-
-instance Storable Ctx where
-	sizeOf _    = sizeCtx
-	alignment _ = 16
-	poke ptr (Ctx b) = unsafeUseAsCString b (\cs -> memcpy (castPtr ptr) (castPtr cs) (fromIntegral sizeCtx))
-
-	peek ptr = create sizeCtx (\bptr -> memcpy bptr (castPtr ptr) (fromIntegral sizeCtx)) >>= return . Ctx
-
-foreign import ccall unsafe "ripemd.h ripemd160_init"
-	c_ripemd160_init :: Ptr Ctx -> IO ()
-
-foreign import ccall "ripemd.h ripemd160_update"
-	c_ripemd160_update :: Ptr Ctx -> CString -> Word32 -> IO ()
-
-foreign import ccall unsafe "ripemd.h ripemd160_finalize"
-	c_ripemd160_finalize :: Ptr Ctx -> CString -> IO ()
-
-allocInternal :: (Ptr Ctx -> IO a) -> IO a
-allocInternal = alloca
-
-allocInternalFrom :: Ctx -> (Ptr Ctx -> IO a) -> IO a
-allocInternalFrom ctx f = allocInternal $ \ptr -> (poke ptr ctx >> f ptr)
-
-updateInternalIO :: Ptr Ctx -> ByteString -> IO ()
-updateInternalIO ptr d =
-	unsafeUseAsCStringLen d (\(cs, len) -> c_ripemd160_update ptr cs (fromIntegral len))
-
-finalizeInternalIO :: Ptr Ctx -> IO ByteString
-finalizeInternalIO ptr =
-	allocaBytes digestSize (\cs -> c_ripemd160_finalize ptr cs >> B.packCStringLen (cs, digestSize))
+import qualified Data.ByteString.Lazy as L (ByteString)
 
-{-# NOINLINE init #-}
--- | init a context
+{-# DEPRECATED init "use crypto.hash.RIPEMD160" #-}
 init :: Ctx
-init = unsafePerformIO $ allocInternal $ \ptr -> do (c_ripemd160_init ptr >> peek ptr)
+init = R.init
 
-{-# NOINLINE update #-}
--- | update a context with a bytestring
+{-# DEPRECATED update "use crypto.hash.RIPEMD160" #-}
 update :: Ctx -> ByteString -> Ctx
-update ctx d = unsafePerformIO $ allocInternalFrom ctx $ \ptr -> do updateInternalIO ptr d >> peek ptr
+update = R.update
 
-{-# NOINLINE finalize #-}
--- | finalize the context into a digest bytestring
+{-# DEPRECATED finalize "use crypto.hash.RIPEMD160" #-}
 finalize :: Ctx -> ByteString
-finalize ctx = unsafePerformIO $ allocInternalFrom ctx $ \ptr -> do finalizeInternalIO ptr
+finalize = R.finalize
 
-{-# NOINLINE hash #-}
--- | hash a strict bytestring into a digest bytestring
+{-# DEPRECATED hash "use crypto.hash.RIPEMD160" #-}
 hash :: ByteString -> ByteString
-hash d = unsafePerformIO $ allocInternal $ \ptr -> do
-	c_ripemd160_init ptr >> updateInternalIO ptr d >> finalizeInternalIO ptr
+hash = R.hash
 
-{-# NOINLINE hashlazy #-}
--- | hash a lazy bytestring into a digest bytestring
+{-# DEPRECATED hashlazy "use crypto.hash.RIPEMD160" #-}
 hashlazy :: L.ByteString -> ByteString
-hashlazy l = unsafePerformIO $ allocInternal $ \ptr -> do
-	c_ripemd160_init ptr >> mapM_ (updateInternalIO ptr) (L.toChunks l) >> finalizeInternalIO ptr
+hashlazy = R.hashlazy
diff --git a/Data/CryptoHash/SHA1.hs b/Data/CryptoHash/SHA1.hs
--- a/Data/CryptoHash/SHA1.hs
+++ b/Data/CryptoHash/SHA1.hs
@@ -1,5 +1,3 @@
-{-# LANGUAGE ForeignFunctionInterface #-}
-
 -- |
 -- Module      : Data.CryptoHash.SHA1
 -- License     : BSD-style
@@ -7,7 +5,7 @@
 -- Stability   : experimental
 -- Portability : unknown
 --
--- A module containing SHA1 bindings
+-- compatibility module for SHA1. use Crypto.Hash.SHA1 instead.
 --
 module Data.CryptoHash.SHA1 (
 	Ctx(..),
@@ -22,76 +20,28 @@
 	hashlazy   -- :: ByteString -> ByteString
 	) where
 
-import Prelude hiding (init)
-import Foreign
-import Foreign.C.String
-import qualified Data.ByteString as B
-import qualified Data.ByteString.Lazy as L
+import Prelude ()
+import Crypto.Hash.SHA1 (Ctx(..))
+import qualified Crypto.Hash.SHA1 as R
 import Data.ByteString (ByteString)
-import Data.ByteString.Unsafe (unsafeUseAsCString, unsafeUseAsCStringLen)
-import Data.ByteString.Internal (create, memcpy)
-
-data Ctx = Ctx !ByteString
-
-digestSize :: Int
-sizeCtx :: Int
-
-digestSize = 20
-sizeCtx = 96
-
-instance Storable Ctx where
-	sizeOf _    = sizeCtx
-	alignment _ = 16
-	poke ptr (Ctx b) = unsafeUseAsCString b (\cs -> memcpy (castPtr ptr) (castPtr cs) (fromIntegral sizeCtx))
-
-	peek ptr = create sizeCtx (\bptr -> memcpy bptr (castPtr ptr) (fromIntegral sizeCtx)) >>= return . Ctx
-
-foreign import ccall unsafe "sha1.h sha1_init"
-	c_sha1_init :: Ptr Ctx -> IO ()
-
-foreign import ccall "sha1.h sha1_update"
-	c_sha1_update :: Ptr Ctx -> CString -> Word32 -> IO ()
-
-foreign import ccall unsafe "sha1.h sha1_finalize"
-	c_sha1_finalize :: Ptr Ctx -> CString -> IO ()
-
-allocInternal :: (Ptr Ctx -> IO a) -> IO a
-allocInternal = alloca
-
-allocInternalFrom :: Ctx -> (Ptr Ctx -> IO a) -> IO a
-allocInternalFrom ctx f = allocInternal $ \ptr -> (poke ptr ctx >> f ptr)
-
-updateInternalIO :: Ptr Ctx -> ByteString -> IO ()
-updateInternalIO ptr d =
-	unsafeUseAsCStringLen d (\(cs, len) -> c_sha1_update ptr cs (fromIntegral len))
-
-finalizeInternalIO :: Ptr Ctx -> IO ByteString
-finalizeInternalIO ptr =
-	allocaBytes digestSize (\cs -> c_sha1_finalize ptr cs >> B.packCStringLen (cs, digestSize))
+import qualified Data.ByteString.Lazy as L (ByteString)
 
-{-# NOINLINE init #-}
--- | init a context
+{-# DEPRECATED init "use crypto.hash.SHA1" #-}
 init :: Ctx
-init = unsafePerformIO $ allocInternal $ \ptr -> do (c_sha1_init ptr >> peek ptr)
+init = R.init
 
-{-# NOINLINE update #-}
--- | update a context with a bytestring
+{-# DEPRECATED update "use crypto.hash.SHA1" #-}
 update :: Ctx -> ByteString -> Ctx
-update ctx d = unsafePerformIO $ allocInternalFrom ctx $ \ptr -> do updateInternalIO ptr d >> peek ptr
+update = R.update
 
-{-# NOINLINE finalize #-}
--- | finalize the context into a digest bytestring
+{-# DEPRECATED finalize "use crypto.hash.SHA1" #-}
 finalize :: Ctx -> ByteString
-finalize ctx = unsafePerformIO $ allocInternalFrom ctx $ \ptr -> do finalizeInternalIO ptr
+finalize = R.finalize
 
-{-# NOINLINE hash #-}
--- | hash a strict bytestring into a digest bytestring
+{-# DEPRECATED hash "use crypto.hash.SHA1" #-}
 hash :: ByteString -> ByteString
-hash d = unsafePerformIO $ allocInternal $ \ptr -> do
-	c_sha1_init ptr >> updateInternalIO ptr d >> finalizeInternalIO ptr
+hash = R.hash
 
-{-# NOINLINE hashlazy #-}
--- | hash a lazy bytestring into a digest bytestring
+{-# DEPRECATED hashlazy "use crypto.hash.SHA1" #-}
 hashlazy :: L.ByteString -> ByteString
-hashlazy l = unsafePerformIO $ allocInternal $ \ptr -> do
-	c_sha1_init ptr >> mapM_ (updateInternalIO ptr) (L.toChunks l) >> finalizeInternalIO ptr
+hashlazy = R.hashlazy
diff --git a/Data/CryptoHash/SHA224.hs b/Data/CryptoHash/SHA224.hs
--- a/Data/CryptoHash/SHA224.hs
+++ b/Data/CryptoHash/SHA224.hs
@@ -1,5 +1,3 @@
-{-# LANGUAGE ForeignFunctionInterface #-}
-
 -- |
 -- Module      : Data.CryptoHash.SHA224
 -- License     : BSD-style
@@ -7,7 +5,7 @@
 -- Stability   : experimental
 -- Portability : unknown
 --
--- A module containing SHA224 bindings
+-- compatibility module for SHA224. use Crypto.Hash.SHA224 instead.
 --
 module Data.CryptoHash.SHA224 (
 	Ctx(..),
@@ -22,76 +20,28 @@
 	hashlazy   -- :: ByteString -> ByteString
 	) where
 
-import Prelude hiding (init)
-import Foreign
-import Foreign.C.String
-import qualified Data.ByteString as B
-import qualified Data.ByteString.Lazy as L
+import Prelude ()
+import Crypto.Hash.SHA224 (Ctx(..))
+import qualified Crypto.Hash.SHA224 as R
 import Data.ByteString (ByteString)
-import Data.ByteString.Unsafe (unsafeUseAsCString, unsafeUseAsCStringLen)
-import Data.ByteString.Internal (create, memcpy)
-
-data Ctx = Ctx !ByteString
-
-digestSize :: Int
-sizeCtx :: Int
-
-digestSize = 28
-sizeCtx = 192
-
-instance Storable Ctx where
-	sizeOf _    = sizeCtx
-	alignment _ = 16
-	poke ptr (Ctx b) = unsafeUseAsCString b (\cs -> memcpy (castPtr ptr) (castPtr cs) (fromIntegral sizeCtx))
-
-	peek ptr = create sizeCtx (\bptr -> memcpy bptr (castPtr ptr) (fromIntegral sizeCtx)) >>= return . Ctx
-
-foreign import ccall unsafe "sha256.h sha224_init"
-	c_sha224_init :: Ptr Ctx -> IO ()
-
-foreign import ccall "sha256.h sha224_update"
-	c_sha224_update :: Ptr Ctx -> CString -> Word32 -> IO ()
-
-foreign import ccall unsafe "sha256.h sha224_finalize"
-	c_sha224_finalize :: Ptr Ctx -> CString -> IO ()
-
-allocInternal :: (Ptr Ctx -> IO a) -> IO a
-allocInternal = alloca
-
-allocInternalFrom :: Ctx -> (Ptr Ctx -> IO a) -> IO a
-allocInternalFrom ctx f = allocInternal $ \ptr -> (poke ptr ctx >> f ptr)
-
-updateInternalIO :: Ptr Ctx -> ByteString -> IO ()
-updateInternalIO ptr d =
-	unsafeUseAsCStringLen d (\(cs, len) -> c_sha224_update ptr cs (fromIntegral len))
-
-finalizeInternalIO :: Ptr Ctx -> IO ByteString
-finalizeInternalIO ptr =
-	allocaBytes digestSize (\cs -> c_sha224_finalize ptr cs >> B.packCStringLen (cs, digestSize))
+import qualified Data.ByteString.Lazy as L (ByteString)
 
-{-# NOINLINE init #-}
--- | init a context
+{-# DEPRECATED init "use crypto.hash.SHA224" #-}
 init :: Ctx
-init = unsafePerformIO $ allocInternal $ \ptr -> do (c_sha224_init ptr >> peek ptr)
+init = R.init
 
-{-# NOINLINE update #-}
--- | update a context with a bytestring
+{-# DEPRECATED update "use crypto.hash.SHA224" #-}
 update :: Ctx -> ByteString -> Ctx
-update ctx d = unsafePerformIO $ allocInternalFrom ctx $ \ptr -> do updateInternalIO ptr d >> peek ptr
+update = R.update
 
-{-# NOINLINE finalize #-}
--- | finalize the context into a digest bytestring
+{-# DEPRECATED finalize "use crypto.hash.SHA224" #-}
 finalize :: Ctx -> ByteString
-finalize ctx = unsafePerformIO $ allocInternalFrom ctx $ \ptr -> do finalizeInternalIO ptr
+finalize = R.finalize
 
-{-# NOINLINE hash #-}
--- | hash a strict bytestring into a digest bytestring
+{-# DEPRECATED hash "use crypto.hash.SHA224" #-}
 hash :: ByteString -> ByteString
-hash d = unsafePerformIO $ allocInternal $ \ptr -> do
-	c_sha224_init ptr >> updateInternalIO ptr d >> finalizeInternalIO ptr
+hash = R.hash
 
-{-# NOINLINE hashlazy #-}
--- | hash a lazy bytestring into a digest bytestring
+{-# DEPRECATED hashlazy "use crypto.hash.SHA224" #-}
 hashlazy :: L.ByteString -> ByteString
-hashlazy l = unsafePerformIO $ allocInternal $ \ptr -> do
-	c_sha224_init ptr >> mapM_ (updateInternalIO ptr) (L.toChunks l) >> finalizeInternalIO ptr
+hashlazy = R.hashlazy
diff --git a/Data/CryptoHash/SHA256.hs b/Data/CryptoHash/SHA256.hs
--- a/Data/CryptoHash/SHA256.hs
+++ b/Data/CryptoHash/SHA256.hs
@@ -1,5 +1,3 @@
-{-# LANGUAGE ForeignFunctionInterface #-}
-
 -- |
 -- Module      : Data.CryptoHash.SHA256
 -- License     : BSD-style
@@ -7,7 +5,7 @@
 -- Stability   : experimental
 -- Portability : unknown
 --
--- A module containing SHA256 bindings
+-- compatibility module for SHA256. use Crypto.Hash.SHA256 instead.
 --
 module Data.CryptoHash.SHA256 (
 	Ctx(..),
@@ -22,76 +20,28 @@
 	hashlazy   -- :: ByteString -> ByteString
 	) where
 
-import Prelude hiding (init)
-import Foreign
-import Foreign.C.String
-import qualified Data.ByteString as B
-import qualified Data.ByteString.Lazy as L
+import Prelude ()
+import Crypto.Hash.SHA256 (Ctx(..))
+import qualified Crypto.Hash.SHA256 as R
 import Data.ByteString (ByteString)
-import Data.ByteString.Unsafe (unsafeUseAsCString, unsafeUseAsCStringLen)
-import Data.ByteString.Internal (create, memcpy)
-
-data Ctx = Ctx !ByteString
-
-digestSize :: Int
-sizeCtx :: Int
-
-digestSize = 32
-sizeCtx = 192
-
-instance Storable Ctx where
-	sizeOf _    = sizeCtx
-	alignment _ = 16
-	poke ptr (Ctx b) = unsafeUseAsCString b (\cs -> memcpy (castPtr ptr) (castPtr cs) (fromIntegral sizeCtx))
-
-	peek ptr = create sizeCtx (\bptr -> memcpy bptr (castPtr ptr) (fromIntegral sizeCtx)) >>= return . Ctx
-
-foreign import ccall unsafe "sha256.h sha256_init"
-	c_sha256_init :: Ptr Ctx -> IO ()
-
-foreign import ccall "sha256.h sha256_update"
-	c_sha256_update :: Ptr Ctx -> CString -> Word32 -> IO ()
-
-foreign import ccall unsafe "sha256.h sha256_finalize"
-	c_sha256_finalize :: Ptr Ctx -> CString -> IO ()
-
-allocInternal :: (Ptr Ctx -> IO a) -> IO a
-allocInternal = alloca
-
-allocInternalFrom :: Ctx -> (Ptr Ctx -> IO a) -> IO a
-allocInternalFrom ctx f = allocInternal $ \ptr -> (poke ptr ctx >> f ptr)
-
-updateInternalIO :: Ptr Ctx -> ByteString -> IO ()
-updateInternalIO ptr d =
-	unsafeUseAsCStringLen d (\(cs, len) -> c_sha256_update ptr cs (fromIntegral len))
-
-finalizeInternalIO :: Ptr Ctx -> IO ByteString
-finalizeInternalIO ptr =
-	allocaBytes digestSize (\cs -> c_sha256_finalize ptr cs >> B.packCStringLen (cs, digestSize))
+import qualified Data.ByteString.Lazy as L (ByteString)
 
-{-# NOINLINE init #-}
--- | init a context
+{-# DEPRECATED init "use crypto.hash.SHA256" #-}
 init :: Ctx
-init = unsafePerformIO $ allocInternal $ \ptr -> do (c_sha256_init ptr >> peek ptr)
+init = R.init
 
-{-# NOINLINE update #-}
--- | update a context with a bytestring
+{-# DEPRECATED update "use crypto.hash.SHA256" #-}
 update :: Ctx -> ByteString -> Ctx
-update ctx d = unsafePerformIO $ allocInternalFrom ctx $ \ptr -> do updateInternalIO ptr d >> peek ptr
+update = R.update
 
-{-# NOINLINE finalize #-}
--- | finalize the context into a digest bytestring
+{-# DEPRECATED finalize "use crypto.hash.SHA256" #-}
 finalize :: Ctx -> ByteString
-finalize ctx = unsafePerformIO $ allocInternalFrom ctx $ \ptr -> do finalizeInternalIO ptr
+finalize = R.finalize
 
-{-# NOINLINE hash #-}
--- | hash a strict bytestring into a digest bytestring
+{-# DEPRECATED hash "use crypto.hash.SHA256" #-}
 hash :: ByteString -> ByteString
-hash d = unsafePerformIO $ allocInternal $ \ptr -> do
-	c_sha256_init ptr >> updateInternalIO ptr d >> finalizeInternalIO ptr
+hash = R.hash
 
-{-# NOINLINE hashlazy #-}
--- | hash a lazy bytestring into a digest bytestring
+{-# DEPRECATED hashlazy "use crypto.hash.SHA256" #-}
 hashlazy :: L.ByteString -> ByteString
-hashlazy l = unsafePerformIO $ allocInternal $ \ptr -> do
-	c_sha256_init ptr >> mapM_ (updateInternalIO ptr) (L.toChunks l) >> finalizeInternalIO ptr
+hashlazy = R.hashlazy
diff --git a/Data/CryptoHash/SHA384.hs b/Data/CryptoHash/SHA384.hs
--- a/Data/CryptoHash/SHA384.hs
+++ b/Data/CryptoHash/SHA384.hs
@@ -1,5 +1,3 @@
-{-# LANGUAGE ForeignFunctionInterface #-}
-
 -- |
 -- Module      : Data.CryptoHash.SHA384
 -- License     : BSD-style
@@ -7,7 +5,7 @@
 -- Stability   : experimental
 -- Portability : unknown
 --
--- A module containing SHA384 bindings
+-- compatibility module for SHA384. use Crypto.Hash.SHA384 instead.
 --
 module Data.CryptoHash.SHA384 (
 	Ctx(..),
@@ -22,76 +20,28 @@
 	hashlazy   -- :: ByteString -> ByteString
 	) where
 
-import Prelude hiding (init)
-import Foreign
-import Foreign.C.String
-import qualified Data.ByteString as B
-import qualified Data.ByteString.Lazy as L
+import Prelude ()
+import Crypto.Hash.SHA384 (Ctx(..))
+import qualified Crypto.Hash.SHA384 as R
 import Data.ByteString (ByteString)
-import Data.ByteString.Unsafe (unsafeUseAsCString, unsafeUseAsCStringLen)
-import Data.ByteString.Internal (create, memcpy)
-
-data Ctx = Ctx !ByteString
-
-digestSize :: Int
-sizeCtx :: Int
-
-digestSize = 48
-sizeCtx = 256
-
-instance Storable Ctx where
-	sizeOf _    = sizeCtx
-	alignment _ = 16
-	poke ptr (Ctx b) = unsafeUseAsCString b (\cs -> memcpy (castPtr ptr) (castPtr cs) (fromIntegral sizeCtx))
-
-	peek ptr = create sizeCtx (\bptr -> memcpy bptr (castPtr ptr) (fromIntegral sizeCtx)) >>= return . Ctx
-
-foreign import ccall unsafe "sha512.h sha384_init"
-	c_sha384_init :: Ptr Ctx -> IO ()
-
-foreign import ccall "sha512.h sha384_update"
-	c_sha384_update :: Ptr Ctx -> CString -> Word32 -> IO ()
-
-foreign import ccall unsafe "sha512.h sha384_finalize"
-	c_sha384_finalize :: Ptr Ctx -> CString -> IO ()
-
-allocInternal :: (Ptr Ctx -> IO a) -> IO a
-allocInternal = alloca
-
-allocInternalFrom :: Ctx -> (Ptr Ctx -> IO a) -> IO a
-allocInternalFrom ctx f = allocInternal $ \ptr -> (poke ptr ctx >> f ptr)
-
-updateInternalIO :: Ptr Ctx -> ByteString -> IO ()
-updateInternalIO ptr d =
-	unsafeUseAsCStringLen d (\(cs, len) -> c_sha384_update ptr cs (fromIntegral len))
-
-finalizeInternalIO :: Ptr Ctx -> IO ByteString
-finalizeInternalIO ptr =
-	allocaBytes digestSize (\cs -> c_sha384_finalize ptr cs >> B.packCStringLen (cs, digestSize))
+import qualified Data.ByteString.Lazy as L (ByteString)
 
-{-# NOINLINE init #-}
--- | init a context
+{-# DEPRECATED init "use crypto.hash.SHA384" #-}
 init :: Ctx
-init = unsafePerformIO $ allocInternal $ \ptr -> do (c_sha384_init ptr >> peek ptr)
+init = R.init
 
-{-# NOINLINE update #-}
--- | update a context with a bytestring
+{-# DEPRECATED update "use crypto.hash.SHA384" #-}
 update :: Ctx -> ByteString -> Ctx
-update ctx d = unsafePerformIO $ allocInternalFrom ctx $ \ptr -> do updateInternalIO ptr d >> peek ptr
+update = R.update
 
-{-# NOINLINE finalize #-}
--- | finalize the context into a digest bytestring
+{-# DEPRECATED finalize "use crypto.hash.SHA384" #-}
 finalize :: Ctx -> ByteString
-finalize ctx = unsafePerformIO $ allocInternalFrom ctx $ \ptr -> do finalizeInternalIO ptr
+finalize = R.finalize
 
-{-# NOINLINE hash #-}
--- | hash a strict bytestring into a digest bytestring
+{-# DEPRECATED hash "use crypto.hash.SHA384" #-}
 hash :: ByteString -> ByteString
-hash d = unsafePerformIO $ allocInternal $ \ptr -> do
-	c_sha384_init ptr >> updateInternalIO ptr d >> finalizeInternalIO ptr
+hash = R.hash
 
-{-# NOINLINE hashlazy #-}
--- | hash a lazy bytestring into a digest bytestring
+{-# DEPRECATED hashlazy "use crypto.hash.SHA384" #-}
 hashlazy :: L.ByteString -> ByteString
-hashlazy l = unsafePerformIO $ allocInternal $ \ptr -> do
-	c_sha384_init ptr >> mapM_ (updateInternalIO ptr) (L.toChunks l) >> finalizeInternalIO ptr
+hashlazy = R.hashlazy
diff --git a/Data/CryptoHash/SHA512.hs b/Data/CryptoHash/SHA512.hs
--- a/Data/CryptoHash/SHA512.hs
+++ b/Data/CryptoHash/SHA512.hs
@@ -1,5 +1,3 @@
-{-# LANGUAGE ForeignFunctionInterface #-}
-
 -- |
 -- Module      : Data.CryptoHash.SHA512
 -- License     : BSD-style
@@ -7,7 +5,7 @@
 -- Stability   : experimental
 -- Portability : unknown
 --
--- A module containing SHA512 bindings
+-- compatibility module for SHA512. use Crypto.Hash.SHA512 instead.
 --
 module Data.CryptoHash.SHA512 (
 	Ctx(..),
@@ -22,76 +20,28 @@
 	hashlazy   -- :: ByteString -> ByteString
 	) where
 
-import Prelude hiding (init)
-import Foreign
-import Foreign.C.String
-import qualified Data.ByteString as B
-import qualified Data.ByteString.Lazy as L
+import Prelude ()
+import Crypto.Hash.SHA512 (Ctx(..))
+import qualified Crypto.Hash.SHA512 as R
 import Data.ByteString (ByteString)
-import Data.ByteString.Unsafe (unsafeUseAsCString, unsafeUseAsCStringLen)
-import Data.ByteString.Internal (create, memcpy)
-
-data Ctx = Ctx !ByteString
-
-digestSize :: Int
-sizeCtx :: Int
-
-digestSize = 64
-sizeCtx = 256
-
-instance Storable Ctx where
-	sizeOf _    = sizeCtx
-	alignment _ = 16
-	poke ptr (Ctx b) = unsafeUseAsCString b (\cs -> memcpy (castPtr ptr) (castPtr cs) (fromIntegral sizeCtx))
-
-	peek ptr = create sizeCtx (\bptr -> memcpy bptr (castPtr ptr) (fromIntegral sizeCtx)) >>= return . Ctx
-
-foreign import ccall unsafe "sha512.h sha512_init"
-	c_sha512_init :: Ptr Ctx -> IO ()
-
-foreign import ccall "sha512.h sha512_update"
-	c_sha512_update :: Ptr Ctx -> CString -> Word32 -> IO ()
-
-foreign import ccall unsafe "sha512.h sha512_finalize"
-	c_sha512_finalize :: Ptr Ctx -> CString -> IO ()
-
-allocInternal :: (Ptr Ctx -> IO a) -> IO a
-allocInternal = alloca
-
-allocInternalFrom :: Ctx -> (Ptr Ctx -> IO a) -> IO a
-allocInternalFrom ctx f = allocInternal $ \ptr -> (poke ptr ctx >> f ptr)
-
-updateInternalIO :: Ptr Ctx -> ByteString -> IO ()
-updateInternalIO ptr d =
-	unsafeUseAsCStringLen d (\(cs, len) -> c_sha512_update ptr cs (fromIntegral len))
-
-finalizeInternalIO :: Ptr Ctx -> IO ByteString
-finalizeInternalIO ptr =
-	allocaBytes digestSize (\cs -> c_sha512_finalize ptr cs >> B.packCStringLen (cs, digestSize))
+import qualified Data.ByteString.Lazy as L (ByteString)
 
-{-# NOINLINE init #-}
--- | init a context
+{-# DEPRECATED init "use crypto.hash.SHA512" #-}
 init :: Ctx
-init = unsafePerformIO $ allocInternal $ \ptr -> do (c_sha512_init ptr >> peek ptr)
+init = R.init
 
-{-# NOINLINE update #-}
--- | update a context with a bytestring
+{-# DEPRECATED update "use crypto.hash.SHA512" #-}
 update :: Ctx -> ByteString -> Ctx
-update ctx d = unsafePerformIO $ allocInternalFrom ctx $ \ptr -> do updateInternalIO ptr d >> peek ptr
+update = R.update
 
-{-# NOINLINE finalize #-}
--- | finalize the context into a digest bytestring
+{-# DEPRECATED finalize "use crypto.hash.SHA512" #-}
 finalize :: Ctx -> ByteString
-finalize ctx = unsafePerformIO $ allocInternalFrom ctx $ \ptr -> do finalizeInternalIO ptr
+finalize = R.finalize
 
-{-# NOINLINE hash #-}
--- | hash a strict bytestring into a digest bytestring
+{-# DEPRECATED hash "use crypto.hash.SHA512" #-}
 hash :: ByteString -> ByteString
-hash d = unsafePerformIO $ allocInternal $ \ptr -> do
-	c_sha512_init ptr >> updateInternalIO ptr d >> finalizeInternalIO ptr
+hash = R.hash
 
-{-# NOINLINE hashlazy #-}
--- | hash a lazy bytestring into a digest bytestring
+{-# DEPRECATED hashlazy "use crypto.hash.SHA512" #-}
 hashlazy :: L.ByteString -> ByteString
-hashlazy l = unsafePerformIO $ allocInternal $ \ptr -> do
-	c_sha512_init ptr >> mapM_ (updateInternalIO ptr) (L.toChunks l) >> finalizeInternalIO ptr
+hashlazy = R.hashlazy
diff --git a/Data/CryptoHash/Skein256.hs b/Data/CryptoHash/Skein256.hs
--- a/Data/CryptoHash/Skein256.hs
+++ b/Data/CryptoHash/Skein256.hs
@@ -1,5 +1,3 @@
-{-# LANGUAGE ForeignFunctionInterface #-}
-
 -- |
 -- Module      : Data.CryptoHash.Skein256
 -- License     : BSD-style
@@ -7,7 +5,7 @@
 -- Stability   : experimental
 -- Portability : unknown
 --
--- A module containing Skein256 bindings
+-- compatibility module for Skein256. use Crypto.Hash.Skein256 instead.
 --
 module Data.CryptoHash.Skein256 (
 	Ctx(..),
@@ -22,81 +20,28 @@
 	hashlazy   -- :: Int -> ByteString -> ByteString
 	) where
 
-import Prelude hiding (init)
-import Foreign
-import Foreign.C.String
-import Foreign.C.Types
-import qualified Data.ByteString as B
-import qualified Data.ByteString.Lazy as L
+import Prelude (Int)
+import Crypto.Hash.Skein256 (Ctx(..))
+import qualified Crypto.Hash.Skein256 as R
 import Data.ByteString (ByteString)
-import Data.ByteString.Unsafe (unsafeUseAsCString, unsafeUseAsCStringLen)
-import Data.ByteString.Internal (create, memcpy)
-
-data Ctx = Ctx !ByteString
-
-sizeCtx :: Int
-sizeCtx = 100
-
-instance Storable Ctx where
-	sizeOf _    = sizeCtx
-	alignment _ = 16
-	poke ptr (Ctx b) = unsafeUseAsCString b (\cs -> memcpy (castPtr ptr) (castPtr cs) (fromIntegral sizeCtx))
-
-	peek ptr = create sizeCtx (\bptr -> memcpy bptr (castPtr ptr) (fromIntegral sizeCtx)) >>= return . Ctx
-
-poke_hashlen :: Ptr Ctx -> IO Int
-poke_hashlen ptr = do
-	let iptr = castPtr ptr :: Ptr CUInt
-	a <- peek iptr
-	return $ fromIntegral a
-
-foreign import ccall unsafe "skein256.h skein256_init"
-	c_skein256_init :: Ptr Ctx -> CUInt -> IO ()
-
-foreign import ccall "skein256.h skein256_update"
-	c_skein256_update :: Ptr Ctx -> CString -> Word32 -> IO ()
-
-foreign import ccall unsafe "skein256.h skein256_finalize"
-	c_skein256_finalize :: Ptr Ctx -> CString -> IO ()
-
-allocInternal :: (Ptr Ctx -> IO a) -> IO a
-allocInternal = alloca
-
-allocInternalFrom :: Ctx -> (Ptr Ctx -> IO a) -> IO a
-allocInternalFrom ctx f = allocInternal $ \ptr -> (poke ptr ctx >> f ptr)
-
-updateInternalIO :: Ptr Ctx -> ByteString -> IO ()
-updateInternalIO ptr d =
-	unsafeUseAsCStringLen d (\(cs, len) -> c_skein256_update ptr cs (fromIntegral len))
-
-finalizeInternalIO :: Ptr Ctx -> IO ByteString
-finalizeInternalIO ptr = do
-	digestSize <- fmap (\x -> (x + 7) `shiftR` 3) $ poke_hashlen ptr
-	allocaBytes digestSize (\cs -> c_skein256_finalize ptr cs >> B.packCStringLen (cs, digestSize))
+import qualified Data.ByteString.Lazy as L (ByteString)
 
-{-# NOINLINE init #-}
--- | init a context
+{-# DEPRECATED init "use crypto.hash.Skein256" #-}
 init :: Int -> Ctx
-init hashlen = unsafePerformIO $ allocInternal $ \ptr -> do (c_skein256_init ptr (fromIntegral hashlen) >> peek ptr)
+init = R.init
 
-{-# NOINLINE update #-}
--- | update a context with a bytestring
+{-# DEPRECATED update "use crypto.hash.Skein256" #-}
 update :: Ctx -> ByteString -> Ctx
-update ctx d = unsafePerformIO $ allocInternalFrom ctx $ \ptr -> do updateInternalIO ptr d >> peek ptr
+update = R.update
 
-{-# NOINLINE finalize #-}
--- | finalize the context into a digest bytestring
+{-# DEPRECATED finalize "use crypto.hash.Skein256" #-}
 finalize :: Ctx -> ByteString
-finalize ctx = unsafePerformIO $ allocInternalFrom ctx $ \ptr -> do finalizeInternalIO ptr
+finalize = R.finalize
 
-{-# NOINLINE hash #-}
--- | hash a strict bytestring into a digest bytestring
+{-# DEPRECATED hash "use crypto.hash.Skein256" #-}
 hash :: Int -> ByteString -> ByteString
-hash hashlen d = unsafePerformIO $ allocInternal $ \ptr -> do
-	c_skein256_init ptr (fromIntegral hashlen) >> updateInternalIO ptr d >> finalizeInternalIO ptr
+hash = R.hash
 
-{-# NOINLINE hashlazy #-}
--- | hash a lazy bytestring into a digest bytestring
+{-# DEPRECATED hashlazy "use crypto.hash.Skein256" #-}
 hashlazy :: Int -> L.ByteString -> ByteString
-hashlazy hashlen l = unsafePerformIO $ allocInternal $ \ptr -> do
-	c_skein256_init ptr (fromIntegral hashlen) >> mapM_ (updateInternalIO ptr) (L.toChunks l) >> finalizeInternalIO ptr
+hashlazy = R.hashlazy
diff --git a/Data/CryptoHash/Skein512.hs b/Data/CryptoHash/Skein512.hs
--- a/Data/CryptoHash/Skein512.hs
+++ b/Data/CryptoHash/Skein512.hs
@@ -1,5 +1,3 @@
-{-# LANGUAGE ForeignFunctionInterface #-}
-
 -- |
 -- Module      : Data.CryptoHash.Skein512
 -- License     : BSD-style
@@ -7,7 +5,7 @@
 -- Stability   : experimental
 -- Portability : unknown
 --
--- A module containing Skein512 bindings
+-- compatibility module for Skein512. use Crypto.Hash.Skein512 instead.
 --
 module Data.CryptoHash.Skein512 (
 	Ctx(..),
@@ -22,81 +20,28 @@
 	hashlazy   -- :: Int -> ByteString -> ByteString
 	) where
 
-import Prelude hiding (init)
-import Foreign
-import Foreign.C.String
-import Foreign.C.Types
-import qualified Data.ByteString as B
-import qualified Data.ByteString.Lazy as L
+import Prelude (Int)
+import Crypto.Hash.Skein512 (Ctx(..))
+import qualified Crypto.Hash.Skein512 as R
 import Data.ByteString (ByteString)
-import Data.ByteString.Unsafe (unsafeUseAsCString, unsafeUseAsCStringLen)
-import Data.ByteString.Internal (create, memcpy)
-
-data Ctx = Ctx !ByteString
-
-sizeCtx :: Int
-sizeCtx = 160
-
-instance Storable Ctx where
-	sizeOf _    = sizeCtx
-	alignment _ = 16
-	poke ptr (Ctx b) = unsafeUseAsCString b (\cs -> memcpy (castPtr ptr) (castPtr cs) (fromIntegral sizeCtx))
-
-	peek ptr = create sizeCtx (\bptr -> memcpy bptr (castPtr ptr) (fromIntegral sizeCtx)) >>= return . Ctx
-
-poke_hashlen :: Ptr Ctx -> IO Int
-poke_hashlen ptr = do
-	let iptr = castPtr ptr :: Ptr CUInt
-	a <- peek iptr
-	return $ fromIntegral a
-
-foreign import ccall unsafe "skein512.h skein512_init"
-	c_skein512_init :: Ptr Ctx -> CUInt -> IO ()
-
-foreign import ccall "skein512.h skein512_update"
-	c_skein512_update :: Ptr Ctx -> CString -> Word32 -> IO ()
-
-foreign import ccall unsafe "skein512.h skein512_finalize"
-	c_skein512_finalize :: Ptr Ctx -> CString -> IO ()
-
-allocInternal :: (Ptr Ctx -> IO a) -> IO a
-allocInternal = alloca
-
-allocInternalFrom :: Ctx -> (Ptr Ctx -> IO a) -> IO a
-allocInternalFrom ctx f = allocInternal $ \ptr -> (poke ptr ctx >> f ptr)
-
-updateInternalIO :: Ptr Ctx -> ByteString -> IO ()
-updateInternalIO ptr d =
-	unsafeUseAsCStringLen d (\(cs, len) -> c_skein512_update ptr cs (fromIntegral len))
-
-finalizeInternalIO :: Ptr Ctx -> IO ByteString
-finalizeInternalIO ptr = do
-	digestSize <- fmap (\x -> (x + 7) `shiftR` 3) $ poke_hashlen ptr
-	allocaBytes digestSize (\cs -> c_skein512_finalize ptr cs >> B.packCStringLen (cs, digestSize))
+import qualified Data.ByteString.Lazy as L (ByteString)
 
-{-# NOINLINE init #-}
--- | init a context
+{-# DEPRECATED init "use crypto.hash.Skein512" #-}
 init :: Int -> Ctx
-init hashlen = unsafePerformIO $ allocInternal $ \ptr -> do (c_skein512_init ptr (fromIntegral hashlen) >> peek ptr)
+init = R.init
 
-{-# NOINLINE update #-}
--- | update a context with a bytestring
+{-# DEPRECATED update "use crypto.hash.Skein512" #-}
 update :: Ctx -> ByteString -> Ctx
-update ctx d = unsafePerformIO $ allocInternalFrom ctx $ \ptr -> do updateInternalIO ptr d >> peek ptr
+update = R.update
 
-{-# NOINLINE finalize #-}
--- | finalize the context into a digest bytestring
+{-# DEPRECATED finalize "use crypto.hash.Skein512" #-}
 finalize :: Ctx -> ByteString
-finalize ctx = unsafePerformIO $ allocInternalFrom ctx $ \ptr -> do finalizeInternalIO ptr
+finalize = R.finalize
 
-{-# NOINLINE hash #-}
--- | hash a strict bytestring into a digest bytestring
+{-# DEPRECATED hash "use crypto.hash.Skein512" #-}
 hash :: Int -> ByteString -> ByteString
-hash hashlen d = unsafePerformIO $ allocInternal $ \ptr -> do
-	c_skein512_init ptr (fromIntegral hashlen) >> updateInternalIO ptr d >> finalizeInternalIO ptr
+hash = R.hash
 
-{-# NOINLINE hashlazy #-}
--- | hash a lazy bytestring into a digest bytestring
+{-# DEPRECATED hashlazy "use crypto.hash.Skein512" #-}
 hashlazy :: Int -> L.ByteString -> ByteString
-hashlazy hashlen l = unsafePerformIO $ allocInternal $ \ptr -> do
-	c_skein512_init ptr (fromIntegral hashlen) >> mapM_ (updateInternalIO ptr) (L.toChunks l) >> finalizeInternalIO ptr
+hashlazy = R.hashlazy
diff --git a/Data/CryptoHash/Tiger.hs b/Data/CryptoHash/Tiger.hs
--- a/Data/CryptoHash/Tiger.hs
+++ b/Data/CryptoHash/Tiger.hs
@@ -1,5 +1,3 @@
-{-# LANGUAGE ForeignFunctionInterface #-}
-
 -- |
 -- Module      : Data.CryptoHash.Tiger
 -- License     : BSD-style
@@ -7,7 +5,7 @@
 -- Stability   : experimental
 -- Portability : unknown
 --
--- A module containing Tiger bindings
+-- compatibility module for Tiger. use Crypto.Hash.Tiger instead.
 --
 module Data.CryptoHash.Tiger (
 	Ctx(..),
@@ -22,76 +20,28 @@
 	hashlazy   -- :: ByteString -> ByteString
 	) where
 
-import Prelude hiding (init)
-import Foreign
-import Foreign.C.String
-import qualified Data.ByteString as B
-import qualified Data.ByteString.Lazy as L
+import Prelude ()
+import Crypto.Hash.Tiger (Ctx(..))
+import qualified Crypto.Hash.Tiger as R
 import Data.ByteString (ByteString)
-import Data.ByteString.Unsafe (unsafeUseAsCString, unsafeUseAsCStringLen)
-import Data.ByteString.Internal (create, memcpy)
-
-data Ctx = Ctx !ByteString
-
-digestSize :: Int
-sizeCtx :: Int
-
-digestSize = 24
-sizeCtx = 96
-
-instance Storable Ctx where
-	sizeOf _    = sizeCtx
-	alignment _ = 16
-	poke ptr (Ctx b) = unsafeUseAsCString b (\cs -> memcpy (castPtr ptr) (castPtr cs) (fromIntegral sizeCtx))
-
-	peek ptr = create sizeCtx (\bptr -> memcpy bptr (castPtr ptr) (fromIntegral sizeCtx)) >>= return . Ctx
-
-foreign import ccall unsafe "tiger.h tiger_init"
-	c_tiger_init :: Ptr Ctx -> IO ()
-
-foreign import ccall "tiger.h tiger_update"
-	c_tiger_update :: Ptr Ctx -> CString -> Word32 -> IO ()
-
-foreign import ccall unsafe "tiger.h tiger_finalize"
-	c_tiger_finalize :: Ptr Ctx -> CString -> IO ()
-
-allocInternal :: (Ptr Ctx -> IO a) -> IO a
-allocInternal = alloca
-
-allocInternalFrom :: Ctx -> (Ptr Ctx -> IO a) -> IO a
-allocInternalFrom ctx f = allocInternal $ \ptr -> (poke ptr ctx >> f ptr)
-
-updateInternalIO :: Ptr Ctx -> ByteString -> IO ()
-updateInternalIO ptr d =
-	unsafeUseAsCStringLen d (\(cs, len) -> c_tiger_update ptr cs (fromIntegral len))
-
-finalizeInternalIO :: Ptr Ctx -> IO ByteString
-finalizeInternalIO ptr =
-	allocaBytes digestSize (\cs -> c_tiger_finalize ptr cs >> B.packCStringLen (cs, digestSize))
+import qualified Data.ByteString.Lazy as L (ByteString)
 
-{-# NOINLINE init #-}
--- | init a context
+{-# DEPRECATED init "use crypto.hash.Tiger" #-}
 init :: Ctx
-init = unsafePerformIO $ allocInternal $ \ptr -> do (c_tiger_init ptr >> peek ptr)
+init = R.init
 
-{-# NOINLINE update #-}
--- | update a context with a bytestring
+{-# DEPRECATED update "use crypto.hash.Tiger" #-}
 update :: Ctx -> ByteString -> Ctx
-update ctx d = unsafePerformIO $ allocInternalFrom ctx $ \ptr -> do updateInternalIO ptr d >> peek ptr
+update = R.update
 
-{-# NOINLINE finalize #-}
--- | finalize the context into a digest bytestring
+{-# DEPRECATED finalize "use crypto.hash.Tiger" #-}
 finalize :: Ctx -> ByteString
-finalize ctx = unsafePerformIO $ allocInternalFrom ctx $ \ptr -> do finalizeInternalIO ptr
+finalize = R.finalize
 
-{-# NOINLINE hash #-}
--- | hash a strict bytestring into a digest bytestring
+{-# DEPRECATED hash "use crypto.hash.Tiger" #-}
 hash :: ByteString -> ByteString
-hash d = unsafePerformIO $ allocInternal $ \ptr -> do
-	c_tiger_init ptr >> updateInternalIO ptr d >> finalizeInternalIO ptr
+hash = R.hash
 
-{-# NOINLINE hashlazy #-}
--- | hash a lazy bytestring into a digest bytestring
+{-# DEPRECATED hashlazy "use crypto.hash.Tiger" #-}
 hashlazy :: L.ByteString -> ByteString
-hashlazy l = unsafePerformIO $ allocInternal $ \ptr -> do
-	c_tiger_init ptr >> mapM_ (updateInternalIO ptr) (L.toChunks l) >> finalizeInternalIO ptr
+hashlazy = R.hashlazy
diff --git a/Tests.hs b/Tests.hs
--- a/Tests.hs
+++ b/Tests.hs
@@ -3,18 +3,18 @@
 import Data.Bits
 import Data.Word
 import qualified Data.ByteString as B
-import qualified Data.CryptoHash.MD2 as MD2
-import qualified Data.CryptoHash.MD4 as MD4
-import qualified Data.CryptoHash.MD5 as MD5
-import qualified Data.CryptoHash.SHA1 as SHA1
-import qualified Data.CryptoHash.SHA224 as SHA224
-import qualified Data.CryptoHash.SHA256 as SHA256
-import qualified Data.CryptoHash.SHA384 as SHA384
-import qualified Data.CryptoHash.SHA512 as SHA512
-import qualified Data.CryptoHash.RIPEMD160 as RIPEMD160
-import qualified Data.CryptoHash.Tiger as Tiger
-import qualified Data.CryptoHash.Skein256 as Skein256
-import qualified Data.CryptoHash.Skein512 as Skein512
+import qualified Crypto.Hash.MD2 as MD2
+import qualified Crypto.Hash.MD4 as MD4
+import qualified Crypto.Hash.MD5 as MD5
+import qualified Crypto.Hash.SHA1 as SHA1
+import qualified Crypto.Hash.SHA224 as SHA224
+import qualified Crypto.Hash.SHA256 as SHA256
+import qualified Crypto.Hash.SHA384 as SHA384
+import qualified Crypto.Hash.SHA512 as SHA512
+import qualified Crypto.Hash.RIPEMD160 as RIPEMD160
+import qualified Crypto.Hash.Tiger as Tiger
+import qualified Crypto.Hash.Skein256 as Skein256
+import qualified Crypto.Hash.Skein512 as Skein512
 
 v0 = ""
 v1 = "The quick brown fox jumps over the lazy dog"
diff --git a/cryptohash.cabal b/cryptohash.cabal
--- a/cryptohash.cabal
+++ b/cryptohash.cabal
@@ -1,5 +1,5 @@
 Name:                cryptohash
-Version:             0.5.3
+Version:             0.6
 Description:
     A collection of crypto hashes, with a practical incremental and one-pass, pure APIs,
     with performance close to the fastest implementations available in others languages.
@@ -27,10 +27,26 @@
   Description:       Build unit test
   Default:           False
 
+Flag cryptoapi
+  Description:       Defines crypto-api instances
+  Default:           False
+
 Library
   Build-Depends:     base >= 3 && < 5, bytestring
   Extensions:        ForeignFunctionInterface
-  Exposed-modules:   Data.CryptoHash.SHA1
+  Exposed-modules:   Crypto.Hash.SHA1
+                     Crypto.Hash.SHA224
+                     Crypto.Hash.SHA256
+                     Crypto.Hash.SHA384
+                     Crypto.Hash.SHA512
+                     Crypto.Hash.MD2
+                     Crypto.Hash.MD4
+                     Crypto.Hash.MD5
+                     Crypto.Hash.RIPEMD160
+                     Crypto.Hash.Skein256
+                     Crypto.Hash.Skein512
+                     Crypto.Hash.Tiger
+                     Data.CryptoHash.SHA1
                      Data.CryptoHash.SHA224
                      Data.CryptoHash.SHA256
                      Data.CryptoHash.SHA384
@@ -57,7 +73,7 @@
 
 Executable           Tests
   Main-Is:           Tests.hs
-  Extensions:        ForeignFunctionInterface
+  Extensions:        ForeignFunctionInterface, CPP
   C-sources:         cbits/sha1.c
                      cbits/sha256.c
                      cbits/sha512.c
@@ -70,9 +86,12 @@
                      cbits/tiger.c
   if flag(test)
     Buildable:       True
-    Build-depends:   base >= 3 && < 5, HUnit, bytestring
+    Build-depends:   base >= 4, HUnit, bytestring
   else
     Buildable:       False
+  if flag(cryptoapi)
+    Build-depends:   crypto-api >= 0.1, tagged >= 0.1, cereal >= 0.2
+    cpp-options:     -DHAVE_CRYPTOAPI
 
 source-repository head
   type:     git
