module Crypto.Threefish.Common (
Tweak (..), showBytes, keyConst, e2m, defaultTweak, parseHex, readHex
) where
import Numeric (showHex)
import Data.Word
import Data.Bits
import Data.Serialize
import Control.Applicative
import qualified Data.ByteString as BS
import Data.Char
import Data.Default
hexDigit :: Char -> Maybe Word8
hexDigit c | c >= '0' && c <= '9' = Just $ fromIntegral $ ord c ord '0'
| c >= 'a' && c <= 'f' = Just $ fromIntegral $ ord c ord 'a' + 10
| c >= 'A' && c <= 'F' = Just $ fromIntegral $ ord c ord 'A' + 10
| otherwise = Nothing
parseHex :: String -> Maybe BS.ByteString
parseHex = go []
where
go :: [Word8] -> String -> Maybe BS.ByteString
go bytes (h:l:xs) = do
h' <- hexDigit h
l' <- hexDigit l
go (((h' `shiftL` 4) .|. l') : bytes) xs
go bytes [] =
Just (BS.pack (reverse bytes))
go _ _ =
Nothing
showBytes :: Word64 -> String
showBytes =
go (8 :: Int)
where
sr = shiftR
go 0 _ = ""
go n w = showHex ((w`sr`4).&.15) $ showHex (w.&.15) $ go (n1) (w`sr`8)
keyConst :: Word64
keyConst = 0x1BD11BDAA9FC1A22
defaultTweak :: Tweak
defaultTweak = Tweak 0 0
e2m :: Either a b -> Maybe b
e2m (Right x) = Just x
e2m _ = Nothing
data Tweak = Tweak !Word64
!Word64
instance Serialize Tweak where
put (Tweak low high) = putWord64le low >> putWord64le high
get = Tweak <$> getWord64le <*> getWord64le
instance Show Tweak where
show (Tweak low high) = showBytes low ++ showBytes high
instance Default Tweak where
def = defaultTweak
readHex :: Serialize a => String -> Maybe a
readHex s = parseHex s >>= e2m . decode