threefish-0.1: Crypto/Threefish/Common.hs
-- | Misc. shared constants and functions.
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
-- | Parses a string of hexadecimal digits into a ByteString.
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
-- | Show a little endian Word64 as a string of bytes.
showBytes :: Word64 -> String
showBytes =
go (8 :: Int)
where
sr = shiftR
go 0 _ = ""
go n w = showHex ((w`sr`4).&.15) $ showHex (w.&.15) $ go (n-1) (w`sr`8)
-- | Key constant for Threefish.
keyConst :: Word64
keyConst = 0x1BD11BDAA9FC1A22
-- | Default tweak when Threefish is used in CBC, CTR, etc. modes.
defaultTweak :: Tweak
defaultTweak = Tweak 0 0
-- | Turn an Either computation into its Maybe counterpart.
e2m :: Either a b -> Maybe b
e2m (Right x) = Just x
e2m _ = Nothing
-- | Threefish tweak value. Please see the Skein specification for info on
-- how to use this.
data Tweak = Tweak {-# UNPACK #-} !Word64
{-# UNPACK #-} !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
-- | Read any deserializable type from a hex string.
readHex :: Serialize a => String -> Maybe a
readHex s = parseHex s >>= e2m . decode