diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,4 +1,8 @@
-# Revision history for sha1
+# Revision history for md5
+
+## 0.1.0.3 -- 2024-02-01
+
+* Update package metadata.
 
 ## 0.1.0.2 -- 2020-03-09
 
diff --git a/Setup.hs b/Setup.hs
deleted file mode 100644
--- a/Setup.hs
+++ /dev/null
@@ -1,2 +0,0 @@
-import Distribution.Simple
-main = defaultMain
diff --git a/md5.cabal b/md5.cabal
--- a/md5.cabal
+++ b/md5.cabal
@@ -1,49 +1,55 @@
-cabal-version: 2.2
-name: md5
-version: 0.1.0.0
-synopsis: MD5 Hash
+cabal-version:      2.2
+name:               md5
+version:            0.1.0.3
+synopsis:           MD5 Hash
 description:
   This library is a copy of cryptohash-md5 that works on GC-managed
   byte arrays instead of ByteString. The C code is a copied from
   that library. If you find an issue with the C code, you should
   open an issue on cryptohash-md5.
-homepage: https://github.com/byteverse/md5
-bug-reports: https://github.com/byteverse/md5/issues
-license: BSD-3-Clause
-license-file: LICENSE
-author: Andrew Martin
-maintainer: andrew.thaddeus@gmail.com
-copyright: 2023 Andrew Martin
-category: Data
-build-type: Simple
-extra-source-files:
-  CHANGELOG.md
-  cbits/md5.h
 
+homepage:           https://github.com/byteverse/md5
+bug-reports:        https://github.com/byteverse/md5/issues
+license:            BSD-3-Clause
+license-file:       LICENSE
+author:             Andrew Martin
+maintainer:         amartin@layer3com.com
+copyright:          2023 Andrew Martin
+category:           Data
+build-type:         Simple
+extra-source-files: cbits/md5.h
+extra-doc-files:    CHANGELOG.md
+
 library
-  include-dirs: cbits
-  cc-options: -Wall -O3
-  hs-source-dirs: src
-  exposed-modules: Hash.Md5
-  other-modules: Hash.Md5.Internal
+  include-dirs:     cbits
+  cc-options:       -Wall
+  hs-source-dirs:   src
+  exposed-modules:  Hash.Md5
+  other-modules:    Hash.Md5.Internal
   build-depends:
-    , base >=4.12 && <5
-    , primitive >=0.7 && <0.8
-    , bytebuild >=0.3.4 && <0.4
-    , byteslice >=0.2.2 && <0.3
+    , base       >=4.12  && <5
+    , bytebuild  >=0.3.4 && <0.4
+    , byteslice  >=0.2.2 && <0.3
+    , primitive  >=0.7   && <0.10
+
   default-language: Haskell2010
-  ghc-options: -O2 -Wall
+  ghc-options:      -O2 -Wall
 
 test-suite test
-  Default-Language: Haskell2010
-  hs-source-dirs: test
-  main-is: Main.hs
-  type: exitcode-stdio-1.0
+  default-language: Haskell2010
+  hs-source-dirs:   test
+  main-is:          Main.hs
+  type:             exitcode-stdio-1.0
   build-depends:
     , base
-    , bytebuild >=0.3.4
-    , byteslice >=0.1.4.0
-    , natural-arithmetic >=0.1.1
-    , primitive
+    , bytebuild           >=0.3.4
+    , byteslice           >=0.1.4.0
     , md5
