{-|
Module      : Botan.Hash
Description : Hash Functions and Checksums
Copyright   : (c) Leo D, 2023
License     : BSD-3-Clause
Maintainer  : leo@apotheca.io
Stability   : experimental
Portability : POSIX

Hash functions are one-way functions, which map data of arbitrary size
to a fixed output length. Most of the hash functions in Botan are designed
to be cryptographically secure, which means that it is computationally
infeasible to create a collision (finding two inputs with the same hash)
or preimages (given a hash output, generating an arbitrary input with the
same hash). But note that not all such hash functions meet their goals,
in particular MD4 and MD5 are trivially broken. However they are still
included due to their wide adoption in various protocols.

Using a hash function is typically split into three stages: initialization,
update, and finalization (often referred to as a IUF interface). The
initialization stage is implicit: after creating a hash function object,
it is ready to process data. Then update is called one or more times.
Calling update several times is equivalent to calling it once with all of
the arguments concatenated. After completing a hash computation (eg using
hashFinal), the internal state is reset to begin hashing a new message.
-}

module Botan.Hash
(

-- * Hashes
-- $introduction

-- * Usage
-- $usage

-- * Idiomatic interface

-- ** Data type
  Hash(..)
, CryptoHash(..)
, Checksum(..)

-- ** Enumerations

, hashes
, cryptoHashes
, checksums

-- ** Associated types
, HashDigest(..)
, BLAKE2bSize(..)
, SHAKE128Size(..)
, SHAKE256Size(..)
, Skein512Size(..)
, Skein512Salt(..)

-- ** Accessors

, hashName
, hashBlockSize
, hashDigestSize

-- ** Idiomatic algorithm
, hash
, hashChunks
, hashLazy
, hashFile
, hashFileLazy
-- , unsafeHash
-- , unsafeHashLazy

-- * Mutable interface

-- ** Tagged mutable context
, MutableHash(..)

-- ** Destructor
, destroyHash

-- ** Initializers
, newHash

-- ** Accessors
, getHashName
, getHashBlockSize
, getHashDigestSize

-- ** Accessory functions
, copyHashState
, clearHash

-- ** Mutable algorithm
, updateHash
, updateHashChunks
, finalizeHash
, updateFinalizeHash
, updateFinalizeClearHash

-- Algorithm references

, blake2b
, gost_34_11
, keccak1600_224
, keccak1600_256
, keccak1600_384
, keccak1600_512
, keccak1600
, md4
, md5
, ripemd160
, sha1
, sha2_224
, sha2_256
, sha2_384
, sha2_512
, sha2_512_256
, sha2
, sha3_224
, sha3_256
, sha3_384
, sha3_512
, sha3
, shake128
, shake256
, sm3
, skein512
, streebog256
, streebog512
, whirlpool
, adler32
, crc24
, crc32

) where

import qualified Data.ByteString as ByteString
import qualified Data.ByteString.Lazy as Lazy

import Data.Foldable

import qualified Botan.Low.Hash as Low

import Botan.Error ()
import Botan.Prelude
import Botan.Utility

-- TODO: Distinguish between nonCopying and autoCopying variants

-- TODO: The patterns established here are useful
--  - The way newtype Foo, isFoo, foo, and unsafeFoo are defined
--  - unsafeFoo may be dropped in favor of MkFoo
--  - easier defining of enumerations
-- Go fix BlockCipher / Cipher to matc

{- $introduction

-}

{- $usage

-}

--
-- Idiomatic interface
--

data Hash
    = BLAKE2b BLAKE2bSize
    | GOST_34_11
    | Keccak1600_224
    | Keccak1600_256
    | Keccak1600_384
    | Keccak1600_512
    | MD4   -- NOTE: TODO: unsafeMD4 instead of md4
    | MD5   -- NOTE: TODO: unsafeMD5 instead of md5
    | RIPEMD160
    | SHA1
    | SHA224    -- TODO: Maybe rename SHA2_...
    | SHA256
    | SHA384
    | SHA512
    | SHA512_256
    | SHA3_224
    | SHA3_256
    | SHA3_384
    | SHA3_512
    | SHAKE128 SHAKE128Size
    | SHAKE256 SHAKE256Size
    | SM3
    | Skein512 Skein512Size Skein512Salt
    | Streebog256
    | Streebog512
    | Whirlpool
    | Adler32
    | CRC24
    | CRC32
