diff --git a/Git/Libgit2.hs b/Git/Libgit2.hs
--- a/Git/Libgit2.hs
+++ b/Git/Libgit2.hs
@@ -41,10 +41,11 @@
        , lgLoadPackFileInMemory
        , lgReadFromPack
        , lgWithPackFile
-       , SHA
+       , SHA(..)
        , oidToSha
        , shaToOid
        , shaToText
+       , textToSha
        , openLgRepository
        , runLgRepository
        , strToOid
@@ -61,12 +62,14 @@
 import           Control.Monad.Loops
 import           Control.Monad.Trans.Reader
 import           Control.Monad.Trans.Resource
+import qualified Data.Binary as Bin
 import           Data.Bits ((.|.))
 import qualified Data.ByteString as B
 import qualified Data.ByteString.Base16 as B16
 import qualified Data.ByteString.Unsafe as BU
 import           Data.HashMap.Strict (HashMap)
 import qualified Data.HashMap.Strict as HashMap
+import           Data.Hashable
 import           Data.IORef
 import           Data.List as L
 import           Data.Maybe
@@ -1117,7 +1120,7 @@
 
         debug "Discovering the hash used to identify the pack file"
         sha <- liftIO $ oidToSha =<< c'git_indexer_stream_hash idxPtr
-        debug $ "The hash used is: " ++ show sha
+        debug $ "The hash used is: " ++ show (shaToText sha)
         return (shaToText sha)
 
 strToOid :: String -> IO (ForeignPtr C'git_oid)
@@ -1129,22 +1132,35 @@
         when (r < 0) $ throwIO Git.OidCopyFailed
         return ptr
 
-type SHA = B.ByteString
+newtype SHA = SHA B.ByteString deriving (Eq, Ord, Read, Show)
 
-oidToSha :: Ptr C'git_oid -> IO B.ByteString
+instance Bin.Binary SHA where
+    put (SHA t) = Bin.put t
+    get = SHA <$> Bin.get
+
+instance Hashable SHA where
+    hashWithSalt salt (SHA bs) = hashWithSalt salt bs
+
+oidToSha :: Ptr C'git_oid -> IO SHA
 oidToSha oidPtr =
-    B.packCStringLen (castPtr oidPtr, sizeOf (undefined :: C'git_oid))
+    SHA <$> B.packCStringLen (castPtr oidPtr, sizeOf (undefined :: C'git_oid))
 
-shaToOid :: B.ByteString -> IO (ForeignPtr C'git_oid)
-shaToOid bs = BU.unsafeUseAsCString bs $ \bytes -> do
+shaToOid :: SHA -> IO (ForeignPtr C'git_oid)
+shaToOid (SHA bs) = BU.unsafeUseAsCString bs $ \bytes -> do
     ptr <- mallocForeignPtr
     withForeignPtr ptr $ \ptr' -> do
         c'git_oid_fromraw ptr' (castPtr bytes)
         return ptr
 
-shaToText :: B.ByteString -> Text
-shaToText = T.decodeUtf8 . B16.encode
+shaToText :: SHA -> Text
+shaToText (SHA bs) = T.decodeUtf8 (B16.encode bs)
 
+textToSha :: Monad m => Text -> m SHA
+textToSha t =
+    case B16.decode $ T.encodeUtf8 t of
+        (bs, "") -> return (SHA bs)
+        _ -> fail "Invalid base16 encoding"
+
 lgWritePackFile :: Git.MonadGit m => FilePath -> LgRepository m ()
 lgWritePackFile packFile = do
     -- jww (2013-04-23): This would be much more efficient (we already have
@@ -1247,7 +1263,7 @@
         debug "Calling function using in-memory odb"
         f odbPtr
 
-lgReadFromPack :: FilePath -> B.ByteString -> Bool
+lgReadFromPack :: FilePath -> SHA -> Bool
                -> IO (Maybe (C'git_otype, CSize, B.ByteString))
 lgReadFromPack idxPath sha metadataOnly =
     alloca $ \objectPtrPtr ->
diff --git a/gitlib-libgit2.cabal b/gitlib-libgit2.cabal
--- a/gitlib-libgit2.cabal
+++ b/gitlib-libgit2.cabal
@@ -1,5 +1,5 @@
 Name:                gitlib-libgit2
-Version:             1.2.1
+Version:             1.2.2
 Synopsis:            Libgit2 backend for gitlib
 License-file:        LICENSE
 License:             MIT
@@ -40,6 +40,7 @@
         , gitlib-utils         >= 1.1.0
         , hlibgit2             >= 0.18.0.7
         , attempt              >= 0.4.0
+        , binary               >= 0.5.1.0
         , bytestring           >= 0.9.2.1
         , base16-bytestring    >= 0.1.1.5
         , conduit              >= 0.5.5
@@ -47,6 +48,7 @@
         , data-default         >= 0.5.0
         , directory            >= 1.1.0.2
         , failure              >= 0.2.0.1
+        , hashable             >= 1.2.0.5
         , hex                  >= 0.1.2
         , lifted-base          >= 0.2.0.2
         , missing-foreign      >= 0.1.1