-  ghc-options: -O2 -Wall
+    , natural-arithmetic  >=0.1.1
+    , primitive
+
+  ghc-options:      -O2 -Wall
+
+source-repository head
+  type:     git
+  location: git://github.com/byteverse/md5.git
diff --git a/src/Hash/Md5.hs b/src/Hash/Md5.hs
--- a/src/Hash/Md5.hs
+++ b/src/Hash/Md5.hs
@@ -1,15 +1,17 @@
-{-# language BangPatterns #-}
-{-# language DataKinds #-}
-{-# language MagicHash #-}
-{-# language UnliftedFFITypes #-}
+{-# LANGUAGE BangPatterns #-}
+{-# LANGUAGE DataKinds #-}
+{-# LANGUAGE MagicHash #-}
+{-# LANGUAGE UnliftedFFITypes #-}
 
 module Hash.Md5
-  ( Context(..)
+  ( Context (..)
+
     -- * Context Reuse
   , context
   , reinitialize
   , update
   , finalize
+
     -- * One Shot
   , boundedBuilder
   ) where
@@ -17,11 +19,9 @@
 import Control.Monad.ST (ST)
 import Data.Bytes.Builder.Bounded as BB
 import Data.Bytes.Builder.Bounded.Unsafe as BBU
-import Data.Bytes.Types (Bytes(Bytes))
-import Data.Primitive (ByteArray(..),MutableByteArray(..))
-import Data.Primitive (newByteArray)
-import GHC.Exts (Int(I#),Int#,MutableByteArray#,ByteArray#,unsafeCoerce#)
-import GHC.Exts (RealWorld)
+import Data.Bytes.Types (Bytes (Bytes))
+import Data.Primitive (ByteArray (..), MutableByteArray (..), newByteArray)
+import GHC.Exts (unsafeCoerce#)
 import GHC.IO (unsafeIOToST)
 
 import Hash.Md5.Internal
@@ -41,17 +41,19 @@
   unsafeIOToST (c_md5_init (unsafeCoerce# ctx))
 
 finalize ::
-     Context s
-  -> MutableByteArray s -- ^ Destination, implied length is 16
-  -> Int -- ^ Destination offset
-  -> ST s ()
+  Context s ->
+  -- | Destination, implied length is 16
+  MutableByteArray s ->
+  -- | Destination offset
+  Int ->
+  ST s ()
 finalize (Context (MutableByteArray ctx)) (MutableByteArray x) !a =
   unsafeIOToST (c_md5_finalize (unsafeCoerce# ctx) (unsafeCoerce# x) a)
 
 update ::
-     Context s
-  -> Bytes
-  -> ST s ()
+  Context s ->
+  Bytes ->
+  ST s ()
 update (Context (MutableByteArray ctx)) (Bytes (ByteArray arr) off len) =
   unsafeIOToST (c_md5_update_unsafe (unsafeCoerce# ctx) arr off len)
 
@@ -64,8 +66,9 @@
     c_md5_finalize ctx (unsafeCoerce# x) a
 
 boundedBuilder :: Bytes -> BB.Builder 16
-boundedBuilder (Bytes arr off len) = BBU.construct
-  (\buf ix -> do
-    performHash buf ix arr off len
-    pure (ix + 16)
-  )
+boundedBuilder (Bytes arr off len) =
+  BBU.construct
+    ( \buf ix -> do
+        performHash buf ix arr off len
+        pure (ix + 16)
+    )
diff --git a/src/Hash/Md5/Internal.hs b/src/Hash/Md5/Internal.hs
--- a/src/Hash/Md5/Internal.hs
+++ b/src/Hash/Md5/Internal.hs
@@ -2,20 +2,17 @@
 {-# LANGUAGE MagicHash #-}
 {-# LANGUAGE UnliftedFFITypes #-}
 
--- |
--- Module      : Hash.MD5.Internal
--- License     : BSD-3
---
+{- |
+Module      : Hash.MD5.Internal
+License     : BSD-3
+-}
 module Hash.Md5.Internal
   ( c_md5_init
   , c_md5_update_unsafe
   , c_md5_finalize
   ) where
 
-import GHC.Exts (ByteArray#, MutableByteArray#,RealWorld,Int#)
-import Data.Word
-import Foreign.C.Types
-import Foreign.Ptr
+import GHC.Exts (ByteArray#, MutableByteArray#, RealWorld)
 
 -- MD5 Context
 --
@@ -30,21 +27,21 @@
 --
 -- Consequently, a MD5 digest as produced by 'finalize' is 16 bytes long.
 foreign import capi unsafe "md5.h hs_byteverse_md5_init"
-    c_md5_init ::
-         MutableByteArray# RealWorld -- ctx, updated
-      -> IO ()
+  c_md5_init ::
+    MutableByteArray# RealWorld -> -- ctx, updated
+    IO ()
 
 foreign import capi unsafe "md5.h hs_byteverse_md5_update"
-    c_md5_update_unsafe ::
-         MutableByteArray# RealWorld -- ctx, updated
-      -> ByteArray# -- bytes that are hashed
-      -> Int -- offset into bytes, often zero
-      -> Int -- length of bytes
-      -> IO ()
+  c_md5_update_unsafe ::
+    MutableByteArray# RealWorld -> -- ctx, updated
+    ByteArray# -> -- bytes that are hashed
+    Int -> -- offset into bytes, often zero
+    Int -> -- length of bytes
+    IO ()
 
 foreign import capi unsafe "md5.h hs_byteverse_md5_finalize"
-    c_md5_finalize ::
-         MutableByteArray# RealWorld -- ctx
-      -> MutableByteArray# RealWorld -- output buffer, must be 16 bytes
-      -> Int -- output buffer offset
-      -> IO ()
+  c_md5_finalize ::
+    MutableByteArray# RealWorld -> -- ctx
+    MutableByteArray# RealWorld -> -- output buffer, must be 16 bytes
+    Int -> -- output buffer offset
+    IO ()
diff --git a/test/Main.hs b/test/Main.hs
--- a/test/Main.hs
+++ b/test/Main.hs
@@ -1,12 +1,12 @@
-{-# language BangPatterns #-}
+{-# LANGUAGE BangPatterns #-}
 
 import Data.Primitive (ByteArray)
 import Data.Word (Word8)
 import Numeric (showHex)
 
 import qualified Arithmetic.Nat as Nat
-import qualified Data.Bytes.Builder.Bounded as BB
 import qualified Data.Bytes as Bytes
+import qualified Data.Bytes.Builder.Bounded as BB
 import qualified Data.Bytes.Text.Ascii as Ascii
 import qualified Data.Primitive as PM
 import qualified GHC.Exts as Exts
@@ -24,26 +24,45 @@
     else fail "Did not match"
 
 printHash :: ByteArray -> IO ()
-printHash !b = putStr (go 0) where
-  go !ix = if ix < 16
-    then let val = PM.indexByteArray b ix :: Word8 in
-      if val < 16
-        then '0' : showHex val (go (ix + 1))
-        else showHex val (go (ix + 1))
-    else "\n"
+printHash !b = putStr (go 0)
+ where
+  go !ix =
+    if ix < 16
+      then
+        let val = PM.indexByteArray b ix :: Word8
+         in if val < 16
+              then '0' : showHex val (go (ix + 1))
+              else showHex val (go (ix + 1))
+      else "\n"
 
 actual :: ByteArray
-actual = BB.run Nat.constant
-  (Md5.boundedBuilder
-    (Bytes.unsafeDrop 5
-      (Ascii.fromString "12345theoceanscovertheearth")
+actual =
+  BB.run
+    Nat.constant
+    ( Md5.boundedBuilder
+        ( Bytes.unsafeDrop
+            5
+            (Ascii.fromString "12345theoceanscovertheearth")
+        )
     )
-  )
 
 expected :: ByteArray
-expected = Exts.fromList
-  [ 0xf6, 0xc6, 0x90, 0x8c
-  , 0x1d, 0xb5, 0x81, 0x4c
-  , 0xa6, 0xfc, 0x9e, 0x59
-  , 0x65, 0x8a, 0xf9, 0xd4
-  ]
+expected =
+  Exts.fromList
+    [ 0xf6
+    , 0xc6
+    , 0x90
+    , 0x8c
+    , 0x1d
+    , 0xb5
+    , 0x81
+    , 0x4c
+    , 0xa6
+    , 0xfc
+    , 0x9e
+    , 0x59
+    , 0x65
+    , 0x8a
+    , 0xf9
+    , 0xd4
+    ]