--     | Parallel Hash Hash
--     | Comb4P Hash Hash
    deriving (Hash -> Hash -> Bool
(Hash -> Hash -> Bool) -> (Hash -> Hash -> Bool) -> Eq Hash
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: Hash -> Hash -> Bool
== :: Hash -> Hash -> Bool
$c/= :: Hash -> Hash -> Bool
/= :: Hash -> Hash -> Bool
Eq, Eq Hash
Eq Hash =>
(Hash -> Hash -> Ordering)
-> (Hash -> Hash -> Bool)
-> (Hash -> Hash -> Bool)
-> (Hash -> Hash -> Bool)
-> (Hash -> Hash -> Bool)
-> (Hash -> Hash -> Hash)
-> (Hash -> Hash -> Hash)
-> Ord Hash
Hash -> Hash -> Bool
Hash -> Hash -> Ordering
Hash -> Hash -> Hash
forall a.
Eq a =>
(a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
$ccompare :: Hash -> Hash -> Ordering
compare :: Hash -> Hash -> Ordering
$c< :: Hash -> Hash -> Bool
< :: Hash -> Hash -> Bool
$c<= :: Hash -> Hash -> Bool
<= :: Hash -> Hash -> Bool
$c> :: Hash -> Hash -> Bool
> :: Hash -> Hash -> Bool
$c>= :: Hash -> Hash -> Bool
>= :: Hash -> Hash -> Bool
$cmax :: Hash -> Hash -> Hash
max :: Hash -> Hash -> Hash
$cmin :: Hash -> Hash -> Hash
min :: Hash -> Hash -> Hash
Ord, Int -> Hash -> ShowS
[Hash] -> ShowS
Hash -> String
(Int -> Hash -> ShowS)
-> (Hash -> String) -> ([Hash] -> ShowS) -> Show Hash
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> Hash -> ShowS
showsPrec :: Int -> Hash -> ShowS
$cshow :: Hash -> String
show :: Hash -> String
$cshowList :: [Hash] -> ShowS
showList :: [Hash] -> ShowS
Show)

newtype CryptoHash = MkCryptoHash { CryptoHash -> Hash
unCryptoHash :: Hash }
    deriving (CryptoHash -> CryptoHash -> Bool
(CryptoHash -> CryptoHash -> Bool)
-> (CryptoHash -> CryptoHash -> Bool) -> Eq CryptoHash
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: CryptoHash -> CryptoHash -> Bool
== :: CryptoHash -> CryptoHash -> Bool
$c/= :: CryptoHash -> CryptoHash -> Bool
/= :: CryptoHash -> CryptoHash -> Bool
Eq, Eq CryptoHash
Eq CryptoHash =>
(CryptoHash -> CryptoHash -> Ordering)
-> (CryptoHash -> CryptoHash -> Bool)
-> (CryptoHash -> CryptoHash -> Bool)
-> (CryptoHash -> CryptoHash -> Bool)
-> (CryptoHash -> CryptoHash -> Bool)
-> (CryptoHash -> CryptoHash -> CryptoHash)
-> (CryptoHash -> CryptoHash -> CryptoHash)
-> Ord CryptoHash
CryptoHash -> CryptoHash -> Bool
CryptoHash -> CryptoHash -> Ordering
CryptoHash -> CryptoHash -> CryptoHash
forall a.
Eq a =>
(a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
$ccompare :: CryptoHash -> CryptoHash -> Ordering
compare :: CryptoHash -> CryptoHash -> Ordering
$c< :: CryptoHash -> CryptoHash -> Bool
< :: CryptoHash -> CryptoHash -> Bool
$c<= :: CryptoHash -> CryptoHash -> Bool
<= :: CryptoHash -> CryptoHash -> Bool
$c> :: CryptoHash -> CryptoHash -> Bool
> :: CryptoHash -> CryptoHash -> Bool
$c>= :: CryptoHash -> CryptoHash -> Bool
>= :: CryptoHash -> CryptoHash -> Bool
$cmax :: CryptoHash -> CryptoHash -> CryptoHash
max :: CryptoHash -> CryptoHash -> CryptoHash
$cmin :: CryptoHash -> CryptoHash -> CryptoHash
min :: CryptoHash -> CryptoHash -> CryptoHash
Ord, Int -> CryptoHash -> ShowS
[CryptoHash] -> ShowS
CryptoHash -> String
(Int -> CryptoHash -> ShowS)
-> (CryptoHash -> String)
-> ([CryptoHash] -> ShowS)
-> Show CryptoHash
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> CryptoHash -> ShowS
showsPrec :: Int -> CryptoHash -> ShowS
$cshow :: CryptoHash -> String
show :: CryptoHash -> String
$cshowList :: [CryptoHash] -> ShowS
showList :: [CryptoHash] -> ShowS
Show)

isCryptoHash :: Hash -> Bool
isCryptoHash :: Hash -> Bool
isCryptoHash (BLAKE2b Int
_)    = Bool
True
isCryptoHash Hash
GOST_34_11     = Bool
True
isCryptoHash Hash
Keccak1600_224 = Bool
True
isCryptoHash Hash
Keccak1600_256 = Bool
True
isCryptoHash Hash
Keccak1600_384 = Bool
True
isCryptoHash Hash
Keccak1600_512 = Bool
True
isCryptoHash Hash
MD4            = Bool
True
isCryptoHash Hash
MD5            = Bool
True
isCryptoHash Hash
RIPEMD160      = Bool
True
isCryptoHash Hash
SHA1           = Bool
True
isCryptoHash Hash
SHA224         = Bool
True
isCryptoHash Hash
SHA256         = Bool
True
isCryptoHash Hash
SHA384         = Bool
True
isCryptoHash Hash
SHA512         = Bool
True
isCryptoHash Hash
SHA512_256     = Bool
True
isCryptoHash Hash
SHA3_224       = Bool
True
isCryptoHash Hash
SHA3_256       = Bool
True
isCryptoHash Hash
SHA3_384       = Bool
True
isCryptoHash Hash
SHA3_512       = Bool
True
isCryptoHash (SHAKE128 Int
_)   = Bool
True
isCryptoHash (SHAKE256 Int
_)   = Bool
True
isCryptoHash Hash
SM3            = Bool
True
isCryptoHash (Skein512 Int
_ Skein512Salt
_) = Bool
True
isCryptoHash Hash
Streebog256    = Bool
True
isCryptoHash Hash
Streebog512    = Bool
True
isCryptoHash Hash
Whirlpool      = Bool
True
isCryptoHash Hash
_              = Bool
False

cryptoHash :: Hash -> Maybe CryptoHash
cryptoHash :: Hash -> Maybe CryptoHash
cryptoHash Hash
h | Hash -> Bool
isCryptoHash Hash
h = CryptoHash -> Maybe CryptoHash
forall a. a -> Maybe a
Just (CryptoHash -> Maybe CryptoHash) -> CryptoHash -> Maybe CryptoHash
forall a b. (a -> b) -> a -> b
$ Hash -> CryptoHash
MkCryptoHash Hash
h
cryptoHash Hash
_                = Maybe CryptoHash
forall a. Maybe a
Nothing

unsafeCryptoHash :: Hash -> CryptoHash
unsafeCryptoHash :: Hash -> CryptoHash
unsafeCryptoHash = Hash -> CryptoHash
MkCryptoHash

newtype Checksum = MkChecksum { Checksum -> Hash
unChecksum :: Hash }
    deriving (Checksum -> Checksum -> Bool
(Checksum -> Checksum -> Bool)
-> (Checksum -> Checksum -> Bool) -> Eq Checksum
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: Checksum -> Checksum -> Bool
== :: Checksum -> Checksum -> Bool
$c/= :: Checksum -> Checksum -> Bool
/= :: Checksum -> Checksum -> Bool
Eq, Eq Checksum
Eq Checksum =>
(Checksum -> Checksum -> Ordering)
-> (Checksum -> Checksum -> Bool)
-> (Checksum -> Checksum -> Bool)
-> (Checksum -> Checksum -> Bool)
-> (Checksum -> Checksum -> Bool)
-> (Checksum -> Checksum -> Checksum)
-> (Checksum -> Checksum -> Checksum)
-> Ord Checksum
Checksum -> Checksum -> Bool
Checksum -> Checksum -> Ordering
Checksum -> Checksum -> Checksum
forall a.
Eq a =>
(a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
$ccompare :: Checksum -> Checksum -> Ordering
compare :: Checksum -> Checksum -> Ordering
$c< :: Checksum -> Checksum -> Bool
< :: Checksum -> Checksum -> Bool
$c<= :: Checksum -> Checksum -> Bool
<= :: Checksum -> Checksum -> Bool
$c> :: Checksum -> Checksum -> Bool
> :: Checksum -> Checksum -> Bool
$c>= :: Checksum -> Checksum -> Bool
>= :: Checksum -> Checksum -> Bool
$cmax :: Checksum -> Checksum -> Checksum
max :: Checksum -> Checksum -> Checksum
$cmin :: Checksum -> Checksum -> Checksum
min :: Checksum -> Checksum -> Checksum
Ord, Int -> Checksum -> ShowS
[Checksum] -> ShowS
Checksum -> String
(Int -> Checksum -> ShowS)
-> (Checksum -> String) -> ([Checksum] -> ShowS) -> Show Checksum
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> Checksum -> ShowS
showsPrec :: Int -> Checksum -> ShowS
$cshow :: Checksum -> String
show :: Checksum -> String
$cshowList :: [Checksum] -> ShowS
showList :: [Checksum] -> ShowS
Show)

isChecksum :: Hash -> Bool
isChecksum :: Hash -> Bool
isChecksum Hash
Adler32  = Bool
True
isChecksum Hash
CRC24    = Bool
True
isChecksum Hash
CRC32    = Bool
True
isChecksum Hash
_        = Bool
False

checksum :: Hash -> Maybe Checksum
checksum :: Hash -> Maybe Checksum
checksum Hash
h | Hash -> Bool
isChecksum Hash
h = Checksum -> Maybe Checksum
forall a. a -> Maybe a
Just (Checksum -> Maybe Checksum) -> Checksum -> Maybe Checksum
forall a b. (a -> b) -> a -> b
$ Hash -> Checksum
MkChecksum Hash
h
checksum Hash
_                = Maybe Checksum
forall a. Maybe a
Nothing

unsafeChecksum :: Hash -> Checksum
unsafeChecksum :: Hash -> Checksum
unsafeChecksum = Hash -> Checksum
MkChecksum

-- newtype HashStrategy = MkHashStrategy { unHashStrategy :: Hash }
--     deriving (Eq, Ord)

-- Associated types

type BLAKE2bSize = Int      -- 1-64 bytes, eg: 8-512 in multiples of 8
type SHAKE128Size = Int
type SHAKE256Size = Int
type Skein512Size = Int
type Skein512Salt = ByteString  -- Must not contain ")", can contain "," if escaped, best use ASCII text

-- Enumerations

-- NOTE: MAC max key sizes imply that the max digest should be 4096
defaultHashLength :: Int
defaultHashLength = Int
128

hashes :: [ Hash ]
hashes :: [Hash]
hashes = 
    [ Int -> Hash
BLAKE2b Int
defaultHashLength
    , Hash
GOST_34_11
    , Hash
Keccak1600_224
    , Hash
Keccak1600_256
    , Hash
Keccak1600_384
    , Hash
Keccak1600_512
    , Hash
MD4
    , Hash
MD5
    , Hash
RIPEMD160
    , Hash
SHA1
    , Hash
SHA224
    , Hash
SHA256
    , Hash
SHA384
    , Hash
SHA512
    , Hash
SHA512_256
    , Hash
SHA3_224
    , Hash
SHA3_256
    , Hash
SHA3_384
    , Hash
SHA3_512
    , Int -> Hash
SHAKE128 Int
defaultHashLength
    , Int -> Hash
SHAKE256 Int
defaultHashLength
    , Hash
SM3
    , Int -> Skein512Salt -> Hash
Skein512 Int
defaultHashLength Skein512Salt
""
    , Hash
Streebog256
    , Hash
Streebog512
    , Hash
Whirlpool
    , Hash
Adler32
    , Hash
CRC24
    , Hash
CRC32
    ]

cryptoHashes :: [ CryptoHash ]
cryptoHashes :: [CryptoHash]
cryptoHashes = (Hash -> CryptoHash) -> [Hash] -> [CryptoHash]
forall a b. (a -> b) -> [a] -> [b]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap Hash -> CryptoHash
MkCryptoHash ([Hash] -> [CryptoHash]) -> [Hash] -> [CryptoHash]
forall a b. (a -> b) -> a -> b
$ (Hash -> Bool) -> [Hash] -> [Hash]
forall a. (a -> Bool) -> [a] -> [a]
filter Hash -> Bool
isCryptoHash [Hash]
hashes

checksums :: [ Checksum ]
checksums :: [Checksum]
checksums = (Hash -> Checksum) -> [Hash] -> [Checksum]
forall a b. (a -> b) -> [a] -> [b]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap Hash -> Checksum
MkChecksum ([Hash] -> [Checksum]) -> [Hash] -> [Checksum]
forall a b. (a -> b) -> a -> b
$ (Hash -> Bool) -> [Hash] -> [Hash]
forall a. (a -> Bool) -> [a] -> [a]
filter Hash -> Bool
isChecksum [Hash]
hashes

-- Associated types

type HashDigest = ByteString

-- Accessors

hashName :: Hash -> Low.HashName
hashName :: Hash -> Skein512Salt
hashName (BLAKE2b Int
sz)       = Int -> Skein512Salt
forall {a}. (Ord a, Num a, Show a) => a -> Skein512Salt
Low.blake2b Int
sz        -- "BLAKE2b(" <> showBytes sz <> ")"
hashName Hash
GOST_34_11         = Skein512Salt
Low.GOST_34_11        -- "GOST-34.11"
hashName Hash
Keccak1600_224     = Integer -> Skein512Salt
forall {a}. (Eq a, Num a, Show a) => a -> Skein512Salt
Low.keccak1600 Integer
224    -- "Keccak-1600(224)"
hashName Hash
Keccak1600_256     = Integer -> Skein512Salt
forall {a}. (Eq a, Num a, Show a) => a -> Skein512Salt
Low.keccak1600 Integer
256    -- "Keccak-1600(256)"
hashName Hash
Keccak1600_384     = Integer -> Skein512Salt
forall {a}. (Eq a, Num a, Show a) => a -> Skein512Salt
Low.keccak1600 Integer
384    -- "Keccak-1600(384)"
hashName Hash
Keccak1600_512     = Integer -> Skein512Salt
forall {a}. (Eq a, Num a, Show a) => a -> Skein512Salt
Low.keccak1600 Integer
512    -- "Keccak-1600(512)"
hashName Hash
MD4                = Skein512Salt
Low.MD4               -- "MD4"
hashName Hash
MD5                = Skein512Salt
Low.MD5               -- "MD5"
hashName Hash
RIPEMD160          = Skein512Salt
Low.RIPEMD160         -- "RIPEMD-160"
hashName Hash
SHA1               = Skein512Salt
Low.SHA1              -- "SHA-1"
hashName Hash
SHA224             = Skein512Salt
Low.SHA224            -- "SHA-224"
hashName Hash
SHA256             = Skein512Salt
Low.SHA256            -- "SHA-256"
hashName Hash
SHA512             = Skein512Salt
Low.SHA512            -- "SHA-512"
hashName Hash
SHA384             = Skein512Salt
Low.SHA384            -- "SHA-384"
hashName Hash
SHA512_256         = Skein512Salt
Low.SHA512_256        -- "SHA-512-256"
hashName Hash
SHA3_224           = Integer -> Skein512Salt
forall {a}. (Eq a, Num a, Show a) => a -> Skein512Salt
Low.sha3 Integer
224          -- "SHA-3(224)"
hashName Hash
SHA3_256           = Integer -> Skein512Salt
forall {a}. (Eq a, Num a, Show a) => a -> Skein512Salt
Low.sha3 Integer
256          -- "SHA-3(256)"
hashName Hash
SHA3_384           = Integer -> Skein512Salt
forall {a}. (Eq a, Num a, Show a) => a -> Skein512Salt
Low.sha3 Integer
384          -- "SHA-3(384)"
hashName Hash
SHA3_512           = Integer -> Skein512Salt
forall {a}. (Eq a, Num a, Show a) => a -> Skein512Salt
Low.sha3 Integer
512          -- "SHA-3(512)"
hashName (SHAKE128 Int
sz)      = Int -> Skein512Salt
forall {a}. Show a => a -> Skein512Salt
Low.shake128 Int
sz       -- "SHAKE-128(" <> showBytes sz <> ")"
hashName (SHAKE256 Int
sz)      = Int -> Skein512Salt
forall {a}. Show a => a -> Skein512Salt
Low.shake256 Int
sz       -- "SHAKE-256(" <> showBytes sz <> ")"
hashName Hash
SM3                = Skein512Salt
Low.SM3               -- "SM3"
hashName (Skein512 Int
sz Skein512Salt
b)    = Int -> Skein512Salt -> Skein512Salt
forall {a}. Show a => a -> Skein512Salt -> Skein512Salt
Low.skein512 Int
sz Skein512Salt
b     -- "Skein-512(" <> showBytes sz <> "," <> b <> ")"
hashName Hash
Streebog256        = Skein512Salt
Low.Streebog256       -- "Streebog-256"
hashName Hash
Streebog512        = Skein512Salt
Low.Streebog512       -- "Streebog-512"
hashName Hash
Whirlpool          = Skein512Salt
Low.Whirlpool         -- "Whirlpool"
hashName Hash
Adler32            = Skein512Salt
Low.Adler32          -- "Adler32"
hashName Hash
CRC24              = Skein512Salt
Low.CRC24            -- "CRC24"
hashName Hash
CRC32              = Skein512Salt
Low.CRC32            -- "CRC32"
-- hashName (Parallel ha hb)   = "Parallel(" <> hashName ha <> "," <> hashName hb <> ")"
-- hashName (Comb4P ha hb)     = "Comb4P(" <> hashName ha <> "," <> hashName hb <> ")"

-- NOTE: SIZE IN BYTES
hashDigestSize :: Hash -> Int
hashDigestSize :: Hash -> Int
hashDigestSize (BLAKE2b Int
n)      = Int -> Int -> Int
forall a. Integral a => a -> a -> a
div Int
n Int
8
hashDigestSize Hash
GOST_34_11       = Int
32
hashDigestSize Hash
Keccak1600_224   = Int
28
hashDigestSize Hash
Keccak1600_256   = Int
32
hashDigestSize Hash
Keccak1600_384   = Int
48
hashDigestSize Hash
Keccak1600_512   = Int
64
hashDigestSize Hash
MD4              = Int
16
hashDigestSize Hash
MD5              = Int
16
hashDigestSize Hash
RIPEMD160        = Int
20
hashDigestSize Hash
SHA1             = Int
20
hashDigestSize Hash
SHA224           = Int
28
hashDigestSize Hash
SHA256           = Int
32
hashDigestSize Hash
SHA384           = Int
48
hashDigestSize Hash
SHA512           = Int
64
hashDigestSize Hash
SHA512_256       = Int
32
hashDigestSize Hash
SHA3_224         = Int
28
hashDigestSize Hash
SHA3_256         = Int
32
hashDigestSize Hash
SHA3_384         = Int
48
hashDigestSize Hash
SHA3_512         = Int
64
hashDigestSize (SHAKE128 Int
n)     = Int -> Int -> Int
forall a. Integral a => a -> a -> a
div Int
n Int
8
hashDigestSize (SHAKE256 Int
n)     = Int -> Int -> Int
forall a. Integral a => a -> a -> a
div Int
n Int
8
hashDigestSize Hash
SM3              = Int
32
hashDigestSize (Skein512 Int
n Skein512Salt
_)  = Int -> Int -> Int
forall a. Integral a => a -> a -> a
div Int
n Int
8
hashDigestSize Hash
Streebog256      = Int
32
hashDigestSize Hash
Streebog512      = Int
64
hashDigestSize Hash
Whirlpool        = Int
64
hashDigestSize Hash
Adler32          = Int
4
hashDigestSize Hash
CRC24            = Int
3
hashDigestSize Hash
CRC32            = Int
4
-- hashDigestSize (Parallel ha hb) = undefined
-- hashDigestSize (Comb4P ha hb)   = undefined
-- NOTE: Extracted / confirmed from inspecting:
{-
generateHashDigestSize :: IO ()
generateHashDigestSize = do
    each <- forM hashes  $ \ h -> do
        ctx <- Low.hashInit (hashName h)
        dsz <- Low.hashOutputLength ctx
        return $ concat $
            [ "hashDigestSize "
            , showsPrec 11 h ""
            , " = "
            , show dsz
            ]
    putStrLn $ unlines $
        "hashDigestSize :: Hash -> Int"
        : each
-}

-- NOTE: SIZE IN BITS
hashBlockSize :: Hash -> Int
hashBlockSize :: Hash -> Int
hashBlockSize (BLAKE2b Int
_) = Int
128
hashBlockSize Hash
GOST_34_11 = Int
32
hashBlockSize Hash
Keccak1600_224 = Int
144
hashBlockSize Hash
Keccak1600_256 = Int
136
hashBlockSize Hash
Keccak1600_384 = Int
104
hashBlockSize Hash
Keccak1600_512 = Int
72
hashBlockSize Hash
MD4 = Int
64
hashBlockSize Hash
MD5 = Int
64
hashBlockSize Hash
RIPEMD160 = Int
64
hashBlockSize Hash
SHA1 = Int
64
hashBlockSize Hash
SHA224 = Int
64
hashBlockSize Hash
SHA256 = Int
64
hashBlockSize Hash
SHA384 = Int
128
hashBlockSize Hash
SHA512 = Int
128
hashBlockSize Hash
SHA512_256 = Int
128
hashBlockSize Hash
SHA3_224 = Int
144
hashBlockSize Hash
SHA3_256 = Int
136
hashBlockSize Hash
SHA3_384 = Int
104
hashBlockSize Hash
SHA3_512 = Int
72
hashBlockSize (SHAKE128 Int
_) = Int
168
hashBlockSize (SHAKE256 Int
_) = Int
136
hashBlockSize Hash
SM3 = Int
64
hashBlockSize (Skein512 Int
_ Skein512Salt
_) = Int
64
hashBlockSize Hash
Streebog256 = Int
64
hashBlockSize Hash
Streebog512 = Int
64
hashBlockSize Hash
Whirlpool = Int
64
hashBlockSize Hash
Adler32 = String -> Int
forall a. HasCallStack => String -> a
error String
"Unimplemented: checksumBlockSize"
hashBlockSize Hash
CRC24   = String -> Int
forall a. HasCallStack => String -> a
error String
"Unimplemented: checksumBlockSize"
hashBlockSize Hash
CRC32   = String -> Int
forall a. HasCallStack => String -> a
error String
"Unimplemented: checksumBlockSize"
{-# WARNING hashBlockSize "Unimplemented for: Adler32, CRC24, CRC32" #-}
-- NOTE: Extracted / confirmed from inspecting:
{-
generateHashBlockSize :: IO ()
generateHashBlockSize = do
    each <- forM hashes  $ \ h -> do
        ctx <- Low.hashInit (hashName h)
        bsz <- Low.hashBlockSize ctx
        return $ concat $
            [ "hashBlockSize "
            , showsPrec 11 h ""
            , " = "
            , show bsz
            ]
    putStrLn $ unlines $
        "hashBlockSize :: Hash -> Int"
        : each
-}

-- Idiomatic algorithm

hash :: Hash -> ByteString -> HashDigest
hash :: Hash -> Skein512Salt -> Skein512Salt
hash Hash
h Skein512Salt
bs = IO Skein512Salt -> Skein512Salt
forall a. IO a -> a
unsafePerformIO (IO Skein512Salt -> Skein512Salt)
-> IO Skein512Salt -> Skein512Salt
forall a b. (a -> b) -> a -> b
$ do
    MutableHash
ctx <- Hash -> IO MutableHash
forall (m :: * -> *). MonadIO m => Hash -> m MutableHash
newHash Hash
h
    MutableHash -> Skein512Salt -> IO Skein512Salt
forall (m :: * -> *).
MonadIO m =>
MutableHash -> Skein512Salt -> m Skein512Salt
updateFinalizeHash MutableHash
ctx Skein512Salt
bs
{-# NOINLINE hash #-}

hashChunks :: Hash -> [ ByteString ] -> HashDigest
hashChunks :: Hash -> [Skein512Salt] -> Skein512Salt
hashChunks Hash
h [Skein512Salt]
bss = IO Skein512Salt -> Skein512Salt
forall a. IO a -> a
unsafePerformIO (IO Skein512Salt -> Skein512Salt)
-> IO Skein512Salt -> Skein512Salt
forall a b. (a -> b) -> a -> b
$ do
    MutableHash
ctx <- Hash -> IO MutableHash
forall (m :: * -> *). MonadIO m => Hash -> m MutableHash
newHash Hash
h
    MutableHash -> [Skein512Salt] -> IO ()
forall (m :: * -> *).
MonadIO m =>
MutableHash -> [Skein512Salt] -> m ()
updateHashChunks MutableHash
ctx [Skein512Salt]
bss
    MutableHash -> IO Skein512Salt
forall (m :: * -> *). MonadIO m => MutableHash -> m Skein512Salt
finalizeHash MutableHash
ctx
{-# NOINLINE hashChunks #-}

hashLazy :: Hash -> Lazy.ByteString -> HashDigest
hashLazy :: Hash -> ByteString -> Skein512Salt
hashLazy Hash
h ByteString
bs = Hash -> [Skein512Salt] -> Skein512Salt
hashChunks Hash
h (ByteString -> [Skein512Salt]
Lazy.toChunks ByteString
bs)
-- hashLazy h bs = unsafePerformIO $ do
--     ctx <- newHash h
--     updateHashChunks ctx (Lazy.toChunks bs)
--     finalizeHash ctx
-- {-# NOINLINE hashLazy #-}

hashFile :: (MonadIO m) => Hash -> FilePath -> m HashDigest
hashFile :: forall (m :: * -> *). MonadIO m => Hash -> String -> m Skein512Salt
hashFile Hash
h String
fp = Hash -> Skein512Salt -> Skein512Salt
hash Hash
h (Skein512Salt -> Skein512Salt) -> m Skein512Salt -> m Skein512Salt
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> IO Skein512Salt -> m Skein512Salt
forall a. IO a -> m a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (String -> IO Skein512Salt
ByteString.readFile String
fp)

hashFileLazy :: (MonadIO m) => Hash -> FilePath -> m HashDigest
hashFileLazy :: forall (m :: * -> *). MonadIO m => Hash -> String -> m Skein512Salt
hashFileLazy Hash
h String
fp = do
    ByteString
bs <- IO ByteString -> m ByteString
forall a. IO a -> m a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO ByteString -> m ByteString) -> IO ByteString -> m ByteString
forall a b. (a -> b) -> a -> b
$ String -> IO ByteString
Lazy.readFile String
fp
    -- Seq is probably unnecessary
    let d :: Skein512Salt
d = Hash -> ByteString -> Skein512Salt
hashLazy Hash
h ByteString
bs
        in Skein512Salt
d Skein512Salt -> m Skein512Salt -> m Skein512Salt
forall a b. a -> b -> b
`seq` Skein512Salt -> m Skein512Salt
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return Skein512Salt
d

--
-- Mutable interface
--

-- Tagged mutable context

data MutableHash = MkMutableHash
    { MutableHash -> Hash
mutableHashType    :: Hash
    , MutableHash -> Hash
mutableHashCtx     :: Low.Hash
    }

-- Destructor

destroyHash
    :: (MonadIO m)
    => MutableHash
    -> m ()
destroyHash :: forall (m :: * -> *). MonadIO m => MutableHash -> m ()
destroyHash = IO () -> m ()
forall a. IO a -> m a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO () -> m ()) -> (MutableHash -> IO ()) -> MutableHash -> m ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Hash -> IO ()
Low.hashDestroy (Hash -> IO ()) -> (MutableHash -> Hash) -> MutableHash -> IO ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. MutableHash -> Hash
mutableHashCtx

-- Initializers

newHash
    :: (MonadIO m)
    => Hash
    -> m MutableHash
newHash :: forall (m :: * -> *). MonadIO m => Hash -> m MutableHash
newHash Hash
h = do
    Hash
ctx <- IO Hash -> m Hash
forall a. IO a -> m a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO Hash -> m Hash) -> IO Hash -> m Hash
forall a b. (a -> b) -> a -> b
$ Skein512Salt -> IO Hash
Low.hashInit (Skein512Salt -> IO Hash) -> Skein512Salt -> IO Hash
forall a b. (a -> b) -> a -> b
$ Hash -> Skein512Salt
hashName Hash
h
    MutableHash -> m MutableHash
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return (MutableHash -> m MutableHash) -> MutableHash -> m MutableHash
forall a b. (a -> b) -> a -> b
$ Hash -> Hash -> MutableHash
MkMutableHash Hash
h Hash
ctx

-- Accessors

getHashName
    :: (MonadIO m)
    => MutableHash
    -> m Low.HashName
getHashName :: forall (m :: * -> *). MonadIO m => MutableHash -> m Skein512Salt
getHashName = IO Skein512Salt -> m Skein512Salt
forall a. IO a -> m a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO Skein512Salt -> m Skein512Salt)
-> (MutableHash -> IO Skein512Salt)
-> MutableHash
-> m Skein512Salt
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Hash -> IO Skein512Salt
Low.hashName (Hash -> IO Skein512Salt)
-> (MutableHash -> Hash) -> MutableHash -> IO Skein512Salt
forall b c a. (b -> c) -> (a -> b) -> a -> c
. MutableHash -> Hash
mutableHashCtx

getHashBlockSize
    :: (MonadIO m)
    => MutableHash
    -> m Int
getHashBlockSize :: forall (m :: * -> *). MonadIO m => MutableHash -> m Int
getHashBlockSize = IO Int -> m Int
forall a. IO a -> m a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO Int -> m Int)
-> (MutableHash -> IO Int) -> MutableHash -> m Int
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Hash -> IO Int
Low.hashBlockSize (Hash -> IO Int) -> (MutableHash -> Hash) -> MutableHash -> IO Int
forall b c a. (b -> c) -> (a -> b) -> a -> c
. MutableHash -> Hash
mutableHashCtx

getHashDigestSize
    :: (MonadIO m)
    => MutableHash
    -> m Int
getHashDigestSize :: forall (m :: * -> *). MonadIO m => MutableHash -> m Int
getHashDigestSize = IO Int -> m Int
forall a. IO a -> m a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO Int -> m Int)
-> (MutableHash -> IO Int) -> MutableHash -> m Int
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Hash -> IO Int
Low.hashOutputLength (Hash -> IO Int) -> (MutableHash -> Hash) -> MutableHash -> IO Int
forall b c a. (b -> c) -> (a -> b) -> a -> c
. MutableHash -> Hash
mutableHashCtx

-- Accessory functions

copyHashState
    :: (MonadIO m)
    => MutableHash
    -> m MutableHash
copyHashState :: forall (m :: * -> *). MonadIO m => MutableHash -> m MutableHash
copyHashState MutableHash
mh = do
    Hash
ctx <- IO Hash -> m Hash
forall a. IO a -> m a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO Hash -> m Hash) -> IO Hash -> m Hash
forall a b. (a -> b) -> a -> b
$ Hash -> IO Hash
Low.hashCopyState (Hash -> IO Hash) -> Hash -> IO Hash
forall a b. (a -> b) -> a -> b
$ MutableHash -> Hash
mutableHashCtx MutableHash
mh
    MutableHash -> m MutableHash
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return (MutableHash -> m MutableHash) -> MutableHash -> m MutableHash
forall a b. (a -> b) -> a -> b
$ Hash -> Hash -> MutableHash
MkMutableHash (MutableHash -> Hash
mutableHashType MutableHash
mh) Hash
ctx

