diff --git a/LICENSE b/LICENSE
new file mode 100644
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,30 @@
+Copyright Michael Xavier (c) 2015
+
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+
+    * Redistributions in binary form must reproduce the above
+      copyright notice, this list of conditions and the following
+      disclaimer in the documentation and/or other materials provided
+      with the distribution.
+
+    * Neither the name of Michael Xavier nor the names of other
+      contributors may be used to endorse or promote products derived
+      from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/Setup.hs b/Setup.hs
new file mode 100644
--- /dev/null
+++ b/Setup.hs
@@ -0,0 +1,2 @@
+import Distribution.Simple
+main = defaultMain
diff --git a/bench/Main.hs b/bench/Main.hs
new file mode 100644
--- /dev/null
+++ b/bench/Main.hs
@@ -0,0 +1,45 @@
+{-# LANGUAGE OverloadedStrings   #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+module Main
+    ( main
+    ) where
+
+
+-------------------------------------------------------------------------------
+import           Criterion
+import           Criterion.Main
+import           Data.ByteString   (ByteString)
+import           Data.Proxy
+-------------------------------------------------------------------------------
+import           Data.Digest.CRC
+import           Data.Digest.CRC16
+import           Data.Digest.CRC32
+import           Data.Digest.CRC64
+import           Data.Digest.CRC8
+-------------------------------------------------------------------------------
+
+
+main :: IO ()
+main = defaultMain
+  [ digestBenchmarks
+  ]
+
+
+-------------------------------------------------------------------------------
+digestBenchmarks :: Benchmark
+digestBenchmarks = bgroup "digest"
+  [ bench "CRC8" (digestBench (Proxy :: Proxy CRC8) )
+  , bench "CRC16" (digestBench (Proxy :: Proxy CRC16))
+  , bench "CRC32" (digestBench (Proxy :: Proxy CRC32))
+  , bench "CRC64" (digestBench (Proxy :: Proxy CRC64))
+  ]
+
+
+-------------------------------------------------------------------------------
+example :: ByteString
+example = "1234567890"
+
+
+-------------------------------------------------------------------------------
+digestBench :: forall a. (CRC a) => Proxy a -> Benchmarkable
+digestBench _ = whnf (digest :: ByteString -> a) example
diff --git a/crc.cabal b/crc.cabal
new file mode 100644
--- /dev/null
+++ b/crc.cabal
@@ -0,0 +1,78 @@
+name:                crc
+version:             0.0.1
+synopsis:            Implements various Cyclic Redundancy Checks (CRC)
+description:         Please see README.md
+homepage:            http://github.com/MichaelXavier/crc#readme
+license:             MIT
+license-file:        LICENSE
+author:              Michael Xavier
+maintainer:          michael@michaelxavier.net
+copyright:           2015 Michael Xavier
+category:            Web
+build-type:          Simple
+-- extra-source-files:
+cabal-version:       >=1.10
+
+flag lib-Werror
+  default: False
+  manual: True
+
+library
+  hs-source-dirs:      src
+  exposed-modules:     Data.Digest.CRC
+                     , Data.Digest.CRC8
+                     , Data.Digest.CRC16
+                     , Data.Digest.CRC32
+                     , Data.Digest.CRC64
+  build-depends:       base >= 4.7 && < 5
+                     , bytestring
+                     , vector
+  default-language:    Haskell2010
+
+  if flag(lib-Werror)
+    ghc-options: -Werror
+
+  ghc-options: -Wall
+
+
+test-suite test
+  type:                exitcode-stdio-1.0
+  hs-source-dirs:      test
+  main-is:             Main.hs
+  build-depends:       base
+                     , crc
+                     , tasty
+                     , tasty-golden
+                     , conduit
+                     , conduit-extra
+                     , bytestring
+                     , resourcet
+  ghc-options:         -threaded -rtsopts -with-rtsopts=-N
+  default-language:    Haskell2010
+
+  if flag(lib-Werror)
+    ghc-options: -Werror
+
+  ghc-options: -Wall
+
+
+benchmark bench
+  type: exitcode-stdio-1.0
+  main-is: Main.hs
+  hs-source-dirs: bench
+  default-language:    Haskell2010
+  build-depends:
+      base
+    , crc
+    , criterion
+    , bytestring
+
+  if flag(lib-Werror)
+    ghc-options: -Werror
+
+  ghc-options: -Wall
+
+
+source-repository head
+  type:     git
+  location: https://github.com/MichaelXavier/crc
diff --git a/src/Data/Digest/CRC.hs b/src/Data/Digest/CRC.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/Digest/CRC.hs
@@ -0,0 +1,25 @@
+{-# LANGUAGE TypeFamilies #-}
+module Data.Digest.CRC
+    ( CRC(..)
+    , digest
+    ) where
+
+
+-------------------------------------------------------------------------------
+import           Data.ByteString     as BS
+import           Data.Vector.Unboxed as V
+-------------------------------------------------------------------------------
+-------------------------------------------------------------------------------
+
+
+
+class CRC a where
+  type CRCWord a
+  initCRC :: a
+  crcWord :: a -> CRCWord a
+  updateDigest :: a -> ByteString -> a
+  crcTable :: V.Vector (CRCWord a)
+
+
+digest :: CRC a => ByteString -> a
+digest = updateDigest initCRC
diff --git a/src/Data/Digest/CRC16.hs b/src/Data/Digest/CRC16.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/Digest/CRC16.hs
@@ -0,0 +1,105 @@
+{-# LANGUAGE TypeFamilies #-}
+module Data.Digest.CRC16
+    ( CRC16(..)
+    ) where
+
+
+-------------------------------------------------------------------------------
+import           Data.Bits
+import           Data.ByteString     as BS
+import           Data.Vector.Unboxed as V
+import           Data.Word
+-------------------------------------------------------------------------------
+import           Data.Digest.CRC
+-------------------------------------------------------------------------------
+
+
+newtype CRC16 = CRC16 { crc16 :: Word16 } deriving (Show, Eq, Ord)
+
+
+instance CRC CRC16 where
+  type CRCWord CRC16 = Word16
+  initCRC = CRC16 0
+  crcWord = crc16
+  updateDigest = updateDigest16
+  crcTable = table
+
+
+-------------------------------------------------------------------------------
+updateDigest16 :: CRC16 -> ByteString -> CRC16
+updateDigest16 crc = BS.foldl go crc
+  where
+    go (CRC16 crc') b8 =
+      let idx = fromIntegral (crc' `xor` b16) .&. 0xff
+          b16 = fromIntegral b8
+      in CRC16 ((table ! idx) `xor` ((crc' `shiftR` 8) .&. 0x00ffff))
+
+
+-------------------------------------------------------------------------------
+table :: V.Vector Word16
+table = V.fromList
+  [ 0x0000, 0xc0c1, 0xc181, 0x0140
+  , 0xc301, 0x03c0, 0x0280, 0xc241
+  , 0xc601, 0x06c0, 0x0780, 0xc741
+  , 0x0500, 0xc5c1, 0xc481, 0x0440
+  , 0xcc01, 0x0cc0, 0x0d80, 0xcd41
+  , 0x0f00, 0xcfc1, 0xce81, 0x0e40
+  , 0x0a00, 0xcac1, 0xcb81, 0x0b40
+  , 0xc901, 0x09c0, 0x0880, 0xc841
+  , 0xd801, 0x18c0, 0x1980, 0xd941
+  , 0x1b00, 0xdbc1, 0xda81, 0x1a40
+  , 0x1e00, 0xdec1, 0xdf81, 0x1f40
+  , 0xdd01, 0x1dc0, 0x1c80, 0xdc41
+  , 0x1400, 0xd4c1, 0xd581, 0x1540
+  , 0xd701, 0x17c0, 0x1680, 0xd641
+  , 0xd201, 0x12c0, 0x1380, 0xd341
+  , 0x1100, 0xd1c1, 0xd081, 0x1040
+  , 0xf001, 0x30c0, 0x3180, 0xf141
+  , 0x3300, 0xf3c1, 0xf281, 0x3240
+  , 0x3600, 0xf6c1, 0xf781, 0x3740
+  , 0xf501, 0x35c0, 0x3480, 0xf441
+  , 0x3c00, 0xfcc1, 0xfd81, 0x3d40
+  , 0xff01, 0x3fc0, 0x3e80, 0xfe41
+  , 0xfa01, 0x3ac0, 0x3b80, 0xfb41
+  , 0x3900, 0xf9c1, 0xf881, 0x3840
+  , 0x2800, 0xe8c1, 0xe981, 0x2940
+  , 0xeb01, 0x2bc0, 0x2a80, 0xea41
+  , 0xee01, 0x2ec0, 0x2f80, 0xef41
+  , 0x2d00, 0xedc1, 0xec81, 0x2c40
+  , 0xe401, 0x24c0, 0x2580, 0xe541
+  , 0x2700, 0xe7c1, 0xe681, 0x2640
+  , 0x2200, 0xe2c1, 0xe381, 0x2340
+  , 0xe101, 0x21c0, 0x2080, 0xe041
+  , 0xa001, 0x60c0, 0x6180, 0xa141
+  , 0x6300, 0xa3c1, 0xa281, 0x6240
+  , 0x6600, 0xa6c1, 0xa781, 0x6740
+  , 0xa501, 0x65c0, 0x6480, 0xa441
+  , 0x6c00, 0xacc1, 0xad81, 0x6d40
+  , 0xaf01, 0x6fc0, 0x6e80, 0xae41
+  , 0xaa01, 0x6ac0, 0x6b80, 0xab41
+  , 0x6900, 0xa9c1, 0xa881, 0x6840
+  , 0x7800, 0xb8c1, 0xb981, 0x7940
+  , 0xbb01, 0x7bc0, 0x7a80, 0xba41
+  , 0xbe01, 0x7ec0, 0x7f80, 0xbf41
+  , 0x7d00, 0xbdc1, 0xbc81, 0x7c40
+  , 0xb401, 0x74c0, 0x7580, 0xb541
+  , 0x7700, 0xb7c1, 0xb681, 0x7640
+  , 0x7200, 0xb2c1, 0xb381, 0x7340
+  , 0xb101, 0x71c0, 0x7080, 0xb041
+  , 0x5000, 0x90c1, 0x9181, 0x5140
+  , 0x9301, 0x53c0, 0x5280, 0x9241
+  , 0x9601, 0x56c0, 0x5780, 0x9741
+  , 0x5500, 0x95c1, 0x9481, 0x5440
+  , 0x9c01, 0x5cc0, 0x5d80, 0x9d41
+  , 0x5f00, 0x9fc1, 0x9e81, 0x5e40
+  , 0x5a00, 0x9ac1, 0x9b81, 0x5b40
+  , 0x9901, 0x59c0, 0x5880, 0x9841
+  , 0x8801, 0x48c0, 0x4980, 0x8941
+  , 0x4b00, 0x8bc1, 0x8a81, 0x4a40
+  , 0x4e00, 0x8ec1, 0x8f81, 0x4f40
+  , 0x8d01, 0x4dc0, 0x4c80, 0x8c41
+  , 0x4400, 0x84c1, 0x8581, 0x4540
+  , 0x8701, 0x47c0, 0x4680, 0x8641
+  , 0x8201, 0x42c0, 0x4380, 0x8341
+  , 0x4100, 0x81c1, 0x8081, 0x4040
+  ]
diff --git a/src/Data/Digest/CRC32.hs b/src/Data/Digest/CRC32.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/Digest/CRC32.hs
@@ -0,0 +1,108 @@
+{-# LANGUAGE TypeFamilies #-}
+module Data.Digest.CRC32
+    ( CRC32(..)
+    , digest
+    , updateDigest
+    ) where
+
+
+-------------------------------------------------------------------------------
+import           Data.Bits
+import           Data.ByteString     as BS
+import           Data.Vector.Unboxed as V
+import           Data.Word
+-------------------------------------------------------------------------------
+import           Data.Digest.CRC
+-------------------------------------------------------------------------------
+
+
+newtype CRC32 = CRC32 { crc32 :: Word32 } deriving (Show, Eq, Ord)
+
+
+instance CRC CRC32 where
+  type CRCWord CRC32 = Word32
+  initCRC = CRC32 0xffffffff
+  crcWord = crc32
+  updateDigest = updateDigest32
+  crcTable = table
+
+
+-------------------------------------------------------------------------------
+updateDigest32 :: CRC32 -> ByteString -> CRC32
+updateDigest32 crc = xorFinal . BS.foldl go crc
+  where
+    xorFinal (CRC32 x) = CRC32 (x `xor` 0xffffffff)
+    go (CRC32 crc') b8 =
+      let idx = fromIntegral (crc' `xor` b32) .&. 0xff
+          b32 = fromIntegral b8
+      in CRC32 (((crc' `shiftR` 8) .&. 0x00ffffff) `xor` (table ! idx))
+
+
+-------------------------------------------------------------------------------
+table :: V.Vector Word32
+table = V.fromList
+  [ 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba
+  , 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3
+  , 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988
+  , 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91
+  , 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de
+  , 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7
+  , 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec
+  , 0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5
+  , 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172
+  , 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b
+  , 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940
+  , 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59
+  , 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116
+  , 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f
+  , 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924
+  , 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d
+  , 0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a
+  , 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433
+  , 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818
+  , 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01
+  , 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e
+  , 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457
+  , 0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c
+  , 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65
+  , 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2
+  , 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb
+  , 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0
+  , 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9
+  , 0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086
+  , 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f
+  , 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4
+  , 0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad
+  , 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a
+  , 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683
+  , 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8
+  , 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1
+  , 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe
+  , 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7
+  , 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc
+  , 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5
+  , 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252
+  , 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b
+  , 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60
+  , 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79
+  , 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236
+  , 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f
+  , 0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04
+  , 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d
+  , 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a
+  , 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713
+  , 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38
+  , 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21
+  , 0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e
+  , 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777
+  , 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c
+  , 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45
+  , 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2
+  , 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db
+  , 0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0
+  , 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9
+  , 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6
+  , 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf
+  , 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94
+  , 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
+  ]
diff --git a/src/Data/Digest/CRC64.hs b/src/Data/Digest/CRC64.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/Digest/CRC64.hs
@@ -0,0 +1,107 @@
+{-# LANGUAGE TypeFamilies #-}
+module Data.Digest.CRC64
+    ( CRC64(..)
+    ) where
+
+
+--TODO: look to uuid for how they structure modules
+--TODO: actually benchmark unboxed vector
+-------------------------------------------------------------------------------
+import           Data.Bits
+import           Data.ByteString     as BS
+import           Data.Vector.Unboxed as V
+import           Data.Word
+-------------------------------------------------------------------------------
+import           Data.Digest.CRC
+-------------------------------------------------------------------------------
+
+
+newtype CRC64 = CRC64 { crc64 :: Word64 } deriving (Show, Eq, Ord)
+
+
+instance CRC CRC64 where
+  type CRCWord CRC64 = Word64
+  initCRC = CRC64 0
+  crcWord = crc64
+  updateDigest = updateDigest64
+  crcTable = table
+
+
+-------------------------------------------------------------------------------
+updateDigest64 :: CRC64 -> ByteString -> CRC64
+updateDigest64 crc = BS.foldl go crc
+  where
+    go (CRC64 crc') b8 =
+      let idx = fromIntegral (crc' `xor` b64) .&. 0xff
+          b64 = fromIntegral b8
+      in CRC64 (((table ! idx) `xor` (crc' `shiftR` 8)) .&. 0xffffffffffffffff)
+
+
+-------------------------------------------------------------------------------
+table :: V.Vector Word64
+table = V.fromList
+  [ 0x0000000000000000 , 0x01b0000000000000 , 0x0360000000000000 , 0x02d0000000000000
+  , 0x06c0000000000000 , 0x0770000000000000 , 0x05a0000000000000 , 0x0410000000000000
+  , 0x0d80000000000000 , 0x0c30000000000000 , 0x0ee0000000000000 , 0x0f50000000000000
+  , 0x0b40000000000000 , 0x0af0000000000000 , 0x0820000000000000 , 0x0990000000000000
+  , 0x1b00000000000000 , 0x1ab0000000000000 , 0x1860000000000000 , 0x19d0000000000000
+  , 0x1dc0000000000000 , 0x1c70000000000000 , 0x1ea0000000000000 , 0x1f10000000000000
+  , 0x1680000000000000 , 0x1730000000000000 , 0x15e0000000000000 , 0x1450000000000000
+  , 0x1040000000000000 , 0x11f0000000000000 , 0x1320000000000000 , 0x1290000000000000
+  , 0x3600000000000000 , 0x37b0000000000000 , 0x3560000000000000 , 0x34d0000000000000
+  , 0x30c0000000000000 , 0x3170000000000000 , 0x33a0000000000000 , 0x3210000000000000
+  , 0x3b80000000000000 , 0x3a30000000000000 , 0x38e0000000000000 , 0x3950000000000000
+  , 0x3d40000000000000 , 0x3cf0000000000000 , 0x3e20000000000000 , 0x3f90000000000000
+  , 0x2d00000000000000 , 0x2cb0000000000000 , 0x2e60000000000000 , 0x2fd0000000000000
+  , 0x2bc0000000000000 , 0x2a70000000000000 , 0x28a0000000000000 , 0x2910000000000000
+  , 0x2080000000000000 , 0x2130000000000000 , 0x23e0000000000000 , 0x2250000000000000
+  , 0x2640000000000000 , 0x27f0000000000000 , 0x2520000000000000 , 0x2490000000000000
+  , 0x6c00000000000000 , 0x6db0000000000000 , 0x6f60000000000000 , 0x6ed0000000000000
+  , 0x6ac0000000000000 , 0x6b70000000000000 , 0x69a0000000000000 , 0x6810000000000000
+  , 0x6180000000000000 , 0x6030000000000000 , 0x62e0000000000000 , 0x6350000000000000
+  , 0x6740000000000000 , 0x66f0000000000000 , 0x6420000000000000 , 0x6590000000000000
+  , 0x7700000000000000 , 0x76b0000000000000 , 0x7460000000000000 , 0x75d0000000000000
+  , 0x71c0000000000000 , 0x7070000000000000 , 0x72a0000000000000 , 0x7310000000000000
+  , 0x7a80000000000000 , 0x7b30000000000000 , 0x79e0000000000000 , 0x7850000000000000
+  , 0x7c40000000000000 , 0x7df0000000000000 , 0x7f20000000000000 , 0x7e90000000000000
+  , 0x5a00000000000000 , 0x5bb0000000000000 , 0x5960000000000000 , 0x58d0000000000000
+  , 0x5cc0000000000000 , 0x5d70000000000000 , 0x5fa0000000000000 , 0x5e10000000000000
+  , 0x5780000000000000 , 0x5630000000000000 , 0x54e0000000000000 , 0x5550000000000000
+  , 0x5140000000000000 , 0x50f0000000000000 , 0x5220000000000000 , 0x5390000000000000
+  , 0x4100000000000000 , 0x40b0000000000000 , 0x4260000000000000 , 0x43d0000000000000
+  , 0x47c0000000000000 , 0x4670000000000000 , 0x44a0000000000000 , 0x4510000000000000
+  , 0x4c80000000000000 , 0x4d30000000000000 , 0x4fe0000000000000 , 0x4e50000000000000
+  , 0x4a40000000000000 , 0x4bf0000000000000 , 0x4920000000000000 , 0x4890000000000000
+  , 0xd800000000000000 , 0xd9b0000000000000 , 0xdb60000000000000 , 0xdad0000000000000
+  , 0xdec0000000000000 , 0xdf70000000000000 , 0xdda0000000000000 , 0xdc10000000000000
+  , 0xd580000000000000 , 0xd430000000000000 , 0xd6e0000000000000 , 0xd750000000000000
+  , 0xd340000000000000 , 0xd2f0000000000000 , 0xd020000000000000 , 0xd190000000000000
+  , 0xc300000000000000 , 0xc2b0000000000000 , 0xc060000000000000 , 0xc1d0000000000000
+  , 0xc5c0000000000000 , 0xc470000000000000 , 0xc6a0000000000000 , 0xc710000000000000
+  , 0xce80000000000000 , 0xcf30000000000000 , 0xcde0000000000000 , 0xcc50000000000000
+  , 0xc840000000000000 , 0xc9f0000000000000 , 0xcb20000000000000 , 0xca90000000000000
+  , 0xee00000000000000 , 0xefb0000000000000 , 0xed60000000000000 , 0xecd0000000000000
+  , 0xe8c0000000000000 , 0xe970000000000000 , 0xeba0000000000000 , 0xea10000000000000
+  , 0xe380000000000000 , 0xe230000000000000 , 0xe0e0000000000000 , 0xe150000000000000
+  , 0xe540000000000000 , 0xe4f0000000000000 , 0xe620000000000000 , 0xe790000000000000
+  , 0xf500000000000000 , 0xf4b0000000000000 , 0xf660000000000000 , 0xf7d0000000000000
+  , 0xf3c0000000000000 , 0xf270000000000000 , 0xf0a0000000000000 , 0xf110000000000000
+  , 0xf880000000000000 , 0xf930000000000000 , 0xfbe0000000000000 , 0xfa50000000000000
+  , 0xfe40000000000000 , 0xfff0000000000000 , 0xfd20000000000000 , 0xfc90000000000000
+  , 0xb400000000000000 , 0xb5b0000000000000 , 0xb760000000000000 , 0xb6d0000000000000
+  , 0xb2c0000000000000 , 0xb370000000000000 , 0xb1a0000000000000 , 0xb010000000000000
+  , 0xb980000000000000 , 0xb830000000000000 , 0xbae0000000000000 , 0xbb50000000000000
+  , 0xbf40000000000000 , 0xbef0000000000000 , 0xbc20000000000000 , 0xbd90000000000000
+  , 0xaf00000000000000 , 0xaeb0000000000000 , 0xac60000000000000 , 0xadd0000000000000
+  , 0xa9c0000000000000 , 0xa870000000000000 , 0xaaa0000000000000 , 0xab10000000000000
+  , 0xa280000000000000 , 0xa330000000000000 , 0xa1e0000000000000 , 0xa050000000000000
+  , 0xa440000000000000 , 0xa5f0000000000000 , 0xa720000000000000 , 0xa690000000000000
+  , 0x8200000000000000 , 0x83b0000000000000 , 0x8160000000000000 , 0x80d0000000000000
+  , 0x84c0000000000000 , 0x8570000000000000 , 0x87a0000000000000 , 0x8610000000000000
+  , 0x8f80000000000000 , 0x8e30000000000000 , 0x8ce0000000000000 , 0x8d50000000000000
+  , 0x8940000000000000 , 0x88f0000000000000 , 0x8a20000000000000 , 0x8b90000000000000
+  , 0x9900000000000000 , 0x98b0000000000000 , 0x9a60000000000000 , 0x9bd0000000000000
+  , 0x9fc0000000000000 , 0x9e70000000000000 , 0x9ca0000000000000 , 0x9d10000000000000
+  , 0x9480000000000000 , 0x9530000000000000 , 0x97e0000000000000 , 0x9650000000000000
+  , 0x9240000000000000 , 0x93f0000000000000 , 0x9120000000000000 , 0x9090000000000000
+  ]
diff --git a/src/Data/Digest/CRC8.hs b/src/Data/Digest/CRC8.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/Digest/CRC8.hs
@@ -0,0 +1,104 @@
+{-# LANGUAGE TypeFamilies #-}
+module Data.Digest.CRC8
+    ( CRC8(..)
+    ) where
+
+
+-------------------------------------------------------------------------------
+import           Data.Bits
+import           Data.ByteString     as BS
+import           Data.Vector.Unboxed as V
+import           Data.Word
+-------------------------------------------------------------------------------
+import           Data.Digest.CRC
+-------------------------------------------------------------------------------
+
+
+newtype CRC8 = CRC8 { crc8 :: Word8 } deriving (Show, Eq, Ord)
+
+
+instance CRC CRC8 where
+  type CRCWord CRC8 = Word8
+  initCRC = CRC8 0
+  crcWord = crc8
+  updateDigest = updateDigest8
+  crcTable = table
+
+
+-------------------------------------------------------------------------------
+updateDigest8 :: CRC8 -> ByteString -> CRC8
+updateDigest8 crc = BS.foldl go crc
+  where
+    go (CRC8 crc') b8 =
+      let idx = fromIntegral (crc' `xor` b8) .&. 0xff
+      in CRC8 ((table ! idx) `xor` ((crc' `shiftR` 8) .&. 0xff))
+
+
+-------------------------------------------------------------------------------
+table :: V.Vector Word8
+table = V.fromList
+  [ 0x00, 0x07, 0x0e, 0x09
+  , 0x1c, 0x1b, 0x12, 0x15
+  , 0x38, 0x3f, 0x36, 0x31
+  , 0x24, 0x23, 0x2a, 0x2d
+  , 0x70, 0x77, 0x7e, 0x79
+  , 0x6c, 0x6b, 0x62, 0x65
+  , 0x48, 0x4f, 0x46, 0x41
+  , 0x54, 0x53, 0x5a, 0x5d
+  , 0xe0, 0xe7, 0xee, 0xe9
+  , 0xfc, 0xfb, 0xf2, 0xf5
+  , 0xd8, 0xdf, 0xd6, 0xd1
+  , 0xc4, 0xc3, 0xca, 0xcd
+  , 0x90, 0x97, 0x9e, 0x99
+  , 0x8c, 0x8b, 0x82, 0x85
+  , 0xa8, 0xaf, 0xa6, 0xa1
+  , 0xb4, 0xb3, 0xba, 0xbd
+  , 0xc7, 0xc0, 0xc9, 0xce
+  , 0xdb, 0xdc, 0xd5, 0xd2
+  , 0xff, 0xf8, 0xf1, 0xf6
+  , 0xe3, 0xe4, 0xed, 0xea
+  , 0xb7, 0xb0, 0xb9, 0xbe
+  , 0xab, 0xac, 0xa5, 0xa2
+  , 0x8f, 0x88, 0x81, 0x86
+  , 0x93, 0x94, 0x9d, 0x9a
+  , 0x27, 0x20, 0x29, 0x2e
+  , 0x3b, 0x3c, 0x35, 0x32
+  , 0x1f, 0x18, 0x11, 0x16
+  , 0x03, 0x04, 0x0d, 0x0a
+  , 0x57, 0x50, 0x59, 0x5e
+  , 0x4b, 0x4c, 0x45, 0x42
+  , 0x6f, 0x68, 0x61, 0x66
+  , 0x73, 0x74, 0x7d, 0x7a
+  , 0x89, 0x8e, 0x87, 0x80
+  , 0x95, 0x92, 0x9b, 0x9c
+  , 0xb1, 0xb6, 0xbf, 0xb8
+  , 0xad, 0xaa, 0xa3, 0xa4
+  , 0xf9, 0xfe, 0xf7, 0xf0
+  , 0xe5, 0xe2, 0xeb, 0xec
+  , 0xc1, 0xc6, 0xcf, 0xc8
+  , 0xdd, 0xda, 0xd3, 0xd4
+  , 0x69, 0x6e, 0x67, 0x60
+  , 0x75, 0x72, 0x7b, 0x7c
+  , 0x51, 0x56, 0x5f, 0x58
+  , 0x4d, 0x4a, 0x43, 0x44
+  , 0x19, 0x1e, 0x17, 0x10
+  , 0x05, 0x02, 0x0b, 0x0c
+  , 0x21, 0x26, 0x2f, 0x28
+  , 0x3d, 0x3a, 0x33, 0x34
+  , 0x4e, 0x49, 0x40, 0x47
+  , 0x52, 0x55, 0x5c, 0x5b
+  , 0x76, 0x71, 0x78, 0x7f
+  , 0x6a, 0x6d, 0x64, 0x63
+  , 0x3e, 0x39, 0x30, 0x37
+  , 0x22, 0x25, 0x2c, 0x2b
+  , 0x06, 0x01, 0x08, 0x0f
+  , 0x1a, 0x1d, 0x14, 0x13
+  , 0xae, 0xa9, 0xa0, 0xa7
+  , 0xb2, 0xb5, 0xbc, 0xbb
+  , 0x96, 0x91, 0x98, 0x9f
+  , 0x8a, 0x8d, 0x84, 0x83
+  , 0xde, 0xd9, 0xd0, 0xd7
+  , 0xc2, 0xc5, 0xcc, 0xcb
+  , 0xe6, 0xe1, 0xe8, 0xef
+  , 0xfa, 0xfd, 0xf4, 0xf3
+  ]
diff --git a/test/Main.hs b/test/Main.hs
new file mode 100644
--- /dev/null
+++ b/test/Main.hs
@@ -0,0 +1,88 @@
+{-# LANGUAGE FlexibleContexts    #-}
+{-# LANGUAGE OverloadedStrings   #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+module Main
+    ( main
+    ) where
+
+
+-------------------------------------------------------------------------------
+import           Control.Monad.Trans.Resource
+import           Data.ByteString              (ByteString)
+import           Data.ByteString.Builder
+import           Data.ByteString.Lazy         (toStrict)
+import           Data.Conduit
+import           Data.Conduit.Binary          as CB
+import           Data.Conduit.List            as CL
+import           Data.Monoid
+import           Data.Proxy
+import           Data.Word
+import           Test.Tasty
+import           Test.Tasty.Golden
+-------------------------------------------------------------------------------
+import           Data.Digest.CRC
+import           Data.Digest.CRC16
+import           Data.Digest.CRC32
+import           Data.Digest.CRC64
+import           Data.Digest.CRC8
+-------------------------------------------------------------------------------
+
+
+
+main :: IO ()
+main = defaultMain testSuite
+
+
+-------------------------------------------------------------------------------
+testSuite :: TestTree
+testSuite = testGroup "crc"
+  [ digestGolden "crc-64.golden" (Proxy :: Proxy CRC64)
+  , digestGolden "crc-32.golden" (Proxy :: Proxy CRC32)
+  , digestGolden "crc-16.golden" (Proxy :: Proxy CRC16)
+  , digestGolden "crc-8.golden" (Proxy :: Proxy CRC8)
+  ]
+
+
+-------------------------------------------------------------------------------
+digestGolden :: forall a. (CRC a, HexBuilder (CRCWord a)) => FilePath -> Proxy a -> TestTree
+digestGolden f _ = goldenVsString f goldenPath mkDigests
+  where
+    goldenPath = "test/data/" <> f
+    mkDigests = runResourceT $
+      sourceFile "test/data/inputs" =$=
+        CB.lines =$=
+        CL.map digest =$=
+        CL.map (toHex :: a -> ByteString) =$=
+        CL.map toHexLine $$
+        sinkLbs
+
+
+-------------------------------------------------------------------------------
+toHex :: (CRC a, HexBuilder (CRCWord a)) => a -> ByteString
+toHex = toStrict . toLazyByteString . buildHex . crcWord
+
+
+-------------------------------------------------------------------------------
+class HexBuilder a where
+  buildHex :: a -> Builder
+
+
+instance HexBuilder Word64 where
+  buildHex = word64Hex
+
+
+instance HexBuilder Word32 where
+  buildHex = word32Hex
+
+
+instance HexBuilder Word16 where
+  buildHex = word16Hex
+
+
+instance HexBuilder Word8 where
+  buildHex = word8Hex
+
+
+-------------------------------------------------------------------------------
+toHexLine :: ByteString -> ByteString
+toHexLine b = "0x" <> b <> "\n"
