diff --git a/Data/Digest/Pure/MD5.hs b/Data/Digest/Pure/MD5.hs
--- a/Data/Digest/Pure/MD5.hs
+++ b/Data/Digest/Pure/MD5.hs
@@ -67,7 +67,7 @@
 
 -- |After finalizing a context, using md5Finalize, a new type
 -- is returned to prevent 're-finalizing' the structure.
-newtype MD5Digest = MD5Digest MD5Context
+data MD5Digest = MD5Digest MD5Partial deriving (Eq, Ord)
 
 -- | The initial context to use when calling md5Update for the first time
 md5InitialContext :: MD5Context
@@ -90,7 +90,7 @@
                         putWord8 0x80
                         mapM_ putWord8 (replicate lenZeroPad 0)
                         putWord64le totLen' )
-        in MD5Digest $ md5Update ctx (L.fromChunks padBS)
+        in MD5Digest $ mdPartial $ md5Update ctx (L.fromChunks padBS)
     where
     l = B.length rem
     lenZeroPad = if (l + 1) <= blockSizeBytes - 8
@@ -118,16 +118,20 @@
 -- context across calls to applyMD5Rounds.
 performMD5Update :: MD5Context -> ByteString -> MD5Context
 performMD5Update !ctx@(MD5Ctx !par@(MD5Par !a !b !c !d) _ !len) !bs = {-# SCC "performMD5Update" #-}
-        let MD5Par a' b' c' d' = applyMD5Rounds par bs
+        let MD5Par a' b' c' d' = if isAligned bs
+                                    then applyMD5Rounds par bs getAlignedNthWord
+                                    else applyMD5Rounds par bs getUnalignedNthWord
         in MD5Ctx {
                         mdPartial = MD5Par (a' + a) (b' + b) (c' + c) (d' + d),
                         mdLeftOver = B.empty,
                         mdTotalLen = len + blockSizeBits
                         }
+  where
+  isAligned (PS _ off _) = off `rem` 4 == 0
 {-# INLINE performMD5Update #-}
 
-applyMD5Rounds :: MD5Partial -> ByteString -> MD5Partial
-applyMD5Rounds par@(MD5Par a b c d) w = {-# SCC "applyMD5Rounds" #-}
+applyMD5Rounds :: MD5Partial -> ByteString -> (Int -> ByteString -> Word32) -> MD5Partial
+applyMD5Rounds par@(MD5Par a b c d) w getNthWord = {-# SCC "applyMD5Rounds" #-}
         let -- Round 1
             !r0  = ff  a  b  c  d   (w!!0)  7  3614090360
             !r1  = ff  d r0  b  c   (w!!1)  12 3905402710
@@ -228,32 +232,44 @@
         {-# INLINE ii #-}
         (!!) word32s pos = getNthWord pos word32s
         {-# INLINE (!!) #-}
-        getNthWord n bs@(PS ptr off len) =
-                inlinePerformIO $ withForeignPtr ptr $ \ptr' -> do
-                let p = castPtr $ plusPtr ptr' off
-                peekElemOff p n
-        {-# INLINE getNthWord #-}
 {-# INLINE applyMD5Rounds #-}
 
+-- getAlignedNthWord :: Word32 -> ByteString -> Word32
+getAlignedNthWord n bs@(PS ptr off len) =
+        inlinePerformIO $ withForeignPtr ptr $ \ptr' -> do
+        let p = castPtr $ plusPtr ptr' off
+        peekElemOff p n
+{-# INLINE getAlignedNthWord #-}
+
+-- getUnalignedNthWord :: Word32 -> ByteString -> Word32
+getUnalignedNthWord n bs@(PS ptr off len) =
+        inlinePerformIO $ withForeignPtr ptr $ \ptr' -> do
+        let p = castPtr $ plusPtr ptr' (off + n*4) :: Ptr Word8
+        w1 <- peekElemOff p 0
+        w2 <- peekElemOff p 1
+        w3 <- peekElemOff p 2
+        w4 <- peekElemOff p 3
+        let y = (w4 .<. 24 .|. w3 .<. 16 .|. w2 .<.8 .|. fromIntegral w1)
+        return y
+{-# INLINE getUnalignedNthWord #-}
+
+infix 9 .<.
+(.<.) :: Word8 -> Int -> Word32
+(.<.) w i = (fromIntegral w) `shiftL` i
+
 ----- Some quick and dirty instances follow -----
 
 instance Show MD5Digest where
     show (MD5Digest h) = show h
 
 instance Binary MD5Digest where
-    put (MD5Digest (MD5Ctx p _ _)) = put p
+    put (MD5Digest p) = put p
     get = do
         p <- get
-        return $ MD5Digest $ MD5Ctx p B.empty 0
-
-instance Ord MD5Digest where
-    compare (MD5Digest (MD5Ctx a _ _)) (MD5Digest (MD5Ctx b _ _)) = compare a b
-
-instance Eq MD5Digest where
-    (MD5Digest (MD5Ctx a _ _)) == (MD5Digest (MD5Ctx b _ _)) = a == b
+        return $ MD5Digest p
 
-instance Show MD5Context where
-  show (MD5Ctx (MD5Par a b c d) _ _) = 
+instance Show MD5Partial where
+  show (MD5Par a b c d) = 
     let bs = runPut $ putWord32be d >> putWord32be c >> putWord32be b >> putWord32be a
     in foldl' (\str w -> let c = showHex w str
                          in if length c < length str + 2
diff --git a/Test/MD5.hs b/Test/MD5.hs
--- a/Test/MD5.hs
+++ b/Test/MD5.hs
@@ -20,7 +20,7 @@
 
 instance Arbitrary L.ByteString where
     arbitrary = do
-        len <- choose (0,1000) :: Gen Int
+        len <- choose (0,10) :: Gen Int
         chunks <- vector len
         return $ L.fromChunks chunks
 
diff --git a/pureMD5.cabal b/pureMD5.cabal
--- a/pureMD5.cabal
+++ b/pureMD5.cabal
@@ -1,5 +1,5 @@
 name:		pureMD5
-version:	1.0.0.1
+version:	1.0.0.2
 license:	BSD3
 license-file:	LICENSE
 author:		Thomas DuBuisson <thomas.dubuisson@gmail.com>
@@ -18,9 +18,9 @@
 
 Library
   if flag(small_base)
-    Build-Depends: base >= 3 && < 5, bytestring >= 0.9 && < 0.10, binary >= 0.4.0 && < 0.6.0
+    Build-Depends: base >= 3 && < 5, bytestring >= 0.9 && < 0.10, binary >= 0.4.0 && < 0.5.0
   else
-    Build-Depends: base >= 3, bytestring, binary >= 0.4.0 && < 0.6.0
+    Build-Depends: base >= 3, bytestring, binary >= 0.4.0
   hs-source-dirs:
   exposed-modules: Data.Digest.Pure.MD5
   ghc-options:	-O2 -funfolding-use-threshold66 -funfolding-creation-threshold66 -fexcess-precision -funbox-strict-fields