clearHash
    :: (MonadIO m)
    => MutableHash
    -> m ()
clearHash :: forall (m :: * -> *). MonadIO m => MutableHash -> m ()
clearHash = IO () -> m ()
forall a. IO a -> m a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO () -> m ()) -> (MutableHash -> IO ()) -> MutableHash -> m ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Hash -> IO ()
Low.hashClear (Hash -> IO ()) -> (MutableHash -> Hash) -> MutableHash -> IO ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. MutableHash -> Hash
mutableHashCtx

-- Mutable algorithm
-- TODO: Flip?
updateHash
    :: (MonadIO m)
    => MutableHash
    -> ByteString
    -> m ()
updateHash :: forall (m :: * -> *).
MonadIO m =>
MutableHash -> Skein512Salt -> m ()
updateHash MutableHash
h Skein512Salt
bs = MutableHash -> [Skein512Salt] -> m ()
forall (m :: * -> *).
MonadIO m =>
MutableHash -> [Skein512Salt] -> m ()
updateHashChunks MutableHash
h [Skein512Salt
bs]

-- TODO: Flip?
updateHashChunks
    :: (MonadIO m)
    => MutableHash
    -> [ByteString]
    -> m ()
updateHashChunks :: forall (m :: * -> *).
MonadIO m =>
MutableHash -> [Skein512Salt] -> m ()
updateHashChunks MutableHash
mh [Skein512Salt]
chunks = let ctx :: Hash
ctx = MutableHash -> Hash
mutableHashCtx MutableHash
mh in
    IO () -> m ()
forall a. IO a -> m a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO () -> m ()) -> IO () -> m ()
forall a b. (a -> b) -> a -> b
$ (Skein512Salt -> IO ()) -> [Skein512Salt] -> IO ()
forall (t :: * -> *) (f :: * -> *) a b.
(Foldable t, Applicative f) =>
(a -> f b) -> t a -> f ()
traverse_ (Hash -> Skein512Salt -> IO ()
Low.hashUpdate Hash
ctx) [Skein512Salt]
chunks

finalizeHash
    :: (MonadIO m)
    => MutableHash
    -> m HashDigest
finalizeHash :: forall (m :: * -> *). MonadIO m => MutableHash -> m Skein512Salt
finalizeHash = IO Skein512Salt -> m Skein512Salt
forall a. IO a -> m a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO Skein512Salt -> m Skein512Salt)
-> (MutableHash -> IO Skein512Salt)
-> MutableHash
-> m Skein512Salt
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Hash -> IO Skein512Salt
Low.hashFinal (Hash -> IO Skein512Salt)
-> (MutableHash -> Hash) -> MutableHash -> IO Skein512Salt
forall b c a. (b -> c) -> (a -> b) -> a -> c
. MutableHash -> Hash
mutableHashCtx

updateFinalizeHash
    :: (MonadIO m)
    => MutableHash
    -> ByteString
    -> m HashDigest
updateFinalizeHash :: forall (m :: * -> *).
MonadIO m =>
MutableHash -> Skein512Salt -> m Skein512Salt
updateFinalizeHash MutableHash
h Skein512Salt
bs = IO Skein512Salt -> m Skein512Salt
forall a. IO a -> m a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO Skein512Salt -> m Skein512Salt)
-> IO Skein512Salt -> m Skein512Salt
forall a b. (a -> b) -> a -> b
$ do
    MutableHash -> Skein512Salt -> IO ()
forall (m :: * -> *).
MonadIO m =>
MutableHash -> Skein512Salt -> m ()
updateHash MutableHash
h Skein512Salt
bs
    MutableHash -> IO Skein512Salt
forall (m :: * -> *). MonadIO m => MutableHash -> m Skein512Salt
finalizeHash MutableHash
h

updateFinalizeClearHash
    :: (MonadIO m)
    => MutableHash
    -> ByteString
    -> m HashDigest
updateFinalizeClearHash :: forall (m :: * -> *).
MonadIO m =>
MutableHash -> Skein512Salt -> m Skein512Salt
updateFinalizeClearHash MutableHash
h Skein512Salt
bs = MutableHash -> Skein512Salt -> m Skein512Salt
forall (m :: * -> *).
MonadIO m =>
MutableHash -> Skein512Salt -> m Skein512Salt
updateFinalizeHash MutableHash
h Skein512Salt
bs m Skein512Salt -> m () -> m Skein512Salt
forall a b. m a -> m b -> m a
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<* MutableHash -> m ()
forall (m :: * -> *). MonadIO m => MutableHash -> m ()
clearHash MutableHash
h


--
-- Algorithm references
--

-- blake2b_128 :: Hash
-- blake2b_128 = fromJust $ blake2b 128

-- blake2b_256 :: Hash
-- blake2b_256 = fromJust $ blake2b 256

-- blake2b_512 :: Hash
-- blake2b_512 = fromJust $ blake2b 512

blake2b :: Int -> Maybe Hash
blake2b :: Int -> Maybe Hash
blake2b Int
n | Int
0 Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
n Bool -> Bool -> Bool
&& Int -> Int -> Int
forall a. Integral a => a -> a -> a
mod Int
n Int
8 Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
0 Bool -> Bool -> Bool
&& Int
n Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= Int
512 = Hash -> Maybe Hash
forall a. a -> Maybe a
Just (Hash -> Maybe Hash) -> Hash -> Maybe Hash
forall a b. (a -> b) -> a -> b
$ Int -> Hash
BLAKE2b Int
n
blake2b Int
_ = Maybe Hash
forall a. Maybe a
Nothing

gost_34_11 :: Hash
gost_34_11 :: Hash
gost_34_11 = Hash
GOST_34_11

keccak1600_224 :: Hash
keccak1600_224 :: Hash
keccak1600_224 = Hash
Keccak1600_224

keccak1600_256 :: Hash
keccak1600_256 :: Hash
keccak1600_256 = Hash
Keccak1600_256

keccak1600_384 :: Hash
keccak1600_384 :: Hash
keccak1600_384 = Hash
Keccak1600_384

keccak1600_512 :: Hash
keccak1600_512 :: Hash
keccak1600_512 = Hash
Keccak1600_512

keccak1600 :: Int -> Maybe Hash
keccak1600 :: Int -> Maybe Hash
keccak1600 Int
224        = Hash -> Maybe Hash
forall a. a -> Maybe a
Just Hash
keccak1600_224
keccak1600 Int
256        = Hash -> Maybe Hash
forall a. a -> Maybe a
Just Hash
keccak1600_256
keccak1600 Int
384        = Hash -> Maybe Hash
forall a. a -> Maybe a
Just Hash
keccak1600_384
keccak1600 Int
512        = Hash -> Maybe Hash
forall a. a -> Maybe a
Just Hash
keccak1600_512
keccak1600 Int
_          = Maybe Hash
forall a. Maybe a
Nothing

md4 :: Hash
md4 :: Hash
md4 = Hash
MD4

md5 :: Hash
md5 :: Hash
md5 = Hash
MD5

ripemd160 :: Hash
ripemd160 :: Hash
ripemd160 = Hash
RIPEMD160

sha1 :: Hash
sha1 :: Hash
sha1 = Hash
SHA1

sha2_224 :: Hash
sha2_224 :: Hash
sha2_224 = Hash
SHA224

sha2_256 :: Hash
sha2_256 :: Hash
sha2_256 = Hash
SHA256

sha2_384 :: Hash
sha2_384 :: Hash
sha2_384 = Hash
SHA384

sha2_512 :: Hash
sha2_512 :: Hash
sha2_512 = Hash
SHA512

sha2_512_256 :: Hash
sha2_512_256 :: Hash
sha2_512_256 = Hash
SHA512_256

sha2 :: Int -> Maybe Hash
sha2 :: Int -> Maybe Hash
sha2 Int
224 = Hash -> Maybe Hash
forall a. a -> Maybe a
Just Hash
sha2_224
sha2 Int
256 = Hash -> Maybe Hash
forall a. a -> Maybe a
Just Hash
sha2_256
sha2 Int
384 = Hash -> Maybe Hash
forall a. a -> Maybe a
Just Hash
sha2_384
sha2 Int
512 = Hash -> Maybe Hash
forall a. a -> Maybe a
Just Hash
sha2_512
sha2 Int
_   = Maybe Hash
forall a. Maybe a
Nothing

sha3_224 :: Hash
sha3_224 :: Hash
sha3_224 = Hash
SHA3_224

sha3_256 :: Hash
sha3_256 :: Hash
sha3_256 = Hash
SHA3_256

sha3_384 :: Hash
sha3_384 :: Hash
sha3_384 = Hash
SHA3_384

sha3_512 :: Hash
sha3_512 :: Hash
sha3_512 = Hash
SHA3_512

sha3 :: Int -> Maybe Hash
sha3 :: Int -> Maybe Hash
sha3 Int
224 = Hash -> Maybe Hash
forall a. a -> Maybe a
Just Hash
sha3_224
sha3 Int
256 = Hash -> Maybe Hash
forall a. a -> Maybe a
Just Hash
sha3_256
sha3 Int
384 = Hash -> Maybe Hash
forall a. a -> Maybe a
Just Hash
sha3_384
sha3 Int
512 = Hash -> Maybe Hash
forall a. a -> Maybe a
Just Hash
sha3_512
sha3 Int
_   = Maybe Hash
forall a. Maybe a
Nothing

shake128 :: Int -> Maybe Hash
shake128 :: Int -> Maybe Hash
shake128 Int
n | Int
0 Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
n Bool -> Bool -> Bool
&& Int -> Int -> Int
forall a. Integral a => a -> a -> a
mod Int
n Int
8 Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
0 Bool -> Bool -> Bool
&& Int
n Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= Int
512 = Hash -> Maybe Hash
forall a. a -> Maybe a
Just (Hash -> Maybe Hash) -> Hash -> Maybe Hash
forall a b. (a -> b) -> a -> b
$ Int -> Hash
SHAKE128 Int
n

shake256 :: Int -> Maybe Hash
shake256 :: Int -> Maybe Hash
shake256 Int
n | Int
0 Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
n Bool -> Bool -> Bool
&& Int -> Int -> Int
forall a. Integral a => a -> a -> a
mod Int
n Int
8 Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
0 Bool -> Bool -> Bool
&& Int
n Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= Int
512 = Hash -> Maybe Hash
forall a. a -> Maybe a
Just (Hash -> Maybe Hash) -> Hash -> Maybe Hash
forall a b. (a -> b) -> a -> b
$ Int -> Hash
SHAKE256 Int
n

sm3 :: Hash
sm3 :: Hash
sm3 = Hash
SM3

skein512 :: Int -> ByteString -> Maybe Hash
skein512 :: Int -> Skein512Salt -> Maybe Hash
skein512 Int
n Skein512Salt
salt | Int
0 Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
n Bool -> Bool -> Bool
&& Int -> Int -> Int
forall a. Integral a => a -> a -> a
mod Int
n Int
8 Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
0 Bool -> Bool -> Bool
&& Int
n Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= Int
512 = Hash -> Maybe Hash
forall a. a -> Maybe a
Just (Hash -> Maybe Hash) -> Hash -> Maybe Hash
forall a b. (a -> b) -> a -> b
$ Int -> Skein512Salt -> Hash
Skein512 Int
n Skein512Salt
salt

streebog256 :: Hash
streebog256 :: Hash
streebog256 = Hash
Streebog256

streebog512 :: Hash
streebog512 :: Hash
streebog512 = Hash
Streebog512

whirlpool :: Hash
whirlpool :: Hash
whirlpool   = Hash
Whirlpool

adler32 :: Hash
adler32 :: Hash
adler32     = Hash
Adler32

crc24 :: Hash
crc24 :: Hash
crc24       = Hash
CRC24

crc32 :: Hash
crc32 :: Hash
crc32       = Hash
CRC32