module Darcs.Util.Hash( Hash(..)
, encodeBase16, decodeBase16, sha256, rawHash
, match ) where
import qualified Crypto.Hash.SHA256 as SHA256 ( hash )
import qualified Data.ByteString as B
import qualified Data.ByteString.Lazy as BL
import qualified Data.ByteString.Char8 as BC
import qualified Codec.Binary.Base16 as B16
import Data.Maybe( isJust, fromJust )
import Data.Char( toLower, toUpper )
import Data.Data( Data )
import Data.Typeable( Typeable )
data Hash = SHA256 !B.ByteString
| SHA1 !B.ByteString
| NoHash
deriving (Show, Eq, Ord, Read, Typeable, Data)
base16 :: B.ByteString -> B.ByteString
debase16 :: B.ByteString -> Maybe B.ByteString
base16 = BC.map toLower . B16.b16Enc
debase16 bs = case B16.b16Dec $ BC.map toUpper bs of
Right (s, _) -> Just s
Left _ -> Nothing
encodeBase16 :: Hash -> B.ByteString
encodeBase16 (SHA256 bs) = base16 bs
encodeBase16 (SHA1 bs) = base16 bs
encodeBase16 NoHash = B.empty
decodeBase16 :: B.ByteString -> Hash
decodeBase16 bs | B.length bs == 64 && isJust (debase16 bs) = SHA256 (fromJust $ debase16 bs)
| B.length bs == 40 && isJust (debase16 bs) = SHA1 (fromJust $ debase16 bs)
| otherwise = NoHash
sha256 :: BL.ByteString -> Hash
sha256 bits = SHA256 $ SHA256.hash $ B.concat $ BL.toChunks bits
rawHash :: Hash -> B.ByteString
rawHash NoHash = error "Cannot obtain raw hash from NoHash."
rawHash (SHA1 s) = s
rawHash (SHA256 s) = s
match :: Hash -> Hash -> Bool
NoHash `match` _ = False
_ `match` NoHash = False
x `match` y = x == y