    {-# LANGUAGE CPP #-}

    -----------------------------------------------------------------------------
    -- |
    -- Module      :  Crypto.Nettle.Hash
    -- Copyright   :  (c) 2013 Stefan Bühler
    -- License     :  MIT-style (see the file COPYING)
    --
    -- Maintainer  :  stbuehler@web.de
    -- Stability   :  experimental
    -- Portability :  portable
    --
    -- This module exports hash algorithms supported by nettle:
    --   <http://www.lysator.liu.se/~nisse/nettle/>
    --
    -----------------------------------------------------------------------------

    module Crypto.Nettle.Hash (
    	-- * HashAlgorithm class
    	  HashAlgorithm(..)

    	, hash
    	, hash'
    	, hashLazy
    	, hashLazy'

    	-- * hash algorithms
    	-- | Only members of the SHA2 and SHA3 family have no known weaknesses (according to <http://www.lysator.liu.se/~nisse/nettle/nettle.html#Hash-functions>)

    	-- ** GOSTHASH94
    	, GOSTHASH94
    	-- ** MD family
    	, MD2
    	, MD4
    	, MD5
    	-- ** RIPEMD160
    	, RIPEMD160
    	-- ** SHA1
    	, SHA1
    	-- ** SHA2 family
    	-- | The SHA2 family supports digests lengths of 28, 32, 48 or 64 bytes (224, 256, 384, 512 bits),
    	--   and the variants are named after the bit length.
    	--
    	--   The SHA2 family of hash functions were specified by NIST, intended as a replacement for 'SHA1'.
    	, SHA224
    	, SHA256
    	, SHA384
    	, SHA512
    	-- ** SHA3 family
    	-- | The SHA3 family supports (like SHA2) digests lengths of 28, 32, 48 or 64 bytes (224, 256, 384, 512 bits),
    	--   and the variants are named after the bit length.
    	--
    	--   The SHA3 hash functions were specified by NIST in response to weaknesses in SHA1, and doubts about
    	--   SHA2 hash functions which structurally are very similar to SHA1. The standard is a result of a competition,
    	--   where the winner, also known as Keccak, was designed by Guido Bertoni, Joan Daemen, Michaël Peeters and
    	--   Gilles Van Assche. It is structurally very different from all widely used earlier hash functions.
    	, SHA3_224
    	, SHA3_256
    	, SHA3_384
    	, SHA3_512
    	) where

    import Crypto.Nettle.Hash.ForeignImports
    import Crypto.Nettle.Hash.Types
    import Nettle.Utils

    import Data.SecureMem
    import qualified Data.ByteString as B
    import qualified Data.ByteString.Internal as B

    -- internal functions are not camelCase on purpose
    {-# ANN module "HLint: ignore Use camelCase" #-}

    nettleHashBlockSize  :: NettleHashAlgorithm a => Tagged a Int
    nettleHashBlockSize :: Tagged a Int
    nettleHashBlockSize = Tagged a Int
    forall a. NettleHashAlgorithm a => Tagged a Int
    nha_block_size
    nettleHashDigestSize :: NettleHashAlgorithm a => Tagged a Int
    nettleHashDigestSize :: Tagged a Int
    nettleHashDigestSize = Tagged a Int
    forall a. NettleHashAlgorithm a => Tagged a Int
    nha_digest_size
    nettleHashName       :: NettleHashAlgorithm a => Tagged a String
    nettleHashName :: Tagged a String
    nettleHashName = Tagged a String
    forall a. NettleHashAlgorithm a => Tagged a String
    nha_name
    nettleHashInit       :: NettleHashAlgorithm a => a
    nettleHashInit :: a
    nettleHashInit = Tagged a a -> a
    forall a. Tagged a a -> a
    untagSelf (Tagged a a -> a) -> Tagged a a -> a
    forall a b. (a -> b) -> a -> b
    $ do
    		Int
    size <- Tagged a Int
    forall a. NettleHashAlgorithm a => Tagged a Int
    nha_ctx_size
    		NettleHashInit
    initfun <- Tagged a NettleHashInit
    forall a. NettleHashAlgorithm a => Tagged a NettleHashInit
    nha_init
    		a -> Tagged a a
    forall (m :: * -> *) a. Monad m => a -> m a
    return (a -> Tagged a a) -> a -> Tagged a a
    forall a b. (a -> b) -> a -> b
    $ SecureMem -> a
    forall a. NettleHashAlgorithm a => SecureMem -> a
    nha_Ctx (SecureMem -> a) -> SecureMem -> a
    forall a b. (a -> b) -> a -> b
    $ Int -> NettleHashInit -> SecureMem
    unsafeCreateSecureMem Int
    size (NettleHashInit -> SecureMem) -> NettleHashInit -> SecureMem
    forall a b. (a -> b) -> a -> b
    $ \ctxptr :: Ptr Word8
    ctxptr ->
    			NettleHashInit
    initfun Ptr Word8
    ctxptr
    nettleHashUpdate     :: NettleHashAlgorithm a => a -> B.ByteString -> a
    nettleHashUpdate :: a -> ByteString -> a
    nettleHashUpdate c :: a
    c msg :: ByteString
    msg = Tagged a a -> a
    forall a. Tagged a a -> a
    untagSelf (Tagged a a -> a) -> Tagged a a -> a
    forall a b. (a -> b) -> a -> b
    $ do
    	NettleHashUpdate
    updatefun <- Tagged a NettleHashUpdate
    forall a. NettleHashAlgorithm a => Tagged a NettleHashUpdate
    nha_update
    	a -> Tagged a a
    forall (m :: * -> *) a. Monad m => a -> m a
    return (a -> Tagged a a) -> a -> Tagged a a
    forall a b. (a -> b) -> a -> b
    $ SecureMem -> a
    forall a. NettleHashAlgorithm a => SecureMem -> a
    nha_Ctx (SecureMem -> a) -> SecureMem -> a
    forall a b. (a -> b) -> a -> b
    $ IO SecureMem -> SecureMem
    forall a. IO a -> a
    unsafeDupablePerformIO (IO SecureMem -> SecureMem) -> IO SecureMem -> SecureMem
    forall a b. (a -> b) -> a -> b
    $
    		SecureMem -> NettleHashInit -> IO SecureMem
    withSecureMemCopy (a -> SecureMem
    forall a. NettleHashAlgorithm a => a -> SecureMem
    nha_ctx a
    c) (NettleHashInit -> IO SecureMem) -> NettleHashInit -> IO SecureMem
    forall a b. (a -> b) -> a -> b
    $ \ctxptr :: Ptr Word8
    ctxptr ->
    		ByteString -> (Word -> NettleHashInit) -> IO ()
    forall a. ByteString -> (Word -> Ptr Word8 -> IO a) -> IO a
    withByteStringPtr ByteString
    msg ((Word -> NettleHashInit) -> IO ())
    -> (Word -> NettleHashInit) -> IO ()
    forall a b. (a -> b) -> a -> b
    $ \msglen :: Word
    msglen msgptr :: Ptr Word8
    msgptr ->
    			NettleHashUpdate
    updatefun Ptr Word8
    ctxptr Word
    msglen Ptr Word8
    msgptr
    nettleHashFinalize   :: NettleHashAlgorithm a => a -> B.ByteString
    nettleHashFinalize :: a -> ByteString
    nettleHashFinalize c :: a
    c = (Tagged a ByteString -> a -> ByteString)
    -> a -> Tagged a ByteString -> ByteString
    forall a b c. (a -> b -> c) -> b -> a -> c
    flip Tagged a ByteString -> a -> ByteString
    forall a b. Tagged a b -> a -> b
    witness a
    c (Tagged a ByteString -> ByteString)
    -> Tagged a ByteString -> ByteString
    forall a b. (a -> b) -> a -> b
    $ do
    	Int
    digestSize <- Tagged a Int
    forall a. NettleHashAlgorithm a => Tagged a Int
    nha_digest_size
    	NettleHashUpdate
    digestfun <- Tagged a NettleHashUpdate
    forall a. NettleHashAlgorithm a => Tagged a NettleHashUpdate
    nha_digest
    	ByteString -> Tagged a ByteString
    forall (m :: * -> *) a. Monad m => a -> m a
    return (ByteString -> Tagged a ByteString)
    -> ByteString -> Tagged a ByteString
    forall a b. (a -> b) -> a -> b
    $ IO ByteString -> ByteString
    forall a. IO a -> a
    unsafeDupablePerformIO (IO ByteString -> ByteString) -> IO ByteString -> ByteString
    forall a b. (a -> b) -> a -> b
    $
    		Int -> NettleHashInit -> IO ByteString
    B.create Int
    digestSize (NettleHashInit -> IO ByteString)
    -> NettleHashInit -> IO ByteString
    forall a b. (a -> b) -> a -> b
    $ \digestptr :: Ptr Word8
    digestptr -> do
    			SecureMem
    _ <- SecureMem -> NettleHashInit -> IO SecureMem
    withSecureMemCopy (a -> SecureMem
    forall a. NettleHashAlgorithm a => a -> SecureMem
    nha_ctx a
    c) (NettleHashInit -> IO SecureMem) -> NettleHashInit -> IO SecureMem
    forall a b. (a -> b) -> a -> b
    $ \ctxptr :: Ptr Word8
    ctxptr ->
    				NettleHashUpdate
    digestfun Ptr Word8
    ctxptr (Int -> Word
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral Int
    digestSize) Ptr Word8
    digestptr
    			() -> IO ()
    forall (m :: * -> *) a. Monad m => a -> m a
    return ()

    class NettleHashAlgorithm a where
    	nha_ctx_size    :: Tagged a Int
    	nha_block_size  :: Tagged a Int
    	nha_digest_size :: Tagged a Int
    	nha_name        :: Tagged a String
    	nha_init        :: Tagged a NettleHashInit
    	nha_update      :: Tagged a NettleHashUpdate
    	nha_digest      :: Tagged a NettleHashDigest
    	nha_ctx         :: a -> SecureMem
    	nha_Ctx         :: SecureMem -> a

    #define INSTANCE_HASH(Typ) \
    instance HashAlgorithm Typ where \
    	{ hashBlockSize  = nettleHashBlockSize \
    	; hashDigestSize = nettleHashDigestSize \
    	; hashName       = nettleHashName \
    	; hashInit       = nettleHashInit \
    	; hashUpdate     = nettleHashUpdate \
    	; hashFinalize   = nettleHashFinalize \
    	}

    -- | The GOST94 or GOST R 34.11-94 hash algorithm is a Soviet-era algorithm used in Russian government standards (see RFC 4357).
    --   It outputs message digests of 32 bytes (256 bits).
    data GOSTHASH94 = GOSTHASH94 { GOSTHASH94 -> SecureMem
    gosthash94_ctx :: SecureMem }
    instance NettleHashAlgorithm GOSTHASH94 where
    	nha_ctx_size :: Tagged GOSTHASH94 Int
    nha_ctx_size    = Int -> Tagged GOSTHASH94 Int
    forall k (s :: k) b. b -> Tagged s b
    Tagged Int
    c_gosthash94_ctx_size
    	nha_block_size :: Tagged GOSTHASH94 Int
    nha_block_size  = Int -> Tagged GOSTHASH94 Int
    forall k (s :: k) b. b -> Tagged s b
    Tagged Int
    c_gosthash94_block_size
    	nha_digest_size :: Tagged GOSTHASH94 Int
    nha_digest_size = Int -> Tagged GOSTHASH94 Int
    forall k (s :: k) b. b -> Tagged s b
    Tagged Int
    c_gosthash94_digest_size
    	nha_name :: Tagged GOSTHASH94 String
    nha_name        = String -> Tagged GOSTHASH94 String
    forall k (s :: k) b. b -> Tagged s b
    Tagged "GOSTHAST94"
    	nha_init :: Tagged GOSTHASH94 NettleHashInit
    nha_init        = NettleHashInit -> Tagged GOSTHASH94 NettleHashInit
    forall k (s :: k) b. b -> Tagged s b
    Tagged NettleHashInit
    c_gosthash94_init
    	nha_update :: Tagged GOSTHASH94 NettleHashUpdate
    nha_update      = NettleHashUpdate -> Tagged GOSTHASH94 NettleHashUpdate
    forall k (s :: k) b. b -> Tagged s b
    Tagged NettleHashUpdate
    c_gosthash94_update
    	nha_digest :: Tagged GOSTHASH94 NettleHashUpdate
    nha_digest      = NettleHashUpdate -> Tagged GOSTHASH94 NettleHashUpdate
    forall k (s :: k) b. b -> Tagged s b
    Tagged NettleHashUpdate
    c_gosthash94_digest
    	nha_ctx :: GOSTHASH94 -> SecureMem
    nha_ctx         = GOSTHASH94 -> SecureMem
    gosthash94_ctx
    	nha_Ctx :: SecureMem -> GOSTHASH94
    nha_Ctx         = SecureMem -> GOSTHASH94
    GOSTHASH94
    INSTANCE_HASH(GOSTHASH94)

    -- | 'MD2' is a hash function of Ronald Rivest's, described in RFC 1319. It outputs message digests of 16 bytes (128 bits).
    data MD2 = MD2 { MD2 -> SecureMem
    md2_ctx :: SecureMem }
    instance NettleHashAlgorithm MD2 where
    	nha_ctx_size :: Tagged MD2 Int
    nha_ctx_size    = Int -> Tagged MD2 Int
    forall k (s :: k) b. b -> Tagged s b
    Tagged Int
    c_md2_ctx_size
    	nha_block_size :: Tagged MD2 Int
    nha_block_size  = Int -> Tagged MD2 Int
    forall k (s :: k) b. b -> Tagged s b
    Tagged Int
    c_md2_block_size
    	nha_digest_size :: Tagged MD2 Int
    nha_digest_size = Int -> Tagged MD2 Int
    forall k (s :: k) b. b -> Tagged s b
    Tagged Int
    c_md2_digest_size
    	nha_name :: Tagged MD2 String
    nha_name        = String -> Tagged MD2 String
    forall k (s :: k) b. b -> Tagged s b
    Tagged "MD2"
    	nha_init :: Tagged MD2 NettleHashInit
    nha_init        = NettleHashInit -> Tagged MD2 NettleHashInit
    forall k (s :: k) b. b -> Tagged s b
    Tagged NettleHashInit
    c_md2_init
    	nha_update :: Tagged MD2 NettleHashUpdate
    nha_update      = NettleHashUpdate -> Tagged MD2 NettleHashUpdate
    forall k (s :: k) b. b -> Tagged s b
    Tagged NettleHashUpdate
    c_md2_update
    	nha_digest :: Tagged MD2 NettleHashUpdate
    nha_digest      = NettleHashUpdate -> Tagged MD2 NettleHashUpdate
    forall k (s :: k) b. b -> Tagged s b
    Tagged NettleHashUpdate
    c_md2_digest
    	nha_ctx :: MD2 -> SecureMem
    nha_ctx         = MD2 -> SecureMem
    md2_ctx
    	nha_Ctx :: SecureMem -> MD2
    nha_Ctx         = SecureMem -> MD2
    MD2
    INSTANCE_HASH(MD2)

    -- | 'MD4' is a hash function of Ronald Rivest's, described in RFC 1320. It outputs message digests of 16 bytes (128 bits).
    data MD4 = MD4 { MD4 -> SecureMem
    md4_ctx :: SecureMem }
    instance NettleHashAlgorithm MD4 where
    	nha_ctx_size :: Tagged MD4 Int
    nha_ctx_size    = Int -> Tagged MD4 Int
    forall k (s :: k) b. b -> Tagged s b
    Tagged Int
    c_md4_ctx_size
    	nha_block_size :: Tagged MD4 Int
    nha_block_size  = Int -> Tagged MD4 Int
    forall k (s :: k) b. b -> Tagged s b
    Tagged Int
    c_md4_block_size
    	nha_digest_size :: Tagged MD4 Int
    nha_digest_size = Int -> Tagged MD4 Int
    forall k (s :: k) b. b -> Tagged s b
    Tagged Int
    c_md4_digest_size
    	nha_name :: Tagged MD4 String
    nha_name        = String -> Tagged MD4 String
    forall k (s :: k) b. b -> Tagged s b
    Tagged "MD4"
    	nha_init :: Tagged MD4 NettleHashInit
    nha_init        = NettleHashInit -> Tagged MD4 NettleHashInit
    forall k (s :: k) b. b -> Tagged s b
    Tagged NettleHashInit
    c_md4_init
    	nha_update :: Tagged MD4 NettleHashUpdate
    nha_update      = NettleHashUpdate -> Tagged MD4 NettleHashUpdate
    forall k (s :: k) b. b -> Tagged s b
    Tagged NettleHashUpdate
    c_md4_update
    	nha_digest :: Tagged MD4 NettleHashUpdate
    nha_digest      = NettleHashUpdate -> Tagged MD4 NettleHashUpdate
    forall k (s :: k) b. b -> Tagged s b
    Tagged NettleHashUpdate
    c_md4_digest
    	nha_ctx :: MD4 -> SecureMem
    nha_ctx         = MD4 -> SecureMem
    md4_ctx
    	nha_Ctx :: SecureMem -> MD4
    nha_Ctx         = SecureMem -> MD4
    MD4
    INSTANCE_HASH(MD4)

    -- | 'MD5' is a hash function of Ronald Rivest's, described in RFC 1321. It outputs message digests of 16 bytes (128 bits).
    data MD5 = MD5 { MD5 -> SecureMem
    md5_ctx :: SecureMem }
    instance NettleHashAlgorithm MD5 where
    	nha_ctx_size :: Tagged MD5 Int
    nha_ctx_size    = Int -> Tagged MD5 Int
    forall k (s :: k) b. b -> Tagged s b
    Tagged Int
    c_md5_ctx_size
    	nha_block_size :: Tagged MD5 Int
    nha_block_size  = Int -> Tagged MD5 Int
    forall k (s :: k) b. b -> Tagged s b
    Tagged Int
    c_md5_block_size
    	nha_digest_size :: Tagged MD5 Int
    nha_digest_size = Int -> Tagged MD5 Int
    forall k (s :: k) b. b -> Tagged s b
    Tagged Int
    c_md5_digest_size
    	nha_name :: Tagged MD5 String
    nha_name        = String -> Tagged MD5 String
    forall k (s :: k) b. b -> Tagged s b
    Tagged "MD5"
    	nha_init :: Tagged MD5 NettleHashInit
    nha_init        = NettleHashInit -> Tagged MD5 NettleHashInit
    forall k (s :: k) b. b -> Tagged s b
    Tagged NettleHashInit
    c_md5_init
    	nha_update :: Tagged MD5 NettleHashUpdate
    nha_update      = NettleHashUpdate -> Tagged MD5 NettleHashUpdate
    forall k (s :: k) b. b -> Tagged s b
    Tagged NettleHashUpdate
    c_md5_update
    	nha_digest :: Tagged MD5 NettleHashUpdate
    nha_digest      = NettleHashUpdate -> Tagged MD5 NettleHashUpdate
    forall k (s :: k) b. b -> Tagged s b
    Tagged NettleHashUpdate
    c_md5_digest
    	nha_ctx :: MD5 -> SecureMem
    nha_ctx         = MD5 -> SecureMem
    md5_ctx
    	nha_Ctx :: SecureMem -> MD5
    nha_Ctx         = SecureMem -> MD5
    MD5
    INSTANCE_HASH(MD5)

    -- | 'RIPEMD160' is a hash function designed by Hans Dobbertin, Antoon Bosselaers, and Bart Preneel, as a strengthened version of RIPEMD.
    --   It produces message digests of 20 bytes (160 bits).
    data RIPEMD160 = RIPEMD160 { RIPEMD160 -> SecureMem
    ripemd160_ctx :: SecureMem }
    instance NettleHashAlgorithm RIPEMD160 where
    	nha_ctx_size :: Tagged RIPEMD160 Int
    nha_ctx_size    = Int -> Tagged RIPEMD160 Int
    forall k (s :: k) b. b -> Tagged s b
    Tagged Int
    c_ripemd160_ctx_size
    	nha_block_size :: Tagged RIPEMD160 Int
    nha_block_size  = Int -> Tagged RIPEMD160 Int
    forall k (s :: k) b. b -> Tagged s b
    Tagged Int
    c_ripemd160_block_size
    	nha_digest_size :: Tagged RIPEMD160 Int
    nha_digest_size = Int -> Tagged RIPEMD160 Int
    forall k (s :: k) b. b -> Tagged s b
    Tagged Int
    c_ripemd160_digest_size
    	nha_name :: Tagged RIPEMD160 String
    nha_name        = String -> Tagged RIPEMD160 String
    forall k (s :: k) b. b -> Tagged s b
    Tagged "RIPEMD160"
    	nha_init :: Tagged RIPEMD160 NettleHashInit
    nha_init        = NettleHashInit -> Tagged RIPEMD160 NettleHashInit
    forall k (s :: k) b. b -> Tagged s b
    Tagged NettleHashInit
    c_ripemd160_init
    	nha_update :: Tagged RIPEMD160 NettleHashUpdate
    nha_update      = NettleHashUpdate -> Tagged RIPEMD160 NettleHashUpdate
    forall k (s :: k) b. b -> Tagged s b
    Tagged NettleHashUpdate
    c_ripemd160_update
    	nha_digest :: Tagged RIPEMD160 NettleHashUpdate
    nha_digest      = NettleHashUpdate -> Tagged RIPEMD160 NettleHashUpdate
    forall k (s :: k) b. b -> Tagged s b
    Tagged NettleHashUpdate
    c_ripemd160_digest
    	nha_ctx :: RIPEMD160 -> SecureMem
    nha_ctx         = RIPEMD160 -> SecureMem
    ripemd160_ctx
    	nha_Ctx :: SecureMem -> RIPEMD160
    nha_Ctx         = SecureMem -> RIPEMD160
    RIPEMD160
    INSTANCE_HASH(RIPEMD160)

    -- | 'SHA1' is a hash function specified by NIST (The U.S. National Institute for Standards and Technology).
    --   It produces message digests of 20 bytes (160 bits).
    data SHA1 = SHA1 { SHA1 -> SecureMem
    sha1_ctx :: SecureMem }
    instance NettleHashAlgorithm SHA1 where
    	nha_ctx_size :: Tagged SHA1 Int
    nha_ctx_size    = Int -> Tagged SHA1 Int
    forall k (s :: k) b. b -> Tagged s b
    Tagged Int
    c_sha1_ctx_size
    	nha_block_size :: Tagged SHA1 Int
    nha_block_size  = Int -> Tagged SHA1 Int
    forall k (s :: k) b. b -> Tagged s b
    Tagged Int
    c_sha1_block_size
    	nha_digest_size :: Tagged SHA1 Int
    nha_digest_size = Int -> Tagged SHA1 Int
    forall k (s :: k) b. b -> Tagged s b
    Tagged Int
    c_sha1_digest_size
    	nha_name :: Tagged SHA1 String
    nha_name        = String -> Tagged SHA1 String
    forall k (s :: k) b. b -> Tagged s b
    Tagged "SHA1"
    	nha_init :: Tagged SHA1 NettleHashInit
    nha_init        = NettleHashInit -> Tagged SHA1 NettleHashInit
    forall k (s :: k) b. b -> Tagged s b
    Tagged NettleHashInit
    c_sha1_init
    	nha_update :: Tagged SHA1 NettleHashUpdate
    nha_update      = NettleHashUpdate -> Tagged SHA1 NettleHashUpdate
    forall k (s :: k) b. b -> Tagged s b
    Tagged NettleHashUpdate
    c_sha1_update
    	nha_digest :: Tagged SHA1 NettleHashUpdate
    nha_digest      = NettleHashUpdate -> Tagged SHA1 NettleHashUpdate
    forall k (s :: k) b. b -> Tagged s b
    Tagged NettleHashUpdate
    c_sha1_digest
    	nha_ctx :: SHA1 -> SecureMem
    nha_ctx         = SHA1 -> SecureMem
    sha1_ctx
    	nha_Ctx :: SecureMem -> SHA1
    nha_Ctx         = SecureMem -> SHA1
    SHA1
    INSTANCE_HASH(SHA1)

    -- | 'SHA224' is a member of the SHA2 family which outputs messages digests of 28 bytes (224 bits).
    data SHA224 = SHA224 { SHA224 -> SecureMem
    sha224_ctx :: SecureMem }
    instance NettleHashAlgorithm SHA224 where
    	nha_ctx_size :: Tagged SHA224 Int
    nha_ctx_size    = Int -> Tagged SHA224 Int
    forall k (s :: k) b. b -> Tagged s b
    Tagged Int
    c_sha224_ctx_size
    	nha_block_size :: Tagged SHA224 Int
    nha_block_size  = Int -> Tagged SHA224 Int
    forall k (s :: k) b. b -> Tagged s b
    Tagged Int
    c_sha224_block_size
    	nha_digest_size :: Tagged SHA224 Int
    nha_digest_size = Int -> Tagged SHA224 Int
    forall k (s :: k) b. b -> Tagged s b
    Tagged Int
    c_sha224_digest_size
    	nha_name :: Tagged SHA224 String
    nha_name        = String -> Tagged SHA224 String
    forall k (s :: k) b. b -> Tagged s b
    Tagged "SHA224"
    	nha_init :: Tagged SHA224 NettleHashInit
    nha_init        = NettleHashInit -> Tagged SHA224 NettleHashInit
    forall k (s :: k) b. b -> Tagged s b
    Tagged NettleHashInit
    c_sha224_init
    	nha_update :: Tagged SHA224 NettleHashUpdate
    nha_update      = NettleHashUpdate -> Tagged SHA224 NettleHashUpdate
    forall k (s :: k) b. b -> Tagged s b
    Tagged NettleHashUpdate
    c_sha224_update
    	nha_digest :: Tagged SHA224 NettleHashUpdate
    nha_digest      = NettleHashUpdate -> Tagged SHA224 NettleHashUpdate
    forall k (s :: k) b. b -> Tagged s b
    Tagged NettleHashUpdate
    c_sha224_digest
    	nha_ctx :: SHA224 -> SecureMem
    nha_ctx         = SHA224 -> SecureMem
    sha224_ctx
    	nha_Ctx :: SecureMem -> SHA224
    nha_Ctx         = SecureMem -> SHA224
    SHA224
    INSTANCE_HASH(SHA224)

    -- | 'SHA256' is a member of the SHA2 family which outputs messages digests of 32 bytes (256 bits).
    data SHA256 = SHA256 { SHA256 -> SecureMem
    sha256_ctx :: SecureMem }
    instance NettleHashAlgorithm SHA256 where
    	nha_ctx_size :: Tagged SHA256 Int
    nha_ctx_size    = Int -> Tagged SHA256 Int
    forall k (s :: k) b. b -> Tagged s b
    Tagged Int
    c_sha256_ctx_size
    	nha_block_size :: Tagged SHA256 Int
    nha_block_size  = Int -> Tagged SHA256 Int
    forall k (s :: k) b. b -> Tagged s b
    Tagged Int
    c_sha256_block_size
    	nha_digest_size :: Tagged SHA256 Int
    nha_digest_size = Int -> Tagged SHA256 Int
    forall k (s :: k) b. b -> Tagged s b
    Tagged Int
    c_sha256_digest_size
    	nha_name :: Tagged SHA256 String
    nha_name        = String -> Tagged SHA256 String
    forall k (s :: k) b. b -> Tagged s b
    Tagged "SHA256"
    	nha_init :: Tagged SHA256 NettleHashInit
    nha_init        = NettleHashInit -> Tagged SHA256 NettleHashInit
    forall k (s :: k) b. b -> Tagged s b
    Tagged NettleHashInit
    c_sha256_init
    	nha_update :: Tagged SHA256 NettleHashUpdate
    nha_update      = NettleHashUpdate -> Tagged SHA256 NettleHashUpdate
    forall k (s :: k) b. b -> Tagged s b
    Tagged NettleHashUpdate
    c_sha256_update
    	nha_digest :: Tagged SHA256 NettleHashUpdate
    nha_digest      = NettleHashUpdate -> Tagged SHA256 NettleHashUpdate
    forall k (s :: k) b. b -> Tagged s b
    Tagged NettleHashUpdate
    c_sha256_digest
    	nha_ctx :: SHA256 -> SecureMem
    nha_ctx         = SHA256 -> SecureMem
    sha256_ctx
    	nha_Ctx :: SecureMem -> SHA256
    nha_Ctx         = SecureMem -> SHA256
    SHA256
    INSTANCE_HASH(SHA256)

    -- | 'SHA384' is a member of the SHA2 family which outputs messages digests of 48 bytes (384 bits).
    data SHA384 = SHA384 { SHA384 -> SecureMem
    sha384_ctx :: SecureMem }
    instance NettleHashAlgorithm SHA384 where
    	nha_ctx_size :: Tagged SHA384 Int
    nha_ctx_size    = Int -> Tagged SHA384 Int
    forall k (s :: k) b. b -> Tagged s b
    Tagged Int
    c_sha384_ctx_size
    	nha_block_size :: Tagged SHA384 Int
    nha_block_size  = Int -> Tagged SHA384 Int
    forall k (s :: k) b. b -> Tagged s b
    Tagged Int
    c_sha384_block_size
    	nha_digest_size :: Tagged SHA384 Int
    nha_digest_size = Int -> Tagged SHA384 Int
    forall k (s :: k) b. b -> Tagged s b
    Tagged Int
    c_sha384_digest_size
    	nha_name :: Tagged SHA384 String
    nha_name        = String -> Tagged SHA384 String
    forall k (s :: k) b. b -> Tagged s b
    Tagged "SHA384"
    	nha_init :: Tagged SHA384 NettleHashInit
    nha_init        = NettleHashInit -> Tagged SHA384 NettleHashInit
    forall k (s :: k) b. b -> Tagged s b
    Tagged NettleHashInit
    c_sha384_init
    	nha_update :: Tagged SHA384 NettleHashUpdate
    nha_update      = NettleHashUpdate -> Tagged SHA384 NettleHashUpdate
    forall k (s :: k) b. b -> Tagged s b
    Tagged NettleHashUpdate
    c_sha384_update
    	nha_digest :: Tagged SHA384 NettleHashUpdate
    nha_digest      = NettleHashUpdate -> Tagged SHA384 NettleHashUpdate
    forall k (s :: k) b. b -> Tagged s b
    Tagged NettleHashUpdate
    c_sha384_digest
    	nha_ctx :: SHA384 -> SecureMem
    nha_ctx         = SHA384 -> SecureMem
    sha384_ctx
    	nha_Ctx :: SecureMem -> SHA384
    nha_Ctx         = SecureMem -> SHA384
    SHA384
    INSTANCE_HASH(SHA384)

    -- | 'SHA512' is a member of the SHA2 family which outputs messages digests of 64 bytes (512 bits).
    data SHA512 = SHA512 { SHA512 -> SecureMem
    sha512_ctx :: SecureMem }
    instance NettleHashAlgorithm SHA512 where
    	nha_ctx_size :: Tagged SHA512 Int
    nha_ctx_size    = Int -> Tagged SHA512 Int
    forall k (s :: k) b. b -> Tagged s b
    Tagged Int
    c_sha512_ctx_size
    	nha_block_size :: Tagged SHA512 Int
    nha_block_size  = Int -> Tagged SHA512 Int
    forall k (s :: k) b. b -> Tagged s b
    Tagged Int
    c_sha512_block_size
    	nha_digest_size :: Tagged SHA512 Int
    nha_digest_size = Int -> Tagged SHA512 Int
    forall k (s :: k) b. b -> Tagged s b
    Tagged Int
    c_sha512_digest_size
    	nha_name :: Tagged SHA512 String
    nha_name        = String -> Tagged SHA512 String
    forall k (s :: k) b. b -> Tagged s b
    Tagged "SHA512"
    	nha_init :: Tagged SHA512 NettleHashInit
    nha_init        = NettleHashInit -> Tagged SHA512 NettleHashInit
    forall k (s :: k) b. b -> Tagged s b
    Tagged NettleHashInit
    c_sha512_init
    	nha_update :: Tagged SHA512 NettleHashUpdate
    nha_update      = NettleHashUpdate -> Tagged SHA512 NettleHashUpdate
    forall k (s :: k) b. b -> Tagged s b
    Tagged NettleHashUpdate
    c_sha512_update
    	nha_digest :: Tagged SHA512 NettleHashUpdate
    nha_digest      = NettleHashUpdate -> Tagged SHA512 NettleHashUpdate
    forall k (s :: k) b. b -> Tagged s b
    Tagged NettleHashUpdate
    c_sha512_digest
    	nha_ctx :: SHA512 -> SecureMem
    nha_ctx         = SHA512 -> SecureMem
    sha512_ctx
    	nha_Ctx :: SecureMem -> SHA512
    nha_Ctx         = SecureMem -> SHA512
    SHA512
    INSTANCE_HASH(SHA512)

    -- | 'SHA3_224' is a member of the SHA3 family which outputs messages digests of 28 bytes (224 bits).
    data SHA3_224 = SHA3_224 { SHA3_224 -> SecureMem
    sha3_224_ctx :: SecureMem }
    instance NettleHashAlgorithm SHA3_224 where
    	nha_ctx_size :: Tagged SHA3_224 Int
    nha_ctx_size    = Int -> Tagged SHA3_224 Int
    forall k (s :: k) b. b -> Tagged s b
    Tagged Int
    c_sha3_224_ctx_size
    	nha_block_size :: Tagged SHA3_224 Int
    nha_block_size  = Int -> Tagged SHA3_224 Int
    forall k (s :: k) b. b -> Tagged s b
    Tagged Int
    c_sha3_224_block_size
    	nha_digest_size :: Tagged SHA3_224 Int
    nha_digest_size = Int -> Tagged SHA3_224 Int
    forall k (s :: k) b. b -> Tagged s b
    Tagged Int
    c_sha3_224_digest_size
    	nha_name :: Tagged SHA3_224 String
    nha_name        = String -> Tagged SHA3_224 String
    forall k (s :: k) b. b -> Tagged s b
    Tagged "SHA3-224"
    	nha_init :: Tagged SHA3_224 NettleHashInit
    nha_init        = NettleHashInit -> Tagged SHA3_224 NettleHashInit
    forall k (s :: k) b. b -> Tagged s b
    Tagged NettleHashInit
    c_sha3_224_init
    	nha_update :: Tagged SHA3_224 NettleHashUpdate
    nha_update      = NettleHashUpdate -> Tagged SHA3_224 NettleHashUpdate
    forall k (s :: k) b. b -> Tagged s b
    Tagged NettleHashUpdate
    c_sha3_224_update
    	nha_digest :: Tagged SHA3_224 NettleHashUpdate
    nha_digest      = NettleHashUpdate -> Tagged SHA3_224 NettleHashUpdate
    forall k (s :: k) b. b -> Tagged s b
    Tagged NettleHashUpdate
    c_sha3_224_digest
    	nha_ctx :: SHA3_224 -> SecureMem
    nha_ctx         = SHA3_224 -> SecureMem
    sha3_224_ctx
    	nha_Ctx :: SecureMem -> SHA3_224
    nha_Ctx         = SecureMem -> SHA3_224
    SHA3_224
    INSTANCE_HASH(SHA3_224)

    -- | 'SHA3_256' is a member of the SHA3 family which outputs messages digests of 32 bytes (256 bits).
    data SHA3_256 = SHA3_256 { SHA3_256 -> SecureMem
    sha3_256_ctx :: SecureMem }
    instance NettleHashAlgorithm SHA3_256 where
    	nha_ctx_size :: Tagged SHA3_256 Int
    nha_ctx_size    = Int -> Tagged SHA3_256 Int
    forall k (s :: k) b. b -> Tagged s b
    Tagged Int
    c_sha3_256_ctx_size
    	nha_block_size :: Tagged SHA3_256 Int
    nha_block_size  = Int -> Tagged SHA3_256 Int
    forall k (s :: k) b. b -> Tagged s b
    Tagged Int
    c_sha3_256_block_size
    	nha_digest_size :: Tagged SHA3_256 Int
    nha_digest_size = Int -> Tagged SHA3_256 Int
    forall k (s :: k) b. b -> Tagged s b
    Tagged Int
    c_sha3_256_digest_size
    	nha_name :: Tagged SHA3_256 String
    nha_name        = String -> Tagged SHA3_256 String
    forall k (s :: k) b. b -> Tagged s b
    Tagged "SHA3-256"
    	nha_init :: Tagged SHA3_256 NettleHashInit
    nha_init        = NettleHashInit -> Tagged SHA3_256 NettleHashInit
    forall k (s :: k) b. b -> Tagged s b
    Tagged NettleHashInit
    c_sha3_256_init
    	nha_update :: Tagged SHA3_256 NettleHashUpdate
    nha_update      = NettleHashUpdate -> Tagged SHA3_256 NettleHashUpdate
    forall k (s :: k) b. b -> Tagged s b
    Tagged NettleHashUpdate
    c_sha3_256_update
    	nha_digest :: Tagged SHA3_256 NettleHashUpdate
    nha_digest      = NettleHashUpdate -> Tagged SHA3_256 NettleHashUpdate
    forall k (s :: k) b. b -> Tagged s b
    Tagged NettleHashUpdate
    c_sha3_256_digest
    	nha_ctx :: SHA3_256 -> SecureMem
    nha_ctx         = SHA3_256 -> SecureMem
    sha3_256_ctx
    	nha_Ctx :: SecureMem -> SHA3_256
    nha_Ctx         = SecureMem -> SHA3_256
    SHA3_256
    INSTANCE_HASH(SHA3_256)

    -- | 'SHA3_384' is a member of the SHA3 family which outputs messages digests of 48 bytes (384 bits).
    data SHA3_384 = SHA3_384 { SHA3_384 -> SecureMem
    sha3_384_ctx :: SecureMem }
    instance NettleHashAlgorithm SHA3_384 where
    	nha_ctx_size :: Tagged SHA3_384 Int
    nha_ctx_size    = Int -> Tagged SHA3_384 Int
    forall k (s :: k) b. b -> Tagged s b
    Tagged Int
    c_sha3_384_ctx_size
    	nha_block_size :: Tagged SHA3_384 Int
    nha_block_size  = Int -> Tagged SHA3_384 Int
    forall k (s :: k) b. b -> Tagged s b
    Tagged Int
    c_sha3_384_block_size
    	nha_digest_size :: Tagged SHA3_384 Int
    nha_digest_size = Int -> Tagged SHA3_384 Int
    forall k (s :: k) b. b -> Tagged s b
    Tagged Int
    c_sha3_384_digest_size
    	nha_name :: Tagged SHA3_384 String
    nha_name        = String -> Tagged SHA3_384 String
    forall k (s :: k) b. b -> Tagged s b
    Tagged "SHA3-384"
    	nha_init :: Tagged SHA3_384 NettleHashInit
    nha_init        = NettleHashInit -> Tagged SHA3_384 NettleHashInit
    forall k (s :: k) b. b -> Tagged s b
    Tagged NettleHashInit
    c_sha3_384_init
    	nha_update :: Tagged SHA3_384 NettleHashUpdate
    nha_update      = NettleHashUpdate -> Tagged SHA3_384 NettleHashUpdate
    forall k (s :: k) b. b -> Tagged s b
    Tagged NettleHashUpdate
    c_sha3_384_update
    	nha_digest :: Tagged SHA3_384 NettleHashUpdate
    nha_digest      = NettleHashUpdate -> Tagged SHA3_384 NettleHashUpdate
    forall k (s :: k) b. b -> Tagged s b
    Tagged NettleHashUpdate
    c_sha3_384_digest
    	nha_ctx :: SHA3_384 -> SecureMem
    nha_ctx         = SHA3_384 -> SecureMem
    sha3_384_ctx
    	nha_Ctx :: SecureMem -> SHA3_384
    nha_Ctx         = SecureMem -> SHA3_384
    SHA3_384
    INSTANCE_HASH(SHA3_384)

    -- | 'SHA3_512' is a member of the SHA3 family which outputs messages digests of 64 bytes (512 bits).
    data SHA3_512 = SHA3_512 { SHA3_512 -> SecureMem
    sha3_512_ctx :: SecureMem }
    instance NettleHashAlgorithm SHA3_512 where
    	nha_ctx_size :: Tagged SHA3_512 Int
    nha_ctx_size    = Int -> Tagged SHA3_512 Int
    forall k (s :: k) b. b -> Tagged s b
    Tagged Int
    c_sha3_512_ctx_size
    	nha_block_size :: Tagged SHA3_512 Int
    nha_block_size  = Int -> Tagged SHA3_512 Int
    forall k (s :: k) b. b -> Tagged s b
    Tagged Int
    c_sha3_512_block_size
    	nha_digest_size :: Tagged SHA3_512 Int
    nha_digest_size = Int -> Tagged SHA3_512 Int
    forall k (s :: k) b. b -> Tagged s b
    Tagged Int
    c_sha3_512_digest_size
    	nha_name :: Tagged SHA3_512 String
    nha_name        = String -> Tagged SHA3_512 String
    forall k (s :: k) b. b -> Tagged s b
    Tagged "SHA3-512"
    	nha_init :: Tagged SHA3_512 NettleHashInit
    nha_init        = NettleHashInit -> Tagged SHA3_512 NettleHashInit
    forall k (s :: k) b. b -> Tagged s b
    Tagged NettleHashInit
    c_sha3_512_init
    	nha_update :: Tagged SHA3_512 NettleHashUpdate
    nha_update      = NettleHashUpdate -> Tagged SHA3_512 NettleHashUpdate
    forall k (s :: k) b. b -> Tagged s b
    Tagged NettleHashUpdate
    c_sha3_512_update
    	nha_digest :: Tagged SHA3_512 NettleHashUpdate
    nha_digest      = NettleHashUpdate -> Tagged SHA3_512 NettleHashUpdate
    forall k (s :: k) b. b -> Tagged s b
    Tagged NettleHashUpdate
    c_sha3_512_digest
    	nha_ctx :: SHA3_512 -> SecureMem
    nha_ctx         = SHA3_512 -> SecureMem
    sha3_512_ctx
    	nha_Ctx :: SecureMem -> SHA3_512
    nha_Ctx         = SecureMem -> SHA3_512
    SHA3_512
    INSTANCE_HASH(SHA3_512)