    -----------------------------------------------------------------------------
    -- |
    -- Module      :  Crypto.Skein
    -- Copyright   :  (c) 2011 Felipe A. Lessa
    -- License     :  BSD3 (see LICENSE)
    --
    -- Maintainer  :  felipe.lessa@gmail.com
    -- Stability   :  provisional
    -- Portability :  portable (needs FFI)
    --
    -- High-level interface for the Skein family of hash functions.
    --
    -----------------------------------------------------------------------------

    module Crypto.Skein
        ( -- * Using this module
          -- $usingMod

          -- ** Skein as a cryptographic hash function
          -- $skeinAsHash

          -- ** Skein as a message authentication code (MAC)
          -- $skeinAsMAC

          -- * About Skein
          -- $about

          -- * Main cryptographic hash functions
          -- $mainHash

          -- ** Skein-512-512
          Skein_512_512
        , Skein_512_512_Ctx
          -- ** Skein-1024-1024
        , Skein_1024_1024
        , Skein_1024_1024_Ctx
          -- ** Skein-256-256
        , Skein_256_256
        , Skein_256_256_Ctx

          -- * Skein-MAC
          -- $skeinmac
        , Key
        , skeinMAC
        , skeinMAC'
        , SkeinMAC (skeinMACCtx)

          -- * Other variants of cryptographic hash functions
          -- $variants

          -- ** Skein-256-128
        , Skein_256_128
        , Skein_256_128_Ctx
          -- ** Skein-256-160
        , Skein_256_160
        , Skein_256_160_Ctx
          -- ** Skein-256-224
        , Skein_256_224
        , Skein_256_224_Ctx

          -- * Skein-512

          -- ** Skein-512-128
        , Skein_512_128
        , Skein_512_128_Ctx
          -- ** Skein-512-160
        , Skein_512_160
        , Skein_512_160_Ctx
          -- ** Skein-512-224
        , Skein_512_224
        , Skein_512_224_Ctx
          -- ** Skein-512-256
        , Skein_512_256
        , Skein_512_256_Ctx
          -- ** Skein-512-384
        , Skein_512_384
        , Skein_512_384_Ctx

          -- * Skein-1024

          -- ** Skein-1024-384
        , Skein_1024_384
        , Skein_1024_384_Ctx
          -- ** Skein-1024-512
        , Skein_1024_512
        , Skein_1024_512_Ctx
        ) where

    -- from base
    import Control.Monad (unless)
    import Foreign
    import Foreign.C
    import qualified System.IO.Unsafe as U

    -- from bytestring
    import qualified Data.ByteString as B
    import qualified Data.ByteString.Lazy as L
    import qualified Data.ByteString.Internal as BI
    import qualified Data.ByteString.Unsafe as BU

    -- from cereal
    import Data.Serialize

    -- from tagged
    import Data.Tagged (Tagged(..))

    -- from crypto-api
    import Crypto.Classes

    -- from this package
    import Crypto.Skein.Internal

    ----------------------------------------------------------------------

    -- $usingMod
    --
    -- Currently this module provides both Skein as a cryptographic
    -- hash function and Skein as a MAC.  This module currently does
    -- not provide some Skein functions, such as tree hashing,
    -- pseudo-random number generation, stream ciphing or key
    -- derivation.
    --
    -- Terminology note: we say \"message\" for your variable-sized
    -- data that is given to Skein.

    -- $skeinAsHash
    --
    -- There are many variants of Skein as a cryptographic hash
    -- function.  They are called @Skein_X_Y@, where @X@ is internal
    -- state size in bits and @Y@ is the output size in bits.  The
    -- main ones are 'Skein_512_512', 'Skein_1024_1024' and
    -- 'Skein_256_256'.  If you are unsure, then use 'Skein_512_512'.
    --
    -- To use these data types, you have to use 'Hash' and
    -- 'Serialize'.  Suppose you wanted to hash a lazy 'L.ByteString'
    -- @bs@.  Then you could use
    --
    -- @
    --   digest :: 'S.ByteString'
    --   digest = let h = 'hash' bs :: 'Skein_512_512'
    --            in 'encode' h
    -- @
    --
    -- where 'hash' is from "Crypto.Classes" (@crypto-api@ package),
    -- 'encode' is from 'Serialize' (@cereal@ package) and @digest@
    -- is a strict 'B.ByteString' with the hash.  Given that we've
    -- used 'Skein_512_512' which has an output size of 512 bits,
    -- @digest@ will have @512 / 8 = 64@ bytes of length.

    -- $skeinAsMAC
    --
    -- If you need a message authentication code (MAC), you may use
    -- HMAC with Skein (e.g. HMAC-Skein-512-512).  Using HMAC with
    -- Skein is supported and secure.  However, Skein also supports
    -- another secure method, called Skein-MAC.
    --
    -- Skein-MAC is as secure as HMAC with Skein, however with a much
    -- lower overhead (especially for short messages).  HMAC requires
    -- two hash invocations.  Skein-MAC, on the other hand, requires
    -- just one hash invocation after the setup.
    --
    -- To use Skein-MAC, you need 'skeinMAC' (or 'skeinMAC'') and
    -- 'Serialize'.  You also need a 'Key' with at least as many bits
    -- as the state size you choose (@256@, @512@ or @1024@ bits).
    --
    -- Suppose you want to use Skein-MAC with 'Skein_512_512'.  To
    -- setup the MAC function with a 'Key' @key@ (that has at least
    -- @512 / 8 = 64@ bytes), use
    --
    -- @
    --   let calcMAC :: 'L.ByteString' -> 'Skein_512_512'
    --       calcMAC = 'skeinMAC' key
    -- @
    --
    -- It is recommended to partially apply 'skeinMAC' (or
    -- 'skeinMAC'') to avoid recomputing the key setup.  We give an
    -- explicit type to 'calcMAC' because we have to choose which
    -- Skein we want.
    --
    -- Now, if you want to calculate the Skein-MAC of a lazy
    -- 'L.ByteString' message @msg@, use
    --
    -- @
    --   let msgMAC = 'encode' (calcMAC msg)
    -- @
    --
    -- where 'encode' is from 'Serialize' (@cereal@ package) and
    -- @msgMAC@ is a strict 'B.ByteString' with the MAC.
    --
    -- Now, suppose you are given a @msg'@ with MAC @msgMAC'@ and
    -- want to check the integrity and authenticity of @msg'@.  You
    -- may do so by calculating the MAC of @msg'@ and checking
    -- against @msgMAC'@:
    --
    -- @
    --   let msgMAC'' = 'encode' (calcMAC msg')
    --   in if msgMAC' == msgMAC''
    --      then Right \"Message is okay\"
    --      else Left \"Message has been corrupted or tampered with\"
    -- @

    -- $about
    --
    -- From <http://www.skein-hash.info/about> at 09/2011:
    --
    -- Skein is a new family of cryptographic hash functions. Its
    -- design combines speed, security, simplicity, and a great deal
    -- of flexibility in a modular package that is easy to analyze.
    --
    -- Skein is fast. Skein-512 -- our primary proposal -- hashes data at
    -- 6.1 clock cycles per byte on a 64-bit CPU. This means that on
    -- a 3.1 GHz x64 Core 2 Duo CPU, Skein hashes data at 500
    -- MBytes/second per core -- almost twice as fast as SHA-512 and
    -- three times faster than SHA-256. An optional hash-tree mode
    -- speeds up parallelizable implementations even more. Skein is
    -- fast for short messages, too; Skein-512 hashes short messages
    -- in about 1000 clock cycles.
    --
    -- Skein is secure. Our current best attack on Skein-512 is on 25
    -- of 72 rounds, for a safety factor of 2.9. For comparison, at a
    -- similar stage in the standardization process, the AES
    -- encryption algorithm had an attack on 6 of 10 rounds, for a
    -- safety factor of only 1.7. Additionally, Skein has a number of
    -- provably secure properties, increasing confidence in the
    -- algorithm.
    --
    -- Skein is simple. Using only three primitive operations, the
    -- Skein compression function can be easily understood and
    -- remembered. The rest of the algorithm is a straightforward
    -- iteration of this function.
    --
    -- Skein is flexible. Skein is defined for three different
    -- internal state sizes -- 256 bits, 512 bits, and 1024 bits --
    -- and any output size. This allows Skein to be a drop-in
    -- replacement for the entire SHA family of hash functions. A
    -- completely optional and extendable argument system makes Skein
    -- an efficient tool to use for a very large number of functions:
    -- a PRNG, a stream cipher, a key derivation function,
    -- authentication without the overhead of HMAC, and a
    -- personalization capability. All these features can be
    -- implemented with very low overhead. Together with the
    -- Threefish large-block cipher at Skein core, this design
    -- provides a full set of symmetric cryptographic primitives
    -- suitable for most modern applications.
    --
    -- Skein is efficient on a variety of platforms, both hardware
    -- and software. Skein-512 can be implemented in about 200 bytes
    -- of state. Small devices, such as 8-bit smart cards, can
    -- implement Skein-256 using about 100 bytes of memory. Larger
    -- devices can implement the larger versions of Skein to achieve
    -- faster speeds.
    --
    -- Skein was designed by a team of highly experienced
    -- cryptographic experts from academia and industry, with
    -- expertise in cryptography, security analysis, software, chip
    -- design, and implementation of real-world cryptographic
    -- systems. This breadth of knowledge allowed them to create a
    -- balanced design that works well in all environments.

    -- $mainHash
    --
    -- These are the main Skein hash functions.  Unless you have any
    -- special reasons, you should use one of these.
    --
    --   ['Skein_512_512'] is the primary cryptographic hash function
    --   of this package.  It can safely be used for all current
    --   hashing applications, and should remain secure for the
    --   foreseeable future.
    --
    --   ['Skein_1024_1024'] is the ultra-conservative variant.  Even
    --   if some future attack managed to break 'Skein_512_512', it
    --   is quite likely that 'Skein_1024_1024' would remain secure.
    --
    --   ['Skein_256_256'] is the low-memory variant.  It can be
    --   implemented using 100 bytes of RAM, but this is not the case
    --   with this implementation.  It is faster than 'Skein_512_512'
    --   only for small message lengths, so it's preferable to use
    --   'Skein_512_512'.  If you can't afford 512 bits of output,
    --   you may get the speed advantage of 'Skein_512_512' by using
    --   'Skein_512_256'.

    -- $variants
    --
    -- These hash functions produce less output bits than their state
    -- size.  For example, 'Skein_512_160' produces 160 output bits
    -- while having 512 bits of state size.  Their main use is to be
    -- a drop-in replacement to legacy hash functions.  If you don't
    -- have any special reason for using them, use one of the main
    -- hash functions above (e.g. 'Skein_512_512').
    --
    -- You may replace:
    --
    --   [MD5] with 'Skein_256_128' or 'Skein_512_128'.
    --
    --   [SHA-1] with 'Skein_256_160' or 'Skein_512_160'.
    --
    --   [SHA-224] with 'Skein_256_224' or 'Skein_512_224'.
    --
    --   [SHA-256] with 'Skein_256_256' or 'Skein_512_256'.
    --
    --   [SHA-384] with 'Skein_512_384' or 'Skein_1024_384'.
    --
    --   [SHA-512] with 'Skein_512_512' or 'Skein_1024_512'.

    ----------------------------------------------------------------------

    -- $skeinmac
    --
    -- The standard way to use a hash function for authentication is
    -- to use the HMAC construction.  While you may securely use
    -- Skein with HMAC (e.g. HMAC-Skein-512-512), Skein also supports
    -- another mode for MAC.  Skein-MAC is as secure as
    -- HMAC-Skein, however faster.  Skein-MAC is as fast as
    -- Skein as a hash function, with zero overhead.

    -- | Secret key used to calculate the Skein-MAC.
    --
    -- The 'Key' may have any length.  However, it's recommended to
    -- have at least the same number of bits of the state size.  For
    -- example, when using 'skeinMAC' with 'Skein_512_256', it is
    -- recommended to have a key with at least 64 bytes (512 bits),
    -- which is the state size of 'Skein_512_256' (the first of the
    -- two numbers).
    type Key = B.ByteString

    -- | Class of Skein contexts that may be used for Skein-MAC (all
    -- of them).  Included here mostly for documentation purposes,
    -- since adding new instances is not safe (functions using
    -- 'SkeinMAC' unsurprisingly assume that they are using Skein).
    class SkeinMAC skeinCtx where
        -- | Construct a context @skeinCtx@ given a 'Key'.  This
        -- context may be used with the usual 'Hash' interface to
        -- obtain a message authentication code (MAC).
        --
        -- For a simpler interface, see 'skeinMAC' and 'skeinMAC''.
        skeinMACCtx :: Key -> skeinCtx

    -- | Calculate the Skein-MAC of a lazy 'L.ByteString' given a
    -- 'Key'.  You probably also want to apply 'encode' to get a
    -- 'B.ByteString' out of the @digest@.
    --
    -- This function may be partially applied for increased
    -- performance.  Using a partially applied @skeinMAC@ is as fast
    -- as using Skein as a cryptographic hash function.  So, instead
    -- of
    --
    -- @
    -- let mac1 = skeinMAC key message1
    --     mac2 = skeinMAC key message2
    --     mac3 = skeinMAC key message3
    --     ...
    -- @
    --
    -- write the following code:
    --
    -- @
    -- let calcMAC = skeinMAC key
    --     mac1 = calcMAC message1
    --     mac2 = calcMAC message2
    --     mac3 = calcMAC message3
    --     ...
    -- @
    --
    -- This way the key will be processed only once (with
    -- 'skeinMACCtx').
    skeinMAC :: (SkeinMAC skeinCtx, Hash skeinCtx digest) =>
                Key -> L.ByteString -> digest
    skeinMAC :: forall skeinCtx digest.
    (SkeinMAC skeinCtx, Hash skeinCtx digest) =>
    Key -> ByteString -> digest
    skeinMAC Key
    k = ByteString -> digest
    go
        where
          ctx :: skeinCtx
    ctx = Key -> skeinCtx
    forall skeinCtx. SkeinMAC skeinCtx => Key -> skeinCtx
    skeinMACCtx Key
    k
          go :: ByteString -> digest
    go  = skeinCtx -> [Key] -> digest
    forall {t} {d}. Hash t d => t -> [Key] -> d
    go' skeinCtx
    ctx ([Key] -> digest) -> (ByteString -> [Key]) -> ByteString -> digest
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . ByteString -> [Key]
    L.toChunks
          go' :: t -> [Key] -> d
    go' t
    ctx' []     = t -> Key -> d
    forall ctx d. Hash ctx d => ctx -> Key -> d
    finalize t
    ctx' Key
    B.empty
          go' t
    ctx' [Key
    x]    = t -> Key -> d
    forall ctx d. Hash ctx d => ctx -> Key -> d
    finalize t
    ctx' Key
    x
          go' t
    ctx' (Key
    x:[Key]
    xs) = t -> [Key] -> d
    go' (t -> Key -> t
    forall ctx d. Hash ctx d => ctx -> Key -> ctx
    updateCtx t
    ctx' Key
    x) [Key]
    xs
          -- See the comment below on skeinMAC'.

    -- | Same as 'skeinMAC', however using a strict 'B.ByteString'.
    -- Should be faster for small 'B.ByteString'@s@.
    skeinMAC' :: (SkeinMAC skeinCtx, Hash skeinCtx digest) =>
                 Key -> B.ByteString -> digest
    skeinMAC' :: forall skeinCtx digest.
    (SkeinMAC skeinCtx, Hash skeinCtx digest) =>
    Key -> Key -> digest
    skeinMAC' Key
    k = Key -> digest
    go
        where
          ctx :: skeinCtx
    ctx = Key -> skeinCtx
    forall skeinCtx. SkeinMAC skeinCtx => Key -> skeinCtx
    skeinMACCtx Key
    k
          go :: Key -> digest
    go  = skeinCtx -> Key -> digest
    forall ctx d. Hash ctx d => ctx -> Key -> d
    finalize skeinCtx
    ctx
          -- We can just call 'finalize' because of the way our
          -- implementation works.  Basically, we accept ByteString
          -- of any length on both 'updateCtx' and 'finalize'.
          -- Calling just 'finalize' is more efficient.

    ----------------------------------------------------------------------

    -- | Helper function to create 'initialCtx'.
    initialCtxSkein :: Storable internalCtx =>
                       CSize
                    -> (Ptr internalCtx -> CSize -> IO CInt)
                    -> (internalCtx -> externalCtx)
                    -> externalCtx
    initialCtxSkein :: forall internalCtx externalCtx.
    Storable internalCtx =>
    CSize
    -> (Ptr internalCtx -> CSize -> IO CInt)
    -> (internalCtx -> externalCtx)
    -> externalCtx
    initialCtxSkein CSize
    bits Ptr internalCtx -> CSize -> IO CInt
    init_ internalCtx -> externalCtx
    mkCtx =
        IO externalCtx -> externalCtx
    forall a. IO a -> a
    U.unsafePerformIO (IO externalCtx -> externalCtx) -> IO externalCtx -> externalCtx
    forall a b. (a -> b) -> a -> b
    $
        (Ptr internalCtx -> IO externalCtx) -> IO externalCtx
    forall a b. Storable a => (Ptr a -> IO b) -> IO b
    alloca ((Ptr internalCtx -> IO externalCtx) -> IO externalCtx)
    -> (Ptr internalCtx -> IO externalCtx) -> IO externalCtx
    forall a b. (a -> b) -> a -> b
    $ \Ptr internalCtx
    ctx_ptr -> do
          IO CInt -> IO ()
    check (IO CInt -> IO ()) -> IO CInt -> IO ()
    forall a b. (a -> b) -> a -> b
    $ Ptr internalCtx -> CSize -> IO CInt
    init_ Ptr internalCtx
    ctx_ptr CSize
    bits
          (internalCtx -> externalCtx) -> IO internalCtx -> IO externalCtx
    forall a b. (a -> b) -> IO a -> IO b
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap internalCtx -> externalCtx
    mkCtx (IO internalCtx -> IO externalCtx)
    -> IO internalCtx -> IO externalCtx
    forall a b. (a -> b) -> a -> b
    $ Ptr internalCtx -> IO internalCtx
    forall a. Storable a => Ptr a -> IO a
    peek Ptr internalCtx
    ctx_ptr

    -- | Helper function to create 'updateCtxSkein'.
    updateCtxSkein :: Storable internalCtx =>
                      (Ptr internalCtx -> Ptr Word8 -> CSize -> IO CInt)
                   -> (externalCtx -> internalCtx)
                   -> (internalCtx -> externalCtx)
                   -> (externalCtx -> B.ByteString -> externalCtx)
    updateCtxSkein :: forall internalCtx externalCtx.
    Storable internalCtx =>
    (Ptr internalCtx -> Ptr Word8 -> CSize -> IO CInt)
    -> (externalCtx -> internalCtx)
    -> (internalCtx -> externalCtx)
    -> externalCtx
    -> Key
    -> externalCtx
    updateCtxSkein Ptr internalCtx -> Ptr Word8 -> CSize -> IO CInt
    update externalCtx -> internalCtx
    unCtx internalCtx -> externalCtx
    mkCtx = \externalCtx
    ctx Key
    bs ->
        IO externalCtx -> externalCtx
    forall a. IO a -> a
    U.unsafePerformIO (IO externalCtx -> externalCtx) -> IO externalCtx -> externalCtx
    forall a b. (a -> b) -> a -> b
    $
        Key -> (CStringLen -> IO externalCtx) -> IO externalCtx
    forall a. Key -> (CStringLen -> IO a) -> IO a
    BU.unsafeUseAsCStringLen Key
    bs ((CStringLen -> IO externalCtx) -> IO externalCtx)
    -> (CStringLen -> IO externalCtx) -> IO externalCtx
    forall a b. (a -> b) -> a -> b
    $ \(Ptr CChar
    bs_ptr, Int
    bs_len) ->
        internalCtx
    -> (Ptr internalCtx -> IO externalCtx) -> IO externalCtx
    forall a b. Storable a => a -> (Ptr a -> IO b) -> IO b
    with (externalCtx -> internalCtx
    unCtx externalCtx
    ctx) ((Ptr internalCtx -> IO externalCtx) -> IO externalCtx)
    -> (Ptr internalCtx -> IO externalCtx) -> IO externalCtx
    forall a b. (a -> b) -> a -> b
    $ \Ptr internalCtx
    ctx_ptr -> do
          IO CInt -> IO ()
    check (IO CInt -> IO ()) -> IO CInt -> IO ()
    forall a b. (a -> b) -> a -> b
    $ Ptr internalCtx -> Ptr Word8 -> CSize -> IO CInt
    update Ptr internalCtx
    ctx_ptr (Ptr CChar -> Ptr Word8
    forall a b. Ptr a -> Ptr b
    castPtr Ptr CChar
    bs_ptr) (Int -> CSize
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral Int
    bs_len)
          (internalCtx -> externalCtx) -> IO internalCtx -> IO externalCtx
    forall a b. (a -> b) -> IO a -> IO b
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap internalCtx -> externalCtx
    mkCtx (IO internalCtx -> IO externalCtx)
    -> IO internalCtx -> IO externalCtx
    forall a b. (a -> b) -> a -> b
    $ Ptr internalCtx -> IO internalCtx
    forall a. Storable a => Ptr a -> IO a
    peek Ptr internalCtx
    ctx_ptr

    -- | Helper function to create 'finalize'.
    finalizeSkein :: Storable internalCtx =>
                     Int
                  -> (Ptr internalCtx -> Ptr Word8 -> CSize -> IO CInt)
                  -> (Ptr internalCtx -> Ptr Word8 -> IO CInt)
                  -> (externalCtx -> internalCtx)
                  -> (B.ByteString -> hash)
                  -> (externalCtx -> B.ByteString -> hash)
    finalizeSkein :: forall internalCtx externalCtx hash.
    Storable internalCtx =>
    Int
    -> (Ptr internalCtx -> Ptr Word8 -> CSize -> IO CInt)
    -> (Ptr internalCtx -> Ptr Word8 -> IO CInt)
    -> (externalCtx -> internalCtx)
    -> (Key -> hash)
    -> externalCtx
    -> Key
    -> hash
    finalizeSkein Int
    hashLenBytes Ptr internalCtx -> Ptr Word8 -> CSize -> IO CInt
    update Ptr internalCtx -> Ptr Word8 -> IO CInt
    final externalCtx -> internalCtx
    unCtx Key -> hash
    mkHash = \externalCtx
    ctx Key
    bs ->
        IO hash -> hash
    forall a. IO a -> a
    U.unsafePerformIO (IO hash -> hash) -> IO hash -> hash
    forall a b. (a -> b) -> a -> b
    $
        internalCtx -> (Ptr internalCtx -> IO hash) -> IO hash
    forall a b. Storable a => a -> (Ptr a -> IO b) -> IO b
    with (externalCtx -> internalCtx
    unCtx externalCtx
    ctx) ((Ptr internalCtx -> IO hash) -> IO hash)
    -> (Ptr internalCtx -> IO hash) -> IO hash
    forall a b. (a -> b) -> a -> b
    $ \Ptr internalCtx
    ctx_ptr -> do
          Bool -> IO () -> IO ()
    forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
    unless (Key -> Bool
    B.null Key
    bs) (IO () -> IO ()) -> IO () -> IO ()
    forall a b. (a -> b) -> a -> b
    $
            Key -> (CStringLen -> IO ()) -> IO ()
    forall a. Key -> (CStringLen -> IO a) -> IO a
    BU.unsafeUseAsCStringLen Key
    bs ((CStringLen -> IO ()) -> IO ()) -> (CStringLen -> IO ()) -> IO ()
    forall a b. (a -> b) -> a -> b
    $ \(Ptr CChar
    bs_ptr, Int
    bs_len) ->
              IO CInt -> IO ()
    check (IO CInt -> IO ()) -> IO CInt -> IO ()
    forall a b. (a -> b) -> a -> b
    $ Ptr internalCtx -> Ptr Word8 -> CSize -> IO CInt
    update Ptr internalCtx
    ctx_ptr (Ptr CChar -> Ptr Word8
    forall a b. Ptr a -> Ptr b
    castPtr Ptr CChar
    bs_ptr) (Int -> CSize
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral Int
    bs_len)
          (Key -> hash) -> IO Key -> IO hash
    forall a b. (a -> b) -> IO a -> IO b
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap Key -> hash
    mkHash (IO Key -> IO hash) -> IO Key -> IO hash
    forall a b. (a -> b) -> a -> b
    $ Int -> (Ptr Word8 -> IO ()) -> IO Key
    BI.create Int
    hashLenBytes ((Ptr Word8 -> IO ()) -> IO Key) -> (Ptr Word8 -> IO ()) -> IO Key
    forall a b. (a -> b) -> a -> b
    $ IO CInt -> IO ()
    check (IO CInt -> IO ()) -> (Ptr Word8 -> IO CInt) -> Ptr Word8 -> IO ()
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Ptr internalCtx -> Ptr Word8 -> IO CInt
    final Ptr internalCtx
    ctx_ptr (Ptr Word8 -> IO CInt)
    -> (Ptr Word8 -> Ptr Word8) -> Ptr Word8 -> IO CInt
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Ptr Word8 -> Ptr Word8
    forall a b. Ptr a -> Ptr b
    castPtr

    -- | Helper function to create 'skeinMACCtx'.
    skeinMACCtxSkein :: Storable internalCtx =>
                        CSize
                     -> (Ptr internalCtx -> CSize -> Word64 -> Ptr Word8 -> CSize -> IO CInt)
                     -> (internalCtx -> externalCtx)
                     -> (Key -> externalCtx)
    skeinMACCtxSkein :: forall internalCtx externalCtx.
    Storable internalCtx =>
    CSize
    -> (Ptr internalCtx
        -> CSize -> Word64 -> Ptr Word8 -> CSize -> IO CInt)
    -> (internalCtx -> externalCtx)
    -> Key
    -> externalCtx
    skeinMACCtxSkein CSize
    bits Ptr internalCtx -> CSize -> Word64 -> Ptr Word8 -> CSize -> IO CInt
    initExt internalCtx -> externalCtx
    mkCtx = \Key
    key ->
        IO externalCtx -> externalCtx
    forall a. IO a -> a
    U.unsafePerformIO (IO externalCtx -> externalCtx) -> IO externalCtx -> externalCtx
    forall a b. (a -> b) -> a -> b
    $
        Key -> (CStringLen -> IO externalCtx) -> IO externalCtx
    forall a. Key -> (CStringLen -> IO a) -> IO a
    BU.unsafeUseAsCStringLen Key
    key ((CStringLen -> IO externalCtx) -> IO externalCtx)
    -> (CStringLen -> IO externalCtx) -> IO externalCtx
    forall a b. (a -> b) -> a -> b
    $ \(Ptr CChar
    key_ptr, Int
    key_len) ->
        (Ptr internalCtx -> IO externalCtx) -> IO externalCtx
    forall a b. Storable a => (Ptr a -> IO b) -> IO b
    alloca ((Ptr internalCtx -> IO externalCtx) -> IO externalCtx)
    -> (Ptr internalCtx -> IO externalCtx) -> IO externalCtx
    forall a b. (a -> b) -> a -> b
    $ \Ptr internalCtx
    ctx_ptr -> do
          IO CInt -> IO ()
    check (IO CInt -> IO ()) -> IO CInt -> IO ()
    forall a b. (a -> b) -> a -> b
    $ Ptr internalCtx -> CSize -> Word64 -> Ptr Word8 -> CSize -> IO CInt
    initExt Ptr internalCtx
    ctx_ptr CSize
    bits Word64
    sKEIN_SEQUENTIAL (Ptr CChar -> Ptr Word8
    forall a b. Ptr a -> Ptr b
    castPtr Ptr CChar
    key_ptr) (Int -> CSize
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral Int
    key_len)
          (internalCtx -> externalCtx) -> IO internalCtx -> IO externalCtx
    forall a b. (a -> b) -> IO a -> IO b
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap internalCtx -> externalCtx
    mkCtx (IO internalCtx -> IO externalCtx)
    -> IO internalCtx -> IO externalCtx
    forall a b. (a -> b) -> a -> b
    $ Ptr internalCtx -> IO internalCtx
    forall a. Storable a => Ptr a -> IO a
    peek Ptr internalCtx
    ctx_ptr

    ----------------------------------------------------------------------
    -- Skein-256
    ----------------------------------------------------------------------

    -- | Context of the Skein-256-128 hash function.
    newtype Skein_256_128_Ctx = S_256_128_Ctx {Skein_256_128_Ctx -> Skein256Ctx
    unS_256_128_Ctx :: Skein256Ctx}

    -- | Skein-256-128 hash.  You probably want to use 'encode' to
    -- obtain a 128-bit (16-byte) 'B.ByteString'.  May be used as a
    -- drop-in replacement for MD5.
    newtype Skein_256_128 = S_256_128 B.ByteString deriving (Skein_256_128 -> Skein_256_128 -> Bool
    (Skein_256_128 -> Skein_256_128 -> Bool)
    -> (Skein_256_128 -> Skein_256_128 -> Bool) -> Eq Skein_256_128
    forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
    $c== :: Skein_256_128 -> Skein_256_128 -> Bool
    == :: Skein_256_128 -> Skein_256_128 -> Bool
    $c/= :: Skein_256_128 -> Skein_256_128 -> Bool
    /= :: Skein_256_128 -> Skein_256_128 -> Bool
    Eq, Eq Skein_256_128
    Eq Skein_256_128 =>
    (Skein_256_128 -> Skein_256_128 -> Ordering)
    -> (Skein_256_128 -> Skein_256_128 -> Bool)
    -> (Skein_256_128 -> Skein_256_128 -> Bool)
    -> (Skein_256_128 -> Skein_256_128 -> Bool)
    -> (Skein_256_128 -> Skein_256_128 -> Bool)
    -> (Skein_256_128 -> Skein_256_128 -> Skein_256_128)
    -> (Skein_256_128 -> Skein_256_128 -> Skein_256_128)
    -> Ord Skein_256_128
    Skein_256_128 -> Skein_256_128 -> Bool
    Skein_256_128 -> Skein_256_128 -> Ordering
    Skein_256_128 -> Skein_256_128 -> Skein_256_128
    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 :: Skein_256_128 -> Skein_256_128 -> Ordering
    compare :: Skein_256_128 -> Skein_256_128 -> Ordering
    $c< :: Skein_256_128 -> Skein_256_128 -> Bool
    < :: Skein_256_128 -> Skein_256_128 -> Bool
    $c<= :: Skein_256_128 -> Skein_256_128 -> Bool
    <= :: Skein_256_128 -> Skein_256_128 -> Bool
    $c> :: Skein_256_128 -> Skein_256_128 -> Bool
    > :: Skein_256_128 -> Skein_256_128 -> Bool
    $c>= :: Skein_256_128 -> Skein_256_128 -> Bool
    >= :: Skein_256_128 -> Skein_256_128 -> Bool
    $cmax :: Skein_256_128 -> Skein_256_128 -> Skein_256_128
    max :: Skein_256_128 -> Skein_256_128 -> Skein_256_128
    $cmin :: Skein_256_128 -> Skein_256_128 -> Skein_256_128
    min :: Skein_256_128 -> Skein_256_128 -> Skein_256_128
    Ord)

    instance Serialize Skein_256_128 where
        put :: Putter Skein_256_128
    put (S_256_128 Key
    bs) = Putter Key
    putByteString Key
    bs
        get :: Get Skein_256_128
    get = (Key -> Skein_256_128) -> Get Key -> Get Skein_256_128
    forall a b. (a -> b) -> Get a -> Get b
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap Key -> Skein_256_128
    S_256_128 (Get Key -> Get Skein_256_128) -> Get Key -> Get Skein_256_128
    forall a b. (a -> b) -> a -> b
    $ Int -> Get Key
    getByteString Int
    16

    instance Hash Skein_256_128_Ctx Skein_256_128 where
        outputLength :: Tagged Skein_256_128 Int
    outputLength = Int -> Tagged Skein_256_128 Int
    forall {k} (s :: k) b. b -> Tagged s b
    Tagged Int
    128
        blockLength :: Tagged Skein_256_128 Int
    blockLength  = Int -> Tagged Skein_256_128 Int
    forall {k} (s :: k) b. b -> Tagged s b
    Tagged Int
    256
        initialCtx :: Skein_256_128_Ctx
    initialCtx   = CSize
    -> (Ptr Skein256Ctx -> CSize -> IO CInt)
    -> (Skein256Ctx -> Skein_256_128_Ctx)
    -> Skein_256_128_Ctx
    forall internalCtx externalCtx.
    Storable internalCtx =>
    CSize
    -> (Ptr internalCtx -> CSize -> IO CInt)
    -> (internalCtx -> externalCtx)
    -> externalCtx
    initialCtxSkein CSize
    128 Ptr Skein256Ctx -> CSize -> IO CInt
    skein256Init Skein256Ctx -> Skein_256_128_Ctx
    S_256_128_Ctx
        updateCtx :: Skein_256_128_Ctx -> Key -> Skein_256_128_Ctx
    updateCtx    = (Ptr Skein256Ctx -> Ptr Word8 -> CSize -> IO CInt)
    -> (Skein_256_128_Ctx -> Skein256Ctx)
    -> (Skein256Ctx -> Skein_256_128_Ctx)
    -> Skein_256_128_Ctx
    -> Key
    -> Skein_256_128_Ctx
    forall internalCtx externalCtx.
    Storable internalCtx =>
    (Ptr internalCtx -> Ptr Word8 -> CSize -> IO CInt)
    -> (externalCtx -> internalCtx)
    -> (internalCtx -> externalCtx)
    -> externalCtx
    -> Key
    -> externalCtx
    updateCtxSkein Ptr Skein256Ctx -> Ptr Word8 -> CSize -> IO CInt
    skein256Update Skein_256_128_Ctx -> Skein256Ctx
    unS_256_128_Ctx Skein256Ctx -> Skein_256_128_Ctx
    S_256_128_Ctx
        finalize :: Skein_256_128_Ctx -> Key -> Skein_256_128
    finalize     = Int
    -> (Ptr Skein256Ctx -> Ptr Word8 -> CSize -> IO CInt)
    -> (Ptr Skein256Ctx -> Ptr Word8 -> IO CInt)
    -> (Skein_256_128_Ctx -> Skein256Ctx)
    -> (Key -> Skein_256_128)
    -> Skein_256_128_Ctx
    -> Key
    -> Skein_256_128
    forall internalCtx externalCtx hash.
    Storable internalCtx =>
    Int
    -> (Ptr internalCtx -> Ptr Word8 -> CSize -> IO CInt)
    -> (Ptr internalCtx -> Ptr Word8 -> IO CInt)
    -> (externalCtx -> internalCtx)
    -> (Key -> hash)
    -> externalCtx
    -> Key
    -> hash
    finalizeSkein Int
    16 Ptr Skein256Ctx -> Ptr Word8 -> CSize -> IO CInt
    skein256Update Ptr Skein256Ctx -> Ptr Word8 -> IO CInt
    skein256Final Skein_256_128_Ctx -> Skein256Ctx
    unS_256_128_Ctx Key -> Skein_256_128
    S_256_128

    instance SkeinMAC Skein_256_128_Ctx where
        skeinMACCtx :: Key -> Skein_256_128_Ctx
    skeinMACCtx = CSize
    -> (Ptr Skein256Ctx
        -> CSize -> Word64 -> Ptr Word8 -> CSize -> IO CInt)
    -> (Skein256Ctx -> Skein_256_128_Ctx)
    -> Key
    -> Skein_256_128_Ctx
    forall internalCtx externalCtx.
    Storable internalCtx =>
    CSize
    -> (Ptr internalCtx
        -> CSize -> Word64 -> Ptr Word8 -> CSize -> IO CInt)
    -> (internalCtx -> externalCtx)
    -> Key
    -> externalCtx
    skeinMACCtxSkein CSize
    128 Ptr Skein256Ctx -> CSize -> Word64 -> Ptr Word8 -> CSize -> IO CInt
    skein256InitExt Skein256Ctx -> Skein_256_128_Ctx
    S_256_128_Ctx

    -- | Context of the Skein-256-160 hash function.
    newtype Skein_256_160_Ctx = S_256_160_Ctx {Skein_256_160_Ctx -> Skein256Ctx
    unS_256_160_Ctx :: Skein256Ctx}

    -- | Skein-256-160 hash.  You probably want to use 'encode' to
    -- obtain a 160-bit (20-byte) 'B.ByteString'.  May be used as a
    -- drop-in replacement for SHA-1.
    newtype Skein_256_160 = S_256_160 B.ByteString deriving (Skein_256_160 -> Skein_256_160 -> Bool
    (Skein_256_160 -> Skein_256_160 -> Bool)
    -> (Skein_256_160 -> Skein_256_160 -> Bool) -> Eq Skein_256_160
    forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
    $c== :: Skein_256_160 -> Skein_256_160 -> Bool
    == :: Skein_256_160 -> Skein_256_160 -> Bool
    $c/= :: Skein_256_160 -> Skein_256_160 -> Bool
    /= :: Skein_256_160 -> Skein_256_160 -> Bool
    Eq, Eq Skein_256_160
    Eq Skein_256_160 =>
    (Skein_256_160 -> Skein_256_160 -> Ordering)
    -> (Skein_256_160 -> Skein_256_160 -> Bool)
    -> (Skein_256_160 -> Skein_256_160 -> Bool)
    -> (Skein_256_160 -> Skein_256_160 -> Bool)
    -> (Skein_256_160 -> Skein_256_160 -> Bool)
    -> (Skein_256_160 -> Skein_256_160 -> Skein_256_160)
    -> (Skein_256_160 -> Skein_256_160 -> Skein_256_160)
    -> Ord Skein_256_160
    Skein_256_160 -> Skein_256_160 -> Bool
    Skein_256_160 -> Skein_256_160 -> Ordering
    Skein_256_160 -> Skein_256_160 -> Skein_256_160
    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 :: Skein_256_160 -> Skein_256_160 -> Ordering
    compare :: Skein_256_160 -> Skein_256_160 -> Ordering
    $c< :: Skein_256_160 -> Skein_256_160 -> Bool
    < :: Skein_256_160 -> Skein_256_160 -> Bool
    $c<= :: Skein_256_160 -> Skein_256_160 -> Bool
    <= :: Skein_256_160 -> Skein_256_160 -> Bool
    $c> :: Skein_256_160 -> Skein_256_160 -> Bool
    > :: Skein_256_160 -> Skein_256_160 -> Bool
    $c>= :: Skein_256_160 -> Skein_256_160 -> Bool
    >= :: Skein_256_160 -> Skein_256_160 -> Bool
    $cmax :: Skein_256_160 -> Skein_256_160 -> Skein_256_160
    max :: Skein_256_160 -> Skein_256_160 -> Skein_256_160
    $cmin :: Skein_256_160 -> Skein_256_160 -> Skein_256_160
    min :: Skein_256_160 -> Skein_256_160 -> Skein_256_160
    Ord)

    instance Serialize Skein_256_160 where
        put :: Putter Skein_256_160
    put (S_256_160 Key
    bs) = Putter Key
    putByteString Key
    bs
        get :: Get Skein_256_160
    get = (Key -> Skein_256_160) -> Get Key -> Get Skein_256_160
    forall a b. (a -> b) -> Get a -> Get b
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap Key -> Skein_256_160
    S_256_160 (Get Key -> Get Skein_256_160) -> Get Key -> Get Skein_256_160
    forall a b. (a -> b) -> a -> b
    $ Int -> Get Key
    getByteString Int
    20

    instance Hash Skein_256_160_Ctx Skein_256_160 where
        outputLength :: Tagged Skein_256_160 Int
    outputLength = Int -> Tagged Skein_256_160 Int
    forall {k} (s :: k) b. b -> Tagged s b
    Tagged Int
    160
        blockLength :: Tagged Skein_256_160 Int
    blockLength  = Int -> Tagged Skein_256_160 Int
    forall {k} (s :: k) b. b -> Tagged s b
    Tagged Int
    256
        initialCtx :: Skein_256_160_Ctx
    initialCtx   = CSize
    -> (Ptr Skein256Ctx -> CSize -> IO CInt)
    -> (Skein256Ctx -> Skein_256_160_Ctx)
    -> Skein_256_160_Ctx
    forall internalCtx externalCtx.
    Storable internalCtx =>
    CSize
    -> (Ptr internalCtx -> CSize -> IO CInt)
    -> (internalCtx -> externalCtx)
    -> externalCtx
    initialCtxSkein CSize
    160 Ptr Skein256Ctx -> CSize -> IO CInt
    skein256Init Skein256Ctx -> Skein_256_160_Ctx
    S_256_160_Ctx
        updateCtx :: Skein_256_160_Ctx -> Key -> Skein_256_160_Ctx
    updateCtx    = (Ptr Skein256Ctx -> Ptr Word8 -> CSize -> IO CInt)
    -> (Skein_256_160_Ctx -> Skein256Ctx)
    -> (Skein256Ctx -> Skein_256_160_Ctx)
    -> Skein_256_160_Ctx
    -> Key
    -> Skein_256_160_Ctx
    forall internalCtx externalCtx.
    Storable internalCtx =>
    (Ptr internalCtx -> Ptr Word8 -> CSize -> IO CInt)
    -> (externalCtx -> internalCtx)
    -> (internalCtx -> externalCtx)
    -> externalCtx
    -> Key
    -> externalCtx
    updateCtxSkein Ptr Skein256Ctx -> Ptr Word8 -> CSize -> IO CInt
    skein256Update Skein_256_160_Ctx -> Skein256Ctx
    unS_256_160_Ctx Skein256Ctx -> Skein_256_160_Ctx
    S_256_160_Ctx
        finalize :: Skein_256_160_Ctx -> Key -> Skein_256_160
    finalize     = Int
    -> (Ptr Skein256Ctx -> Ptr Word8 -> CSize -> IO CInt)
    -> (Ptr Skein256Ctx -> Ptr Word8 -> IO CInt)
    -> (Skein_256_160_Ctx -> Skein256Ctx)
    -> (Key -> Skein_256_160)
    -> Skein_256_160_Ctx
    -> Key
    -> Skein_256_160
    forall internalCtx externalCtx hash.
    Storable internalCtx =>
    Int
    -> (Ptr internalCtx -> Ptr Word8 -> CSize -> IO CInt)
    -> (Ptr internalCtx -> Ptr Word8 -> IO CInt)
    -> (externalCtx -> internalCtx)
    -> (Key -> hash)
    -> externalCtx
    -> Key
    -> hash
    finalizeSkein Int
    20 Ptr Skein256Ctx -> Ptr Word8 -> CSize -> IO CInt
    skein256Update Ptr Skein256Ctx -> Ptr Word8 -> IO CInt
    skein256Final Skein_256_160_Ctx -> Skein256Ctx
    unS_256_160_Ctx Key -> Skein_256_160
    S_256_160

    instance SkeinMAC Skein_256_160_Ctx where
        skeinMACCtx :: Key -> Skein_256_160_Ctx
    skeinMACCtx = CSize
    -> (Ptr Skein256Ctx
        -> CSize -> Word64 -> Ptr Word8 -> CSize -> IO CInt)
    -> (Skein256Ctx -> Skein_256_160_Ctx)
    -> Key
    -> Skein_256_160_Ctx
    forall internalCtx externalCtx.
    Storable internalCtx =>
    CSize
    -> (Ptr internalCtx
        -> CSize -> Word64 -> Ptr Word8 -> CSize -> IO CInt)
    -> (internalCtx -> externalCtx)
    -> Key
    -> externalCtx
    skeinMACCtxSkein CSize
    160 Ptr Skein256Ctx -> CSize -> Word64 -> Ptr Word8 -> CSize -> IO CInt
    skein256InitExt Skein256Ctx -> Skein_256_160_Ctx
    S_256_160_Ctx

    -- | Context of the Skein-256-224 hash function.
    newtype Skein_256_224_Ctx = S_256_224_Ctx {Skein_256_224_Ctx -> Skein256Ctx
    unS_256_224_Ctx :: Skein256Ctx}

    -- | Skein-256-224 hash.  You probably want to use 'encode' to
    -- obtain a 224-bit (28-byte) 'B.ByteString'.  May be used as a
    -- drop-in replacement for SHA-224.
    newtype Skein_256_224 = S_256_224 B.ByteString deriving (Skein_256_224 -> Skein_256_224 -> Bool
    (Skein_256_224 -> Skein_256_224 -> Bool)
    -> (Skein_256_224 -> Skein_256_224 -> Bool) -> Eq Skein_256_224
    forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
    $c== :: Skein_256_224 -> Skein_256_224 -> Bool
    == :: Skein_256_224 -> Skein_256_224 -> Bool
    $c/= :: Skein_256_224 -> Skein_256_224 -> Bool
    /= :: Skein_256_224 -> Skein_256_224 -> Bool
    Eq, Eq Skein_256_224
    Eq Skein_256_224 =>
    (Skein_256_224 -> Skein_256_224 -> Ordering)
    -> (Skein_256_224 -> Skein_256_224 -> Bool)
    -> (Skein_256_224 -> Skein_256_224 -> Bool)
    -> (Skein_256_224 -> Skein_256_224 -> Bool)
    -> (Skein_256_224 -> Skein_256_224 -> Bool)
    -> (Skein_256_224 -> Skein_256_224 -> Skein_256_224)
    -> (Skein_256_224 -> Skein_256_224 -> Skein_256_224)
    -> Ord Skein_256_224
    Skein_256_224 -> Skein_256_224 -> Bool
    Skein_256_224 -> Skein_256_224 -> Ordering
    Skein_256_224 -> Skein_256_224 -> Skein_256_224
    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 :: Skein_256_224 -> Skein_256_224 -> Ordering
    compare :: Skein_256_224 -> Skein_256_224 -> Ordering
    $c< :: Skein_256_224 -> Skein_256_224 -> Bool
    < :: Skein_256_224 -> Skein_256_224 -> Bool
    $c<= :: Skein_256_224 -> Skein_256_224 -> Bool
    <= :: Skein_256_224 -> Skein_256_224 -> Bool
    $c> :: Skein_256_224 -> Skein_256_224 -> Bool
    > :: Skein_256_224 -> Skein_256_224 -> Bool
    $c>= :: Skein_256_224 -> Skein_256_224 -> Bool
    >= :: Skein_256_224 -> Skein_256_224 -> Bool
    $cmax :: Skein_256_224 -> Skein_256_224 -> Skein_256_224
    max :: Skein_256_224 -> Skein_256_224 -> Skein_256_224
    $cmin :: Skein_256_224 -> Skein_256_224 -> Skein_256_224
    min :: Skein_256_224 -> Skein_256_224 -> Skein_256_224
    Ord)

    instance Serialize Skein_256_224 where
        put :: Putter Skein_256_224
    put (S_256_224 Key
    bs) = Putter Key
    putByteString Key
    bs
        get :: Get Skein_256_224
    get = (Key -> Skein_256_224) -> Get Key -> Get Skein_256_224
    forall a b. (a -> b) -> Get a -> Get b
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap Key -> Skein_256_224
    S_256_224 (Get Key -> Get Skein_256_224) -> Get Key -> Get Skein_256_224
    forall a b. (a -> b) -> a -> b
    $ Int -> Get Key
    getByteString Int
    28

    instance Hash Skein_256_224_Ctx Skein_256_224 where
        outputLength :: Tagged Skein_256_224 Int
    outputLength = Int -> Tagged Skein_256_224 Int
    forall {k} (s :: k) b. b -> Tagged s b
    Tagged Int
    224
        blockLength :: Tagged Skein_256_224 Int
    blockLength  = Int -> Tagged Skein_256_224 Int
    forall {k} (s :: k) b. b -> Tagged s b
    Tagged Int
    256
        initialCtx :: Skein_256_224_Ctx
    initialCtx   = CSize
    -> (Ptr Skein256Ctx -> CSize -> IO CInt)
    -> (Skein256Ctx -> Skein_256_224_Ctx)
    -> Skein_256_224_Ctx
    forall internalCtx externalCtx.
    Storable internalCtx =>
    CSize
    -> (Ptr internalCtx -> CSize -> IO CInt)
    -> (internalCtx -> externalCtx)
    -> externalCtx
    initialCtxSkein CSize
    224 Ptr Skein256Ctx -> CSize -> IO CInt
    skein256Init Skein256Ctx -> Skein_256_224_Ctx
    S_256_224_Ctx
        updateCtx :: Skein_256_224_Ctx -> Key -> Skein_256_224_Ctx
    updateCtx    = (Ptr Skein256Ctx -> Ptr Word8 -> CSize -> IO CInt)
    -> (Skein_256_224_Ctx -> Skein256Ctx)
    -> (Skein256Ctx -> Skein_256_224_Ctx)
    -> Skein_256_224_Ctx
    -> Key
    -> Skein_256_224_Ctx
    forall internalCtx externalCtx.
    Storable internalCtx =>
    (Ptr internalCtx -> Ptr Word8 -> CSize -> IO CInt)
    -> (externalCtx -> internalCtx)
    -> (internalCtx -> externalCtx)
    -> externalCtx
    -> Key
    -> externalCtx
    updateCtxSkein Ptr Skein256Ctx -> Ptr Word8 -> CSize -> IO CInt
    skein256Update Skein_256_224_Ctx -> Skein256Ctx
    unS_256_224_Ctx Skein256Ctx -> Skein_256_224_Ctx
    S_256_224_Ctx
        finalize :: Skein_256_224_Ctx -> Key -> Skein_256_224
    finalize     = Int
    -> (Ptr Skein256Ctx -> Ptr Word8 -> CSize -> IO CInt)
    -> (Ptr Skein256Ctx -> Ptr Word8 -> IO CInt)
    -> (Skein_256_224_Ctx -> Skein256Ctx)
    -> (Key -> Skein_256_224)
    -> Skein_256_224_Ctx
    -> Key
    -> Skein_256_224
    forall internalCtx externalCtx hash.
    Storable internalCtx =>
    Int
    -> (Ptr internalCtx -> Ptr Word8 -> CSize -> IO CInt)
    -> (Ptr internalCtx -> Ptr Word8 -> IO CInt)
    -> (externalCtx -> internalCtx)
    -> (Key -> hash)
    -> externalCtx
    -> Key
    -> hash
    finalizeSkein Int
    28 Ptr Skein256Ctx -> Ptr Word8 -> CSize -> IO CInt
    skein256Update Ptr Skein256Ctx -> Ptr Word8 -> IO CInt
    skein256Final Skein_256_224_Ctx -> Skein256Ctx
    unS_256_224_Ctx Key -> Skein_256_224
    S_256_224

    instance SkeinMAC Skein_256_224_Ctx where
        skeinMACCtx :: Key -> Skein_256_224_Ctx
    skeinMACCtx = CSize
    -> (Ptr Skein256Ctx
        -> CSize -> Word64 -> Ptr Word8 -> CSize -> IO CInt)
    -> (Skein256Ctx -> Skein_256_224_Ctx)
    -> Key
    -> Skein_256_224_Ctx
    forall internalCtx externalCtx.
    Storable internalCtx =>
    CSize
    -> (Ptr internalCtx
        -> CSize -> Word64 -> Ptr Word8 -> CSize -> IO CInt)
    -> (internalCtx -> externalCtx)
    -> Key
    -> externalCtx
    skeinMACCtxSkein CSize
    224 Ptr Skein256Ctx -> CSize -> Word64 -> Ptr Word8 -> CSize -> IO CInt
    skein256InitExt Skein256Ctx -> Skein_256_224_Ctx
    S_256_224_Ctx

    -- | Context of the Skein-256-256 hash function.
    newtype Skein_256_256_Ctx = S_256_256_Ctx {Skein_256_256_Ctx -> Skein256Ctx
    unS_256_256_Ctx :: Skein256Ctx}

    -- | Skein-256-256 hash.  You probably want to use 'encode' to
    -- obtain a 256-bit (32-byte) 'B.ByteString'.  Usually it's better
    -- to use 'Skein_512_256' (256 bits of output) or 'Skein_512_512'
    -- (512 bits of output).
    newtype Skein_256_256 = S_256_256 B.ByteString deriving (Skein_256_256 -> Skein_256_256 -> Bool
    (Skein_256_256 -> Skein_256_256 -> Bool)
    -> (Skein_256_256 -> Skein_256_256 -> Bool) -> Eq Skein_256_256
    forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
    $c== :: Skein_256_256 -> Skein_256_256 -> Bool
    == :: Skein_256_256 -> Skein_256_256 -> Bool
    $c/= :: Skein_256_256 -> Skein_256_256 -> Bool
    /= :: Skein_256_256 -> Skein_256_256 -> Bool
    Eq, Eq Skein_256_256
    Eq Skein_256_256 =>
    (Skein_256_256 -> Skein_256_256 -> Ordering)
    -> (Skein_256_256 -> Skein_256_256 -> Bool)
    -> (Skein_256_256 -> Skein_256_256 -> Bool)
    -> (Skein_256_256 -> Skein_256_256 -> Bool)
    -> (Skein_256_256 -> Skein_256_256 -> Bool)
    -> (Skein_256_256 -> Skein_256_256 -> Skein_256_256)
    -> (Skein_256_256 -> Skein_256_256 -> Skein_256_256)
    -> Ord Skein_256_256
    Skein_256_256 -> Skein_256_256 -> Bool
    Skein_256_256 -> Skein_256_256 -> Ordering
    Skein_256_256 -> Skein_256_256 -> Skein_256_256
    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 :: Skein_256_256 -> Skein_256_256 -> Ordering
    compare :: Skein_256_256 -> Skein_256_256 -> Ordering
    $c< :: Skein_256_256 -> Skein_256_256 -> Bool
    < :: Skein_256_256 -> Skein_256_256 -> Bool
    $c<= :: Skein_256_256 -> Skein_256_256 -> Bool
    <= :: Skein_256_256 -> Skein_256_256 -> Bool
    $c> :: Skein_256_256 -> Skein_256_256 -> Bool
    > :: Skein_256_256 -> Skein_256_256 -> Bool
    $c>= :: Skein_256_256 -> Skein_256_256 -> Bool
    >= :: Skein_256_256 -> Skein_256_256 -> Bool
    $cmax :: Skein_256_256 -> Skein_256_256 -> Skein_256_256
    max :: Skein_256_256 -> Skein_256_256 -> Skein_256_256
    $cmin :: Skein_256_256 -> Skein_256_256 -> Skein_256_256
    min :: Skein_256_256 -> Skein_256_256 -> Skein_256_256
    Ord)

    instance Serialize Skein_256_256 where
        put :: Putter Skein_256_256
    put (S_256_256 Key
    bs) = Putter Key
    putByteString Key
    bs
        get :: Get Skein_256_256
    get = (Key -> Skein_256_256) -> Get Key -> Get Skein_256_256
    forall a b. (a -> b) -> Get a -> Get b
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap Key -> Skein_256_256
    S_256_256 (Get Key -> Get Skein_256_256) -> Get Key -> Get Skein_256_256
    forall a b. (a -> b) -> a -> b
    $ Int -> Get Key
    getByteString Int
    32

    instance Hash Skein_256_256_Ctx Skein_256_256 where
        outputLength :: Tagged Skein_256_256 Int
    outputLength = Int -> Tagged Skein_256_256 Int
    forall {k} (s :: k) b. b -> Tagged s b
    Tagged Int
    256
        blockLength :: Tagged Skein_256_256 Int
    blockLength  = Int -> Tagged Skein_256_256 Int
    forall {k} (s :: k) b. b -> Tagged s b
    Tagged Int
    256
        initialCtx :: Skein_256_256_Ctx
    initialCtx   = CSize
    -> (Ptr Skein256Ctx -> CSize -> IO CInt)
    -> (Skein256Ctx -> Skein_256_256_Ctx)
    -> Skein_256_256_Ctx
    forall internalCtx externalCtx.
    Storable internalCtx =>
    CSize
    -> (Ptr internalCtx -> CSize -> IO CInt)
    -> (internalCtx -> externalCtx)
    -> externalCtx
    initialCtxSkein CSize
    256 Ptr Skein256Ctx -> CSize -> IO CInt
    skein256Init Skein256Ctx -> Skein_256_256_Ctx
    S_256_256_Ctx
        updateCtx :: Skein_256_256_Ctx -> Key -> Skein_256_256_Ctx
    updateCtx    = (Ptr Skein256Ctx -> Ptr Word8 -> CSize -> IO CInt)
    -> (Skein_256_256_Ctx -> Skein256Ctx)
    -> (Skein256Ctx -> Skein_256_256_Ctx)
    -> Skein_256_256_Ctx
    -> Key
    -> Skein_256_256_Ctx
    forall internalCtx externalCtx.
    Storable internalCtx =>
    (Ptr internalCtx -> Ptr Word8 -> CSize -> IO CInt)
    -> (externalCtx -> internalCtx)
    -> (internalCtx -> externalCtx)
    -> externalCtx
    -> Key
    -> externalCtx
    updateCtxSkein Ptr Skein256Ctx -> Ptr Word8 -> CSize -> IO CInt
    skein256Update Skein_256_256_Ctx -> Skein256Ctx
    unS_256_256_Ctx Skein256Ctx -> Skein_256_256_Ctx
    S_256_256_Ctx
        finalize :: Skein_256_256_Ctx -> Key -> Skein_256_256
    finalize     = Int
    -> (Ptr Skein256Ctx -> Ptr Word8 -> CSize -> IO CInt)
    -> (Ptr Skein256Ctx -> Ptr Word8 -> IO CInt)
    -> (Skein_256_256_Ctx -> Skein256Ctx)
    -> (Key -> Skein_256_256)
    -> Skein_256_256_Ctx
    -> Key
    -> Skein_256_256
    forall internalCtx externalCtx hash.
    Storable internalCtx =>
    Int
    -> (Ptr internalCtx -> Ptr Word8 -> CSize -> IO CInt)
    -> (Ptr internalCtx -> Ptr Word8 -> IO CInt)
    -> (externalCtx -> internalCtx)
    -> (Key -> hash)
    -> externalCtx
    -> Key
    -> hash
    finalizeSkein Int
    32 Ptr Skein256Ctx -> Ptr Word8 -> CSize -> IO CInt
    skein256Update Ptr Skein256Ctx -> Ptr Word8 -> IO CInt
    skein256Final Skein_256_256_Ctx -> Skein256Ctx
    unS_256_256_Ctx Key -> Skein_256_256
    S_256_256

    instance SkeinMAC Skein_256_256_Ctx where
        skeinMACCtx :: Key -> Skein_256_256_Ctx
    skeinMACCtx = CSize
    -> (Ptr Skein256Ctx
        -> CSize -> Word64 -> Ptr Word8 -> CSize -> IO CInt)
    -> (Skein256Ctx -> Skein_256_256_Ctx)
    -> Key
    -> Skein_256_256_Ctx
    forall internalCtx externalCtx.
    Storable internalCtx =>
    CSize
    -> (Ptr internalCtx
        -> CSize -> Word64 -> Ptr Word8 -> CSize -> IO CInt)
    -> (internalCtx -> externalCtx)
    -> Key
    -> externalCtx
    skeinMACCtxSkein CSize
    256 Ptr Skein256Ctx -> CSize -> Word64 -> Ptr Word8 -> CSize -> IO CInt
    skein256InitExt Skein256Ctx -> Skein_256_256_Ctx
    S_256_256_Ctx

    ----------------------------------------------------------------------
    -- Skein-512
    ----------------------------------------------------------------------

    -- | Context of the Skein-512-128 hash function.
    newtype Skein_512_128_Ctx = S_512_128_Ctx {Skein_512_128_Ctx -> Skein512Ctx
    unS_512_128_Ctx :: Skein512Ctx}

    -- | Skein-512-128 hash.  You probably want to use 'encode' to
    -- obtain a 128-bit (16-byte) 'B.ByteString'.  May be used as a
    -- drop-in replacement for MD5.
    newtype Skein_512_128 = S_512_128 B.ByteString deriving (Skein_512_128 -> Skein_512_128 -> Bool
    (Skein_512_128 -> Skein_512_128 -> Bool)
    -> (Skein_512_128 -> Skein_512_128 -> Bool) -> Eq Skein_512_128
    forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
    $c== :: Skein_512_128 -> Skein_512_128 -> Bool
    == :: Skein_512_128 -> Skein_512_128 -> Bool
    $c/= :: Skein_512_128 -> Skein_512_128 -> Bool
    /= :: Skein_512_128 -> Skein_512_128 -> Bool
    Eq, Eq Skein_512_128
    Eq Skein_512_128 =>
    (Skein_512_128 -> Skein_512_128 -> Ordering)
    -> (Skein_512_128 -> Skein_512_128 -> Bool)
    -> (Skein_512_128 -> Skein_512_128 -> Bool)
    -> (Skein_512_128 -> Skein_512_128 -> Bool)
    -> (Skein_512_128 -> Skein_512_128 -> Bool)
    -> (Skein_512_128 -> Skein_512_128 -> Skein_512_128)
    -> (Skein_512_128 -> Skein_512_128 -> Skein_512_128)
    -> Ord Skein_512_128
    Skein_512_128 -> Skein_512_128 -> Bool
    Skein_512_128 -> Skein_512_128 -> Ordering
    Skein_512_128 -> Skein_512_128 -> Skein_512_128
    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 :: Skein_512_128 -> Skein_512_128 -> Ordering
    compare :: Skein_512_128 -> Skein_512_128 -> Ordering
    $c< :: Skein_512_128 -> Skein_512_128 -> Bool
    < :: Skein_512_128 -> Skein_512_128 -> Bool
    $c<= :: Skein_512_128 -> Skein_512_128 -> Bool
    <= :: Skein_512_128 -> Skein_512_128 -> Bool
    $c> :: Skein_512_128 -> Skein_512_128 -> Bool
    > :: Skein_512_128 -> Skein_512_128 -> Bool
    $c>= :: Skein_512_128 -> Skein_512_128 -> Bool
    >= :: Skein_512_128 -> Skein_512_128 -> Bool
    $cmax :: Skein_512_128 -> Skein_512_128 -> Skein_512_128
    max :: Skein_512_128 -> Skein_512_128 -> Skein_512_128
    $cmin :: Skein_512_128 -> Skein_512_128 -> Skein_512_128
    min :: Skein_512_128 -> Skein_512_128 -> Skein_512_128
    Ord)

    instance Serialize Skein_512_128 where
        put :: Putter Skein_512_128
    put (S_512_128 Key
    bs) = Putter Key
    putByteString Key
    bs
        get :: Get Skein_512_128
    get = (Key -> Skein_512_128) -> Get Key -> Get Skein_512_128
    forall a b. (a -> b) -> Get a -> Get b
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap Key -> Skein_512_128
    S_512_128 (Get Key -> Get Skein_512_128) -> Get Key -> Get Skein_512_128
    forall a b. (a -> b) -> a -> b
    $ Int -> Get Key
    getByteString Int
    16

    instance Hash Skein_512_128_Ctx Skein_512_128 where
        outputLength :: Tagged Skein_512_128 Int
    outputLength = Int -> Tagged Skein_512_128 Int
    forall {k} (s :: k) b. b -> Tagged s b
    Tagged Int
    128
        blockLength :: Tagged Skein_512_128 Int
    blockLength  = Int -> Tagged Skein_512_128 Int
    forall {k} (s :: k) b. b -> Tagged s b
    Tagged Int
    512
        initialCtx :: Skein_512_128_Ctx
    initialCtx   = CSize
    -> (Ptr Skein512Ctx -> CSize -> IO CInt)
    -> (Skein512Ctx -> Skein_512_128_Ctx)
    -> Skein_512_128_Ctx
    forall internalCtx externalCtx.
    Storable internalCtx =>
    CSize
    -> (Ptr internalCtx -> CSize -> IO CInt)
    -> (internalCtx -> externalCtx)
    -> externalCtx
    initialCtxSkein CSize
    128 Ptr Skein512Ctx -> CSize -> IO CInt
    skein512Init Skein512Ctx -> Skein_512_128_Ctx
    S_512_128_Ctx
        updateCtx :: Skein_512_128_Ctx -> Key -> Skein_512_128_Ctx
    updateCtx    = (Ptr Skein512Ctx -> Ptr Word8 -> CSize -> IO CInt)
    -> (Skein_512_128_Ctx -> Skein512Ctx)
    -> (Skein512Ctx -> Skein_512_128_Ctx)
    -> Skein_512_128_Ctx
    -> Key
    -> Skein_512_128_Ctx
    forall internalCtx externalCtx.
    Storable internalCtx =>
    (Ptr internalCtx -> Ptr Word8 -> CSize -> IO CInt)
    -> (externalCtx -> internalCtx)
    -> (internalCtx -> externalCtx)
    -> externalCtx
    -> Key
    -> externalCtx
    updateCtxSkein Ptr Skein512Ctx -> Ptr Word8 -> CSize -> IO CInt
    skein512Update Skein_512_128_Ctx -> Skein512Ctx
    unS_512_128_Ctx Skein512Ctx -> Skein_512_128_Ctx
    S_512_128_Ctx
        finalize :: Skein_512_128_Ctx -> Key -> Skein_512_128
    finalize     = Int
    -> (Ptr Skein512Ctx -> Ptr Word8 -> CSize -> IO CInt)
    -> (Ptr Skein512Ctx -> Ptr Word8 -> IO CInt)
    -> (Skein_512_128_Ctx -> Skein512Ctx)
    -> (Key -> Skein_512_128)
    -> Skein_512_128_Ctx
    -> Key
    -> Skein_512_128
    forall internalCtx externalCtx hash.
    Storable internalCtx =>
    Int
    -> (Ptr internalCtx -> Ptr Word8 -> CSize -> IO CInt)
    -> (Ptr internalCtx -> Ptr Word8 -> IO CInt)
    -> (externalCtx -> internalCtx)
    -> (Key -> hash)
    -> externalCtx
    -> Key
    -> hash
    finalizeSkein Int
    16 Ptr Skein512Ctx -> Ptr Word8 -> CSize -> IO CInt
    skein512Update Ptr Skein512Ctx -> Ptr Word8 -> IO CInt
    skein512Final Skein_512_128_Ctx -> Skein512Ctx
    unS_512_128_Ctx Key -> Skein_512_128
    S_512_128

    instance SkeinMAC Skein_512_128_Ctx where
        skeinMACCtx :: Key -> Skein_512_128_Ctx
    skeinMACCtx = CSize
    -> (Ptr Skein512Ctx
        -> CSize -> Word64 -> Ptr Word8 -> CSize -> IO CInt)
    -> (Skein512Ctx -> Skein_512_128_Ctx)
    -> Key
    -> Skein_512_128_Ctx
    forall internalCtx externalCtx.
    Storable internalCtx =>
    CSize
    -> (Ptr internalCtx
        -> CSize -> Word64 -> Ptr Word8 -> CSize -> IO CInt)
    -> (internalCtx -> externalCtx)
    -> Key
    -> externalCtx
    skeinMACCtxSkein CSize
    128 Ptr Skein512Ctx -> CSize -> Word64 -> Ptr Word8 -> CSize -> IO CInt
    skein512InitExt Skein512Ctx -> Skein_512_128_Ctx
    S_512_128_Ctx

    -- | Context of the Skein-512-160 hash function.
    newtype Skein_512_160_Ctx = S_512_160_Ctx {Skein_512_160_Ctx -> Skein512Ctx
    unS_512_160_Ctx :: Skein512Ctx}

    -- | Skein-512-160 hash.  You probably want to use 'encode' to
    -- obtain a 160-bit (20-byte) 'B.ByteString'.  May be used as a
    -- drop-in replacement for SHA-1.
    newtype Skein_512_160 = S_512_160 B.ByteString deriving (Skein_512_160 -> Skein_512_160 -> Bool
    (Skein_512_160 -> Skein_512_160 -> Bool)
    -> (Skein_512_160 -> Skein_512_160 -> Bool) -> Eq Skein_512_160
    forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
    $c== :: Skein_512_160 -> Skein_512_160 -> Bool
    == :: Skein_512_160 -> Skein_512_160 -> Bool
    $c/= :: Skein_512_160 -> Skein_512_160 -> Bool
    /= :: Skein_512_160 -> Skein_512_160 -> Bool
    Eq, Eq Skein_512_160
    Eq Skein_512_160 =>
    (Skein_512_160 -> Skein_512_160 -> Ordering)
    -> (Skein_512_160 -> Skein_512_160 -> Bool)
    -> (Skein_512_160 -> Skein_512_160 -> Bool)
    -> (Skein_512_160 -> Skein_512_160 -> Bool)
    -> (Skein_512_160 -> Skein_512_160 -> Bool)
    -> (Skein_512_160 -> Skein_512_160 -> Skein_512_160)
    -> (Skein_512_160 -> Skein_512_160 -> Skein_512_160)
    -> Ord Skein_512_160
    Skein_512_160 -> Skein_512_160 -> Bool
    Skein_512_160 -> Skein_512_160 -> Ordering
    Skein_512_160 -> Skein_512_160 -> Skein_512_160
    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 :: Skein_512_160 -> Skein_512_160 -> Ordering
    compare :: Skein_512_160 -> Skein_512_160 -> Ordering
    $c< :: Skein_512_160 -> Skein_512_160 -> Bool
    < :: Skein_512_160 -> Skein_512_160 -> Bool
    $c<= :: Skein_512_160 -> Skein_512_160 -> Bool
    <= :: Skein_512_160 -> Skein_512_160 -> Bool
    $c> :: Skein_512_160 -> Skein_512_160 -> Bool
    > :: Skein_512_160 -> Skein_512_160 -> Bool
    $c>= :: Skein_512_160 -> Skein_512_160 -> Bool
    >= :: Skein_512_160 -> Skein_512_160 -> Bool
    $cmax :: Skein_512_160 -> Skein_512_160 -> Skein_512_160
    max :: Skein_512_160 -> Skein_512_160 -> Skein_512_160
    $cmin :: Skein_512_160 -> Skein_512_160 -> Skein_512_160
    min :: Skein_512_160 -> Skein_512_160 -> Skein_512_160
    Ord)

    instance Serialize Skein_512_160 where
        put :: Putter Skein_512_160
    put (S_512_160 Key
    bs) = Putter Key
    putByteString Key
    bs
        get :: Get Skein_512_160
    get = (Key -> Skein_512_160) -> Get Key -> Get Skein_512_160
    forall a b. (a -> b) -> Get a -> Get b
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap Key -> Skein_512_160
    S_512_160 (Get Key -> Get Skein_512_160) -> Get Key -> Get Skein_512_160
    forall a b. (a -> b) -> a -> b
    $ Int -> Get Key
    getByteString Int
    20

    instance Hash Skein_512_160_Ctx Skein_512_160 where
        outputLength :: Tagged Skein_512_160 Int
    outputLength = Int -> Tagged Skein_512_160 Int
    forall {k} (s :: k) b. b -> Tagged s b
    Tagged Int
    160
        blockLength :: Tagged Skein_512_160 Int
    blockLength  = Int -> Tagged Skein_512_160 Int
    forall {k} (s :: k) b. b -> Tagged s b
    Tagged Int
    512
        initialCtx :: Skein_512_160_Ctx
    initialCtx   = CSize
    -> (Ptr Skein512Ctx -> CSize -> IO CInt)
    -> (Skein512Ctx -> Skein_512_160_Ctx)
    -> Skein_512_160_Ctx
    forall internalCtx externalCtx.
    Storable internalCtx =>
    CSize
    -> (Ptr internalCtx -> CSize -> IO CInt)
    -> (internalCtx -> externalCtx)
    -> externalCtx
    initialCtxSkein CSize
    160 Ptr Skein512Ctx -> CSize -> IO CInt
    skein512Init Skein512Ctx -> Skein_512_160_Ctx
    S_512_160_Ctx
        updateCtx :: Skein_512_160_Ctx -> Key -> Skein_512_160_Ctx
    updateCtx    = (Ptr Skein512Ctx -> Ptr Word8 -> CSize -> IO CInt)
    -> (Skein_512_160_Ctx -> Skein512Ctx)
    -> (Skein512Ctx -> Skein_512_160_Ctx)
    -> Skein_512_160_Ctx
    -> Key
    -> Skein_512_160_Ctx
    forall internalCtx externalCtx.
    Storable internalCtx =>
    (Ptr internalCtx -> Ptr Word8 -> CSize -> IO CInt)
    -> (externalCtx -> internalCtx)
    -> (internalCtx -> externalCtx)
    -> externalCtx
    -> Key
    -> externalCtx
    updateCtxSkein Ptr Skein512Ctx -> Ptr Word8 -> CSize -> IO CInt
    skein512Update Skein_512_160_Ctx -> Skein512Ctx
    unS_512_160_Ctx Skein512Ctx -> Skein_512_160_Ctx
    S_512_160_Ctx
        finalize :: Skein_512_160_Ctx -> Key -> Skein_512_160
    finalize     = Int
    -> (Ptr Skein512Ctx -> Ptr Word8 -> CSize -> IO CInt)
    -> (Ptr Skein512Ctx -> Ptr Word8 -> IO CInt)
    -> (Skein_512_160_Ctx -> Skein512Ctx)
    -> (Key -> Skein_512_160)
    -> Skein_512_160_Ctx
    -> Key
    -> Skein_512_160
    forall internalCtx externalCtx hash.
    Storable internalCtx =>
    Int
    -> (Ptr internalCtx -> Ptr Word8 -> CSize -> IO CInt)
    -> (Ptr internalCtx -> Ptr Word8 -> IO CInt)
    -> (externalCtx -> internalCtx)
    -> (Key -> hash)
    -> externalCtx
    -> Key
    -> hash
    finalizeSkein Int
    20 Ptr Skein512Ctx -> Ptr Word8 -> CSize -> IO CInt
    skein512Update Ptr Skein512Ctx -> Ptr Word8 -> IO CInt
    skein512Final Skein_512_160_Ctx -> Skein512Ctx
    unS_512_160_Ctx Key -> Skein_512_160
    S_512_160

    instance SkeinMAC Skein_512_160_Ctx where
        skeinMACCtx :: Key -> Skein_512_160_Ctx
    skeinMACCtx = CSize
    -> (Ptr Skein512Ctx
        -> CSize -> Word64 -> Ptr Word8 -> CSize -> IO CInt)
    -> (Skein512Ctx -> Skein_512_160_Ctx)
    -> Key
    -> Skein_512_160_Ctx
    forall internalCtx externalCtx.
    Storable internalCtx =>
    CSize
    -> (Ptr internalCtx
        -> CSize -> Word64 -> Ptr Word8 -> CSize -> IO CInt)
    -> (internalCtx -> externalCtx)
    -> Key
    -> externalCtx
    skeinMACCtxSkein CSize
    160 Ptr Skein512Ctx -> CSize -> Word64 -> Ptr Word8 -> CSize -> IO CInt
    skein512InitExt Skein512Ctx -> Skein_512_160_Ctx
    S_512_160_Ctx

    -- | Context of the Skein-512-224 hash function.
    newtype Skein_512_224_Ctx = S_512_224_Ctx {Skein_512_224_Ctx -> Skein512Ctx
    unS_512_224_Ctx :: Skein512Ctx}

    -- | Skein-512-224 hash.  You probably want to use 'encode' to
    -- obtain a 224-bit (28-byte) 'B.ByteString'.  May be used as a drop-in replacement for SHA-224.
    newtype Skein_512_224 = S_512_224 B.ByteString deriving (Skein_512_224 -> Skein_512_224 -> Bool
    (Skein_512_224 -> Skein_512_224 -> Bool)
    -> (Skein_512_224 -> Skein_512_224 -> Bool) -> Eq Skein_512_224
    forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
    $c== :: Skein_512_224 -> Skein_512_224 -> Bool
    == :: Skein_512_224 -> Skein_512_224 -> Bool
    $c/= :: Skein_512_224 -> Skein_512_224 -> Bool
    /= :: Skein_512_224 -> Skein_512_224 -> Bool
    Eq, Eq Skein_512_224
    Eq Skein_512_224 =>
    (Skein_512_224 -> Skein_512_224 -> Ordering)
    -> (Skein_512_224 -> Skein_512_224 -> Bool)
    -> (Skein_512_224 -> Skein_512_224 -> Bool)
    -> (Skein_512_224 -> Skein_512_224 -> Bool)
    -> (Skein_512_224 -> Skein_512_224 -> Bool)
    -> (Skein_512_224 -> Skein_512_224 -> Skein_512_224)
    -> (Skein_512_224 -> Skein_512_224 -> Skein_512_224)
    -> Ord Skein_512_224
    Skein_512_224 -> Skein_512_224 -> Bool
    Skein_512_224 -> Skein_512_224 -> Ordering
    Skein_512_224 -> Skein_512_224 -> Skein_512_224
    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 :: Skein_512_224 -> Skein_512_224 -> Ordering
    compare :: Skein_512_224 -> Skein_512_224 -> Ordering
    $c< :: Skein_512_224 -> Skein_512_224 -> Bool
    < :: Skein_512_224 -> Skein_512_224 -> Bool
    $c<= :: Skein_512_224 -> Skein_512_224 -> Bool
    <= :: Skein_512_224 -> Skein_512_224 -> Bool
    $c> :: Skein_512_224 -> Skein_512_224 -> Bool
    > :: Skein_512_224 -> Skein_512_224 -> Bool
    $c>= :: Skein_512_224 -> Skein_512_224 -> Bool
    >= :: Skein_512_224 -> Skein_512_224 -> Bool
    $cmax :: Skein_512_224 -> Skein_512_224 -> Skein_512_224
    max :: Skein_512_224 -> Skein_512_224 -> Skein_512_224
    $cmin :: Skein_512_224 -> Skein_512_224 -> Skein_512_224
    min :: Skein_512_224 -> Skein_512_224 -> Skein_512_224
    Ord)

    instance Serialize Skein_512_224 where
        put :: Putter Skein_512_224
    put (S_512_224 Key
    bs) = Putter Key
    putByteString Key
    bs
        get :: Get Skein_512_224
    get = (Key -> Skein_512_224) -> Get Key -> Get Skein_512_224
    forall a b. (a -> b) -> Get a -> Get b
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap Key -> Skein_512_224
    S_512_224 (Get Key -> Get Skein_512_224) -> Get Key -> Get Skein_512_224
    forall a b. (a -> b) -> a -> b
    $ Int -> Get Key
    getByteString Int
    28

    instance Hash Skein_512_224_Ctx Skein_512_224 where
        outputLength :: Tagged Skein_512_224 Int
    outputLength = Int -> Tagged Skein_512_224 Int
    forall {k} (s :: k) b. b -> Tagged s b
    Tagged Int
    224
        blockLength :: Tagged Skein_512_224 Int
    blockLength  = Int -> Tagged Skein_512_224 Int
    forall {k} (s :: k) b. b -> Tagged s b
    Tagged Int
    512
        initialCtx :: Skein_512_224_Ctx
    initialCtx   = CSize
    -> (Ptr Skein512Ctx -> CSize -> IO CInt)
    -> (Skein512Ctx -> Skein_512_224_Ctx)
    -> Skein_512_224_Ctx
    forall internalCtx externalCtx.
    Storable internalCtx =>
    CSize
    -> (Ptr internalCtx -> CSize -> IO CInt)
    -> (internalCtx -> externalCtx)
    -> externalCtx
    initialCtxSkein CSize
    224 Ptr Skein512Ctx -> CSize -> IO CInt
    skein512Init Skein512Ctx -> Skein_512_224_Ctx
    S_512_224_Ctx
        updateCtx :: Skein_512_224_Ctx -> Key -> Skein_512_224_Ctx
    updateCtx    = (Ptr Skein512Ctx -> Ptr Word8 -> CSize -> IO CInt)
    -> (Skein_512_224_Ctx -> Skein512Ctx)
    -> (Skein512Ctx -> Skein_512_224_Ctx)
    -> Skein_512_224_Ctx
    -> Key
    -> Skein_512_224_Ctx
    forall internalCtx externalCtx.
    Storable internalCtx =>
    (Ptr internalCtx -> Ptr Word8 -> CSize -> IO CInt)
    -> (externalCtx -> internalCtx)
    -> (internalCtx -> externalCtx)
    -> externalCtx
    -> Key
    -> externalCtx
    updateCtxSkein Ptr Skein512Ctx -> Ptr Word8 -> CSize -> IO CInt
    skein512Update Skein_512_224_Ctx -> Skein512Ctx
    unS_512_224_Ctx Skein512Ctx -> Skein_512_224_Ctx
    S_512_224_Ctx
        finalize :: Skein_512_224_Ctx -> Key -> Skein_512_224
    finalize     = Int
    -> (Ptr Skein512Ctx -> Ptr Word8 -> CSize -> IO CInt)
    -> (Ptr Skein512Ctx -> Ptr Word8 -> IO CInt)
    -> (Skein_512_224_Ctx -> Skein512Ctx)
    -> (Key -> Skein_512_224)
    -> Skein_512_224_Ctx
    -> Key
    -> Skein_512_224
    forall internalCtx externalCtx hash.
    Storable internalCtx =>
    Int
    -> (Ptr internalCtx -> Ptr Word8 -> CSize -> IO CInt)
    -> (Ptr internalCtx -> Ptr Word8 -> IO CInt)
    -> (externalCtx -> internalCtx)
    -> (Key -> hash)
    -> externalCtx
    -> Key
    -> hash
    finalizeSkein Int
    28 Ptr Skein512Ctx -> Ptr Word8 -> CSize -> IO CInt
    skein512Update Ptr Skein512Ctx -> Ptr Word8 -> IO CInt
    skein512Final Skein_512_224_Ctx -> Skein512Ctx
    unS_512_224_Ctx Key -> Skein_512_224
    S_512_224

    instance SkeinMAC Skein_512_224_Ctx where
        skeinMACCtx :: Key -> Skein_512_224_Ctx
    skeinMACCtx = CSize
    -> (Ptr Skein512Ctx
        -> CSize -> Word64 -> Ptr Word8 -> CSize -> IO CInt)
    -> (Skein512Ctx -> Skein_512_224_Ctx)
    -> Key
    -> Skein_512_224_Ctx
    forall internalCtx externalCtx.
    Storable internalCtx =>
    CSize
    -> (Ptr internalCtx
        -> CSize -> Word64 -> Ptr Word8 -> CSize -> IO CInt)
    -> (internalCtx -> externalCtx)
    -> Key
    -> externalCtx
    skeinMACCtxSkein CSize
    224 Ptr Skein512Ctx -> CSize -> Word64 -> Ptr Word8 -> CSize -> IO CInt
    skein512InitExt Skein512Ctx -> Skein_512_224_Ctx
    S_512_224_Ctx

    -- | Context of the Skein-512-256 hash function.
    newtype Skein_512_256_Ctx = S_512_256_Ctx {Skein_512_256_Ctx -> Skein512Ctx
    unS_512_256_Ctx :: Skein512Ctx}

    -- | Skein-512-256 hash.  You probably want to use 'encode' to
    -- obtain a 256-bit (32-byte) 'B.ByteString'.
    newtype Skein_512_256 = S_512_256 B.ByteString deriving (Skein_512_256 -> Skein_512_256 -> Bool
    (Skein_512_256 -> Skein_512_256 -> Bool)
    -> (Skein_512_256 -> Skein_512_256 -> Bool) -> Eq Skein_512_256
    forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
    $c== :: Skein_512_256 -> Skein_512_256 -> Bool
    == :: Skein_512_256 -> Skein_512_256 -> Bool
    $c/= :: Skein_512_256 -> Skein_512_256 -> Bool
    /= :: Skein_512_256 -> Skein_512_256 -> Bool
    Eq, Eq Skein_512_256
    Eq Skein_512_256 =>
    (Skein_512_256 -> Skein_512_256 -> Ordering)
    -> (Skein_512_256 -> Skein_512_256 -> Bool)
    -> (Skein_512_256 -> Skein_512_256 -> Bool)
    -> (Skein_512_256 -> Skein_512_256 -> Bool)
    -> (Skein_512_256 -> Skein_512_256 -> Bool)
    -> (Skein_512_256 -> Skein_512_256 -> Skein_512_256)
    -> (Skein_512_256 -> Skein_512_256 -> Skein_512_256)
    -> Ord Skein_512_256
    Skein_512_256 -> Skein_512_256 -> Bool
    Skein_512_256 -> Skein_512_256 -> Ordering
    Skein_512_256 -> Skein_512_256 -> Skein_512_256
    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 :: Skein_512_256 -> Skein_512_256 -> Ordering
    compare :: Skein_512_256 -> Skein_512_256 -> Ordering
    $c< :: Skein_512_256 -> Skein_512_256 -> Bool
    < :: Skein_512_256 -> Skein_512_256 -> Bool
    $c<= :: Skein_512_256 -> Skein_512_256 -> Bool
    <= :: Skein_512_256 -> Skein_512_256 -> Bool
    $c> :: Skein_512_256 -> Skein_512_256 -> Bool
    > :: Skein_512_256 -> Skein_512_256 -> Bool
    $c>= :: Skein_512_256 -> Skein_512_256 -> Bool
    >= :: Skein_512_256 -> Skein_512_256 -> Bool
    $cmax :: Skein_512_256 -> Skein_512_256 -> Skein_512_256
    max :: Skein_512_256 -> Skein_512_256 -> Skein_512_256
    $cmin :: Skein_512_256 -> Skein_512_256 -> Skein_512_256
    min :: Skein_512_256 -> Skein_512_256 -> Skein_512_256
    Ord)

    instance Serialize Skein_512_256 where
        put :: Putter Skein_512_256
    put (S_512_256 Key
    bs) = Putter Key
    putByteString Key
    bs
        get :: Get Skein_512_256
    get = (Key -> Skein_512_256) -> Get Key -> Get Skein_512_256
    forall a b. (a -> b) -> Get a -> Get b
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap Key -> Skein_512_256
    S_512_256 (Get Key -> Get Skein_512_256) -> Get Key -> Get Skein_512_256
    forall a b. (a -> b) -> a -> b
    $ Int -> Get Key
    getByteString Int
    32

    instance Hash Skein_512_256_Ctx Skein_512_256 where
        outputLength :: Tagged Skein_512_256 Int
    outputLength = Int -> Tagged Skein_512_256 Int
    forall {k} (s :: k) b. b -> Tagged s b
    Tagged Int
    256
        blockLength :: Tagged Skein_512_256 Int
    blockLength  = Int -> Tagged Skein_512_256 Int
    forall {k} (s :: k) b. b -> Tagged s b
    Tagged Int
    512
        initialCtx :: Skein_512_256_Ctx
    initialCtx   = CSize
    -> (Ptr Skein512Ctx -> CSize -> IO CInt)
    -> (Skein512Ctx -> Skein_512_256_Ctx)
    -> Skein_512_256_Ctx
    forall internalCtx externalCtx.
    Storable internalCtx =>
    CSize
    -> (Ptr internalCtx -> CSize -> IO CInt)
    -> (internalCtx -> externalCtx)
    -> externalCtx
    initialCtxSkein CSize
    256 Ptr Skein512Ctx -> CSize -> IO CInt
    skein512Init Skein512Ctx -> Skein_512_256_Ctx
    S_512_256_Ctx
        updateCtx :: Skein_512_256_Ctx -> Key -> Skein_512_256_Ctx
    updateCtx    = (Ptr Skein512Ctx -> Ptr Word8 -> CSize -> IO CInt)
    -> (Skein_512_256_Ctx -> Skein512Ctx)
    -> (Skein512Ctx -> Skein_512_256_Ctx)
    -> Skein_512_256_Ctx
    -> Key
    -> Skein_512_256_Ctx
    forall internalCtx externalCtx.
    Storable internalCtx =>
    (Ptr internalCtx -> Ptr Word8 -> CSize -> IO CInt)
    -> (externalCtx -> internalCtx)
    -> (internalCtx -> externalCtx)
    -> externalCtx
    -> Key
    -> externalCtx
    updateCtxSkein Ptr Skein512Ctx -> Ptr Word8 -> CSize -> IO CInt
    skein512Update Skein_512_256_Ctx -> Skein512Ctx
    unS_512_256_Ctx Skein512Ctx -> Skein_512_256_Ctx
    S_512_256_Ctx
        finalize :: Skein_512_256_Ctx -> Key -> Skein_512_256
    finalize     = Int
    -> (Ptr Skein512Ctx -> Ptr Word8 -> CSize -> IO CInt)
    -> (Ptr Skein512Ctx -> Ptr Word8 -> IO CInt)
    -> (Skein_512_256_Ctx -> Skein512Ctx)
    -> (Key -> Skein_512_256)
    -> Skein_512_256_Ctx
    -> Key
    -> Skein_512_256
    forall internalCtx externalCtx hash.
    Storable internalCtx =>
    Int
    -> (Ptr internalCtx -> Ptr Word8 -> CSize -> IO CInt)
    -> (Ptr internalCtx -> Ptr Word8 -> IO CInt)
    -> (externalCtx -> internalCtx)
    -> (Key -> hash)
    -> externalCtx
    -> Key
    -> hash
    finalizeSkein Int
    32 Ptr Skein512Ctx -> Ptr Word8 -> CSize -> IO CInt
    skein512Update Ptr Skein512Ctx -> Ptr Word8 -> IO CInt
    skein512Final Skein_512_256_Ctx -> Skein512Ctx
    unS_512_256_Ctx Key -> Skein_512_256
    S_512_256

    instance SkeinMAC Skein_512_256_Ctx where
        skeinMACCtx :: Key -> Skein_512_256_Ctx
    skeinMACCtx = CSize
    -> (Ptr Skein512Ctx
        -> CSize -> Word64 -> Ptr Word8 -> CSize -> IO CInt)
    -> (Skein512Ctx -> Skein_512_256_Ctx)
    -> Key
    -> Skein_512_256_Ctx
    forall internalCtx externalCtx.
    Storable internalCtx =>
    CSize
    -> (Ptr internalCtx
        -> CSize -> Word64 -> Ptr Word8 -> CSize -> IO CInt)
    -> (internalCtx -> externalCtx)
    -> Key
    -> externalCtx
    skeinMACCtxSkein CSize
    256 Ptr Skein512Ctx -> CSize -> Word64 -> Ptr Word8 -> CSize -> IO CInt
    skein512InitExt Skein512Ctx -> Skein_512_256_Ctx
    S_512_256_Ctx

    -- | Context of the Skein-512-384 hash function.
    newtype Skein_512_384_Ctx = S_512_384_Ctx {Skein_512_384_Ctx -> Skein512Ctx
    unS_512_384_Ctx :: Skein512Ctx}

    -- | Skein-512-384 hash.  You probably want to use 'encode' to
    -- obtain a 384-bit (48-byte) 'B.ByteString'.  May be used as a
    -- drop-in replacement for SHA-384.
    newtype Skein_512_384 = S_512_384 B.ByteString deriving (Skein_512_384 -> Skein_512_384 -> Bool
    (Skein_512_384 -> Skein_512_384 -> Bool)
    -> (Skein_512_384 -> Skein_512_384 -> Bool) -> Eq Skein_512_384
    forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
    $c== :: Skein_512_384 -> Skein_512_384 -> Bool
    == :: Skein_512_384 -> Skein_512_384 -> Bool
    $c/= :: Skein_512_384 -> Skein_512_384 -> Bool
    /= :: Skein_512_384 -> Skein_512_384 -> Bool
    Eq, Eq Skein_512_384
    Eq Skein_512_384 =>
    (Skein_512_384 -> Skein_512_384 -> Ordering)
    -> (Skein_512_384 -> Skein_512_384 -> Bool)
    -> (Skein_512_384 -> Skein_512_384 -> Bool)
    -> (Skein_512_384 -> Skein_512_384 -> Bool)
    -> (Skein_512_384 -> Skein_512_384 -> Bool)
    -> (Skein_512_384 -> Skein_512_384 -> Skein_512_384)
    -> (Skein_512_384 -> Skein_512_384 -> Skein_512_384)
    -> Ord Skein_512_384
    Skein_512_384 -> Skein_512_384 -> Bool
    Skein_512_384 -> Skein_512_384 -> Ordering
    Skein_512_384 -> Skein_512_384 -> Skein_512_384
    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 :: Skein_512_384 -> Skein_512_384 -> Ordering
    compare :: Skein_512_384 -> Skein_512_384 -> Ordering
    $c< :: Skein_512_384 -> Skein_512_384 -> Bool
    < :: Skein_512_384 -> Skein_512_384 -> Bool
    $c<= :: Skein_512_384 -> Skein_512_384 -> Bool
    <= :: Skein_512_384 -> Skein_512_384 -> Bool
    $c> :: Skein_512_384 -> Skein_512_384 -> Bool
    > :: Skein_512_384 -> Skein_512_384 -> Bool
    $c>= :: Skein_512_384 -> Skein_512_384 -> Bool
    >= :: Skein_512_384 -> Skein_512_384 -> Bool
    $cmax :: Skein_512_384 -> Skein_512_384 -> Skein_512_384
    max :: Skein_512_384 -> Skein_512_384 -> Skein_512_384
    $cmin :: Skein_512_384 -> Skein_512_384 -> Skein_512_384
    min :: Skein_512_384 -> Skein_512_384 -> Skein_512_384
    Ord)

    instance Serialize Skein_512_384 where
        put :: Putter Skein_512_384
    put (S_512_384 Key
    bs) = Putter Key
    putByteString Key
    bs
        get :: Get Skein_512_384
    get = (Key -> Skein_512_384) -> Get Key -> Get Skein_512_384
    forall a b. (a -> b) -> Get a -> Get b
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap Key -> Skein_512_384
    S_512_384 (Get Key -> Get Skein_512_384) -> Get Key -> Get Skein_512_384
    forall a b. (a -> b) -> a -> b
    $ Int -> Get Key
    getByteString Int
    48

    instance Hash Skein_512_384_Ctx Skein_512_384 where
        outputLength :: Tagged Skein_512_384 Int
    outputLength = Int -> Tagged Skein_512_384 Int
    forall {k} (s :: k) b. b -> Tagged s b
    Tagged Int
    384
        blockLength :: Tagged Skein_512_384 Int
    blockLength  = Int -> Tagged Skein_512_384 Int
    forall {k} (s :: k) b. b -> Tagged s b
    Tagged Int
    512
        initialCtx :: Skein_512_384_Ctx
    initialCtx   = CSize
    -> (Ptr Skein512Ctx -> CSize -> IO CInt)
    -> (Skein512Ctx -> Skein_512_384_Ctx)
    -> Skein_512_384_Ctx
    forall internalCtx externalCtx.
    Storable internalCtx =>
    CSize
    -> (Ptr internalCtx -> CSize -> IO CInt)
    -> (internalCtx -> externalCtx)
    -> externalCtx
    initialCtxSkein CSize
    384 Ptr Skein512Ctx -> CSize -> IO CInt
    skein512Init Skein512Ctx -> Skein_512_384_Ctx
    S_512_384_Ctx
        updateCtx :: Skein_512_384_Ctx -> Key -> Skein_512_384_Ctx
    updateCtx    = (Ptr Skein512Ctx -> Ptr Word8 -> CSize -> IO CInt)
    -> (Skein_512_384_Ctx -> Skein512Ctx)
    -> (Skein512Ctx -> Skein_512_384_Ctx)
    -> Skein_512_384_Ctx
    -> Key
    -> Skein_512_384_Ctx
    forall internalCtx externalCtx.
    Storable internalCtx =>
    (Ptr internalCtx -> Ptr Word8 -> CSize -> IO CInt)
    -> (externalCtx -> internalCtx)
    -> (internalCtx -> externalCtx)
    -> externalCtx
    -> Key
    -> externalCtx
    updateCtxSkein Ptr Skein512Ctx -> Ptr Word8 -> CSize -> IO CInt
    skein512Update Skein_512_384_Ctx -> Skein512Ctx
    unS_512_384_Ctx Skein512Ctx -> Skein_512_384_Ctx
    S_512_384_Ctx
        finalize :: Skein_512_384_Ctx -> Key -> Skein_512_384
    finalize     = Int
    -> (Ptr Skein512Ctx -> Ptr Word8 -> CSize -> IO CInt)
    -> (Ptr Skein512Ctx -> Ptr Word8 -> IO CInt)
    -> (Skein_512_384_Ctx -> Skein512Ctx)
    -> (Key -> Skein_512_384)
    -> Skein_512_384_Ctx
    -> Key
    -> Skein_512_384
    forall internalCtx externalCtx hash.
    Storable internalCtx =>
    Int
    -> (Ptr internalCtx -> Ptr Word8 -> CSize -> IO CInt)
    -> (Ptr internalCtx -> Ptr Word8 -> IO CInt)
    -> (externalCtx -> internalCtx)
    -> (Key -> hash)
    -> externalCtx
    -> Key
    -> hash
    finalizeSkein Int
    48 Ptr Skein512Ctx -> Ptr Word8 -> CSize -> IO CInt
    skein512Update Ptr Skein512Ctx -> Ptr Word8 -> IO CInt
    skein512Final Skein_512_384_Ctx -> Skein512Ctx
    unS_512_384_Ctx Key -> Skein_512_384
    S_512_384

    instance SkeinMAC Skein_512_384_Ctx where
        skeinMACCtx :: Key -> Skein_512_384_Ctx
    skeinMACCtx = CSize
    -> (Ptr Skein512Ctx
        -> CSize -> Word64 -> Ptr Word8 -> CSize -> IO CInt)
    -> (Skein512Ctx -> Skein_512_384_Ctx)
    -> Key
    -> Skein_512_384_Ctx
    forall internalCtx externalCtx.
    Storable internalCtx =>
    CSize
    -> (Ptr internalCtx
        -> CSize -> Word64 -> Ptr Word8 -> CSize -> IO CInt)
    -> (internalCtx -> externalCtx)
    -> Key
    -> externalCtx
    skeinMACCtxSkein CSize
    384 Ptr Skein512Ctx -> CSize -> Word64 -> Ptr Word8 -> CSize -> IO CInt
    skein512InitExt Skein512Ctx -> Skein_512_384_Ctx
    S_512_384_Ctx

    -- | Context of the Skein-512-512 hash function.
    newtype Skein_512_512_Ctx = S_512_512_Ctx {Skein_512_512_Ctx -> Skein512Ctx
    unS_512_512_Ctx :: Skein512Ctx}

    -- | Skein-512-512 hash.  You probably want to use 'encode' to
    -- obtain a 512-bit (64-byte) 'B.ByteString'.  It's the main Skein
    -- hash function.  May be used as a drop-in replacement for
    -- SHA-512 as well.
    newtype Skein_512_512 = S_512_512 B.ByteString deriving (Skein_512_512 -> Skein_512_512 -> Bool
    (Skein_512_512 -> Skein_512_512 -> Bool)
    -> (Skein_512_512 -> Skein_512_512 -> Bool) -> Eq Skein_512_512
    forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
    $c== :: Skein_512_512 -> Skein_512_512 -> Bool
    == :: Skein_512_512 -> Skein_512_512 -> Bool
    $c/= :: Skein_512_512 -> Skein_512_512 -> Bool
    /= :: Skein_512_512 -> Skein_512_512 -> Bool
    Eq, Eq Skein_512_512
    Eq Skein_512_512 =>
    (Skein_512_512 -> Skein_512_512 -> Ordering)
    -> (Skein_512_512 -> Skein_512_512 -> Bool)
    -> (Skein_512_512 -> Skein_512_512 -> Bool)
    -> (Skein_512_512 -> Skein_512_512 -> Bool)
    -> (Skein_512_512 -> Skein_512_512 -> Bool)
    -> (Skein_512_512 -> Skein_512_512 -> Skein_512_512)
    -> (Skein_512_512 -> Skein_512_512 -> Skein_512_512)
    -> Ord Skein_512_512
    Skein_512_512 -> Skein_512_512 -> Bool
    Skein_512_512 -> Skein_512_512 -> Ordering
    Skein_512_512 -> Skein_512_512 -> Skein_512_512
    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 :: Skein_512_512 -> Skein_512_512 -> Ordering
    compare :: Skein_512_512 -> Skein_512_512 -> Ordering
    $c< :: Skein_512_512 -> Skein_512_512 -> Bool
    < :: Skein_512_512 -> Skein_512_512 -> Bool
    $c<= :: Skein_512_512 -> Skein_512_512 -> Bool
    <= :: Skein_512_512 -> Skein_512_512 -> Bool
    $c> :: Skein_512_512 -> Skein_512_512 -> Bool
    > :: Skein_512_512 -> Skein_512_512 -> Bool
    $c>= :: Skein_512_512 -> Skein_512_512 -> Bool
    >= :: Skein_512_512 -> Skein_512_512 -> Bool
    $cmax :: Skein_512_512 -> Skein_512_512 -> Skein_512_512
    max :: Skein_512_512 -> Skein_512_512 -> Skein_512_512
    $cmin :: Skein_512_512 -> Skein_512_512 -> Skein_512_512
    min :: Skein_512_512 -> Skein_512_512 -> Skein_512_512
    Ord)

    instance Serialize Skein_512_512 where
        put :: Putter Skein_512_512
    put (S_512_512 Key
    bs) = Putter Key
    putByteString Key
    bs
        get :: Get Skein_512_512
    get = (Key -> Skein_512_512) -> Get Key -> Get Skein_512_512
    forall a b. (a -> b) -> Get a -> Get b
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap Key -> Skein_512_512
    S_512_512 (Get Key -> Get Skein_512_512) -> Get Key -> Get Skein_512_512
    forall a b. (a -> b) -> a -> b
    $ Int -> Get Key
    getByteString Int
    64

    instance Hash Skein_512_512_Ctx Skein_512_512 where
        outputLength :: Tagged Skein_512_512 Int
    outputLength = Int -> Tagged Skein_512_512 Int
    forall {k} (s :: k) b. b -> Tagged s b
    Tagged Int
    512
        blockLength :: Tagged Skein_512_512 Int
    blockLength  = Int -> Tagged Skein_512_512 Int
    forall {k} (s :: k) b. b -> Tagged s b
    Tagged Int
    512
        initialCtx :: Skein_512_512_Ctx
    initialCtx   = CSize
    -> (Ptr Skein512Ctx -> CSize -> IO CInt)
    -> (Skein512Ctx -> Skein_512_512_Ctx)
    -> Skein_512_512_Ctx
    forall internalCtx externalCtx.
    Storable internalCtx =>
    CSize
    -> (Ptr internalCtx -> CSize -> IO CInt)
    -> (internalCtx -> externalCtx)
    -> externalCtx
    initialCtxSkein CSize
    512 Ptr Skein512Ctx -> CSize -> IO CInt
    skein512Init Skein512Ctx -> Skein_512_512_Ctx
    S_512_512_Ctx
        updateCtx :: Skein_512_512_Ctx -> Key -> Skein_512_512_Ctx
    updateCtx    = (Ptr Skein512Ctx -> Ptr Word8 -> CSize -> IO CInt)
    -> (Skein_512_512_Ctx -> Skein512Ctx)
    -> (Skein512Ctx -> Skein_512_512_Ctx)
    -> Skein_512_512_Ctx
    -> Key
    -> Skein_512_512_Ctx
    forall internalCtx externalCtx.
    Storable internalCtx =>
    (Ptr internalCtx -> Ptr Word8 -> CSize -> IO CInt)
    -> (externalCtx -> internalCtx)
    -> (internalCtx -> externalCtx)
    -> externalCtx
    -> Key
    -> externalCtx
    updateCtxSkein Ptr Skein512Ctx -> Ptr Word8 -> CSize -> IO CInt
    skein512Update Skein_512_512_Ctx -> Skein512Ctx
    unS_512_512_Ctx Skein512Ctx -> Skein_512_512_Ctx
    S_512_512_Ctx
        finalize :: Skein_512_512_Ctx -> Key -> Skein_512_512
    finalize     = Int
    -> (Ptr Skein512Ctx -> Ptr Word8 -> CSize -> IO CInt)
    -> (Ptr Skein512Ctx -> Ptr Word8 -> IO CInt)
    -> (Skein_512_512_Ctx -> Skein512Ctx)
    -> (Key -> Skein_512_512)
    -> Skein_512_512_Ctx
    -> Key
    -> Skein_512_512
    forall internalCtx externalCtx hash.
    Storable internalCtx =>
    Int
    -> (Ptr internalCtx -> Ptr Word8 -> CSize -> IO CInt)
    -> (Ptr internalCtx -> Ptr Word8 -> IO CInt)
    -> (externalCtx -> internalCtx)
    -> (Key -> hash)
    -> externalCtx
    -> Key
    -> hash
    finalizeSkein Int
    64 Ptr Skein512Ctx -> Ptr Word8 -> CSize -> IO CInt
    skein512Update Ptr Skein512Ctx -> Ptr Word8 -> IO CInt
    skein512Final Skein_512_512_Ctx -> Skein512Ctx
    unS_512_512_Ctx Key -> Skein_512_512
    S_512_512

    instance SkeinMAC Skein_512_512_Ctx where
        skeinMACCtx :: Key -> Skein_512_512_Ctx
    skeinMACCtx = CSize
    -> (Ptr Skein512Ctx
        -> CSize -> Word64 -> Ptr Word8 -> CSize -> IO CInt)
    -> (Skein512Ctx -> Skein_512_512_Ctx)
    -> Key
    -> Skein_512_512_Ctx
    forall internalCtx externalCtx.
    Storable internalCtx =>
    CSize
    -> (Ptr internalCtx
        -> CSize -> Word64 -> Ptr Word8 -> CSize -> IO CInt)
    -> (internalCtx -> externalCtx)
    -> Key
    -> externalCtx
    skeinMACCtxSkein CSize
    512 Ptr Skein512Ctx -> CSize -> Word64 -> Ptr Word8 -> CSize -> IO CInt
    skein512InitExt Skein512Ctx -> Skein_512_512_Ctx
    S_512_512_Ctx

    ----------------------------------------------------------------------
    -- Skein-1024
    ----------------------------------------------------------------------

    -- | Context of the Skein-1024-384 hash function.
    newtype Skein_1024_384_Ctx = S_1024_384_Ctx {Skein_1024_384_Ctx -> Skein1024Ctx
    unS_1024_384_Ctx :: Skein1024Ctx}

    -- | Skein-1024-384 hash.  You probably want to use 'encode' to
    -- obtain a 384-bit (48-byte) 'B.ByteString'.  May be used as a
    -- drop-in replacement for SHA-384.
    newtype Skein_1024_384 = S_1024_384 B.ByteString deriving (Skein_1024_384 -> Skein_1024_384 -> Bool
    (Skein_1024_384 -> Skein_1024_384 -> Bool)
    -> (Skein_1024_384 -> Skein_1024_384 -> Bool) -> Eq Skein_1024_384
    forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
    $c== :: Skein_1024_384 -> Skein_1024_384 -> Bool
    == :: Skein_1024_384 -> Skein_1024_384 -> Bool
    $c/= :: Skein_1024_384 -> Skein_1024_384 -> Bool
    /= :: Skein_1024_384 -> Skein_1024_384 -> Bool
    Eq, Eq Skein_1024_384
    Eq Skein_1024_384 =>
    (Skein_1024_384 -> Skein_1024_384 -> Ordering)
    -> (Skein_1024_384 -> Skein_1024_384 -> Bool)
    -> (Skein_1024_384 -> Skein_1024_384 -> Bool)
    -> (Skein_1024_384 -> Skein_1024_384 -> Bool)
    -> (Skein_1024_384 -> Skein_1024_384 -> Bool)
    -> (Skein_1024_384 -> Skein_1024_384 -> Skein_1024_384)
    -> (Skein_1024_384 -> Skein_1024_384 -> Skein_1024_384)
    -> Ord Skein_1024_384
    Skein_1024_384 -> Skein_1024_384 -> Bool
    Skein_1024_384 -> Skein_1024_384 -> Ordering
    Skein_1024_384 -> Skein_1024_384 -> Skein_1024_384
    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 :: Skein_1024_384 -> Skein_1024_384 -> Ordering
    compare :: Skein_1024_384 -> Skein_1024_384 -> Ordering
    $c< :: Skein_1024_384 -> Skein_1024_384 -> Bool
    < :: Skein_1024_384 -> Skein_1024_384 -> Bool
    $c<= :: Skein_1024_384 -> Skein_1024_384 -> Bool
    <= :: Skein_1024_384 -> Skein_1024_384 -> Bool
    $c> :: Skein_1024_384 -> Skein_1024_384 -> Bool
    > :: Skein_1024_384 -> Skein_1024_384 -> Bool
    $c>= :: Skein_1024_384 -> Skein_1024_384 -> Bool
    >= :: Skein_1024_384 -> Skein_1024_384 -> Bool
    $cmax :: Skein_1024_384 -> Skein_1024_384 -> Skein_1024_384
    max :: Skein_1024_384 -> Skein_1024_384 -> Skein_1024_384
    $cmin :: Skein_1024_384 -> Skein_1024_384 -> Skein_1024_384
    min :: Skein_1024_384 -> Skein_1024_384 -> Skein_1024_384
    Ord)

    instance Serialize Skein_1024_384 where
        put :: Putter Skein_1024_384
    put (S_1024_384 Key
    bs) = Putter Key
    putByteString Key
    bs
        get :: Get Skein_1024_384
    get = (Key -> Skein_1024_384) -> Get Key -> Get Skein_1024_384
    forall a b. (a -> b) -> Get a -> Get b
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap Key -> Skein_1024_384
    S_1024_384 (Get Key -> Get Skein_1024_384) -> Get Key -> Get Skein_1024_384
    forall a b. (a -> b) -> a -> b
    $ Int -> Get Key
    getByteString Int
    48

    instance Hash Skein_1024_384_Ctx Skein_1024_384 where
        outputLength :: Tagged Skein_1024_384 Int
    outputLength = Int -> Tagged Skein_1024_384 Int
    forall {k} (s :: k) b. b -> Tagged s b
    Tagged Int
    384
        blockLength :: Tagged Skein_1024_384 Int
    blockLength  = Int -> Tagged Skein_1024_384 Int
    forall {k} (s :: k) b. b -> Tagged s b
    Tagged Int
    1024
        initialCtx :: Skein_1024_384_Ctx
    initialCtx   = CSize
    -> (Ptr Skein1024Ctx -> CSize -> IO CInt)
    -> (Skein1024Ctx -> Skein_1024_384_Ctx)
    -> Skein_1024_384_Ctx
    forall internalCtx externalCtx.
    Storable internalCtx =>
    CSize
    -> (Ptr internalCtx -> CSize -> IO CInt)
    -> (internalCtx -> externalCtx)
    -> externalCtx
    initialCtxSkein CSize
    384 Ptr Skein1024Ctx -> CSize -> IO CInt
    skein1024Init Skein1024Ctx -> Skein_1024_384_Ctx
    S_1024_384_Ctx
        updateCtx :: Skein_1024_384_Ctx -> Key -> Skein_1024_384_Ctx
    updateCtx    = (Ptr Skein1024Ctx -> Ptr Word8 -> CSize -> IO CInt)
    -> (Skein_1024_384_Ctx -> Skein1024Ctx)
    -> (Skein1024Ctx -> Skein_1024_384_Ctx)
    -> Skein_1024_384_Ctx
    -> Key
    -> Skein_1024_384_Ctx
    forall internalCtx externalCtx.
    Storable internalCtx =>
    (Ptr internalCtx -> Ptr Word8 -> CSize -> IO CInt)
    -> (externalCtx -> internalCtx)
    -> (internalCtx -> externalCtx)
    -> externalCtx
    -> Key
    -> externalCtx
    updateCtxSkein Ptr Skein1024Ctx -> Ptr Word8 -> CSize -> IO CInt
    skein1024Update Skein_1024_384_Ctx -> Skein1024Ctx
    unS_1024_384_Ctx Skein1024Ctx -> Skein_1024_384_Ctx
    S_1024_384_Ctx
        finalize :: Skein_1024_384_Ctx -> Key -> Skein_1024_384
    finalize     = Int
    -> (Ptr Skein1024Ctx -> Ptr Word8 -> CSize -> IO CInt)
    -> (Ptr Skein1024Ctx -> Ptr Word8 -> IO CInt)
    -> (Skein_1024_384_Ctx -> Skein1024Ctx)
    -> (Key -> Skein_1024_384)
    -> Skein_1024_384_Ctx
    -> Key
    -> Skein_1024_384
    forall internalCtx externalCtx hash.
    Storable internalCtx =>
    Int
    -> (Ptr internalCtx -> Ptr Word8 -> CSize -> IO CInt)
    -> (Ptr internalCtx -> Ptr Word8 -> IO CInt)
    -> (externalCtx -> internalCtx)
    -> (Key -> hash)
    -> externalCtx
    -> Key
    -> hash
    finalizeSkein Int
    48 Ptr Skein1024Ctx -> Ptr Word8 -> CSize -> IO CInt
    skein1024Update Ptr Skein1024Ctx -> Ptr Word8 -> IO CInt
    skein1024Final Skein_1024_384_Ctx -> Skein1024Ctx
    unS_1024_384_Ctx Key -> Skein_1024_384
    S_1024_384

    instance SkeinMAC Skein_1024_384_Ctx where
        skeinMACCtx :: Key -> Skein_1024_384_Ctx
    skeinMACCtx = CSize
    -> (Ptr Skein1024Ctx
        -> CSize -> Word64 -> Ptr Word8 -> CSize -> IO CInt)
    -> (Skein1024Ctx -> Skein_1024_384_Ctx)
    -> Key
    -> Skein_1024_384_Ctx
    forall internalCtx externalCtx.
    Storable internalCtx =>
    CSize
    -> (Ptr internalCtx
        -> CSize -> Word64 -> Ptr Word8 -> CSize -> IO CInt)
    -> (internalCtx -> externalCtx)
    -> Key
    -> externalCtx
    skeinMACCtxSkein CSize
    384 Ptr Skein1024Ctx
    -> CSize -> Word64 -> Ptr Word8 -> CSize -> IO CInt
    skein1024InitExt Skein1024Ctx -> Skein_1024_384_Ctx
    S_1024_384_Ctx

    -- | Context of the Skein-1024-512 hash function.
    newtype Skein_1024_512_Ctx = S_1024_512_Ctx {Skein_1024_512_Ctx -> Skein1024Ctx
    unS_1024_512_Ctx :: Skein1024Ctx}

    -- | Skein-1024-512 hash.  You probably want to use 'encode' to
    -- obtain a 512-bit (64-byte) 'B.ByteString'.  May be used as a
    -- drop-in replacement for SHA-512.
    newtype Skein_1024_512 = S_1024_512 B.ByteString deriving (Skein_1024_512 -> Skein_1024_512 -> Bool
    (Skein_1024_512 -> Skein_1024_512 -> Bool)
    -> (Skein_1024_512 -> Skein_1024_512 -> Bool) -> Eq Skein_1024_512
    forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
    $c== :: Skein_1024_512 -> Skein_1024_512 -> Bool
    == :: Skein_1024_512 -> Skein_1024_512 -> Bool
    $c/= :: Skein_1024_512 -> Skein_1024_512 -> Bool
    /= :: Skein_1024_512 -> Skein_1024_512 -> Bool
    Eq, Eq Skein_1024_512
    Eq Skein_1024_512 =>
    (Skein_1024_512 -> Skein_1024_512 -> Ordering)
    -> (Skein_1024_512 -> Skein_1024_512 -> Bool)
    -> (Skein_1024_512 -> Skein_1024_512 -> Bool)
    -> (Skein_1024_512 -> Skein_1024_512 -> Bool)
    -> (Skein_1024_512 -> Skein_1024_512 -> Bool)
    -> (Skein_1024_512 -> Skein_1024_512 -> Skein_1024_512)
    -> (Skein_1024_512 -> Skein_1024_512 -> Skein_1024_512)
    -> Ord Skein_1024_512
    Skein_1024_512 -> Skein_1024_512 -> Bool
    Skein_1024_512 -> Skein_1024_512 -> Ordering
    Skein_1024_512 -> Skein_1024_512 -> Skein_1024_512
    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 :: Skein_1024_512 -> Skein_1024_512 -> Ordering
    compare :: Skein_1024_512 -> Skein_1024_512 -> Ordering
    $c< :: Skein_1024_512 -> Skein_1024_512 -> Bool
    < :: Skein_1024_512 -> Skein_1024_512 -> Bool
    $c<= :: Skein_1024_512 -> Skein_1024_512 -> Bool
    <= :: Skein_1024_512 -> Skein_1024_512 -> Bool
    $c> :: Skein_1024_512 -> Skein_1024_512 -> Bool
    > :: Skein_1024_512 -> Skein_1024_512 -> Bool
    $c>= :: Skein_1024_512 -> Skein_1024_512 -> Bool
    >= :: Skein_1024_512 -> Skein_1024_512 -> Bool
    $cmax :: Skein_1024_512 -> Skein_1024_512 -> Skein_1024_512
    max :: Skein_1024_512 -> Skein_1024_512 -> Skein_1024_512
    $cmin :: Skein_1024_512 -> Skein_1024_512 -> Skein_1024_512
    min :: Skein_1024_512 -> Skein_1024_512 -> Skein_1024_512
    Ord)

    instance Serialize Skein_1024_512 where
        put :: Putter Skein_1024_512
    put (S_1024_512 Key
    bs) = Putter Key
    putByteString Key
    bs
        get :: Get Skein_1024_512
    get = (Key -> Skein_1024_512) -> Get Key -> Get Skein_1024_512
    forall a b. (a -> b) -> Get a -> Get b
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap Key -> Skein_1024_512
    S_1024_512 (Get Key -> Get Skein_1024_512) -> Get Key -> Get Skein_1024_512
    forall a b. (a -> b) -> a -> b
    $ Int -> Get Key
    getByteString Int
    64

    instance Hash Skein_1024_512_Ctx Skein_1024_512 where
        outputLength :: Tagged Skein_1024_512 Int
    outputLength = Int -> Tagged Skein_1024_512 Int
    forall {k} (s :: k) b. b -> Tagged s b
    Tagged Int
    512
        blockLength :: Tagged Skein_1024_512 Int
    blockLength  = Int -> Tagged Skein_1024_512 Int
    forall {k} (s :: k) b. b -> Tagged s b
    Tagged Int
    1024
        initialCtx :: Skein_1024_512_Ctx
    initialCtx   = CSize
    -> (Ptr Skein1024Ctx -> CSize -> IO CInt)
    -> (Skein1024Ctx -> Skein_1024_512_Ctx)
    -> Skein_1024_512_Ctx
    forall internalCtx externalCtx.
    Storable internalCtx =>
    CSize
    -> (Ptr internalCtx -> CSize -> IO CInt)
    -> (internalCtx -> externalCtx)
    -> externalCtx
    initialCtxSkein CSize
    512 Ptr Skein1024Ctx -> CSize -> IO CInt
    skein1024Init Skein1024Ctx -> Skein_1024_512_Ctx
    S_1024_512_Ctx
        updateCtx :: Skein_1024_512_Ctx -> Key -> Skein_1024_512_Ctx
    updateCtx    = (Ptr Skein1024Ctx -> Ptr Word8 -> CSize -> IO CInt)
    -> (Skein_1024_512_Ctx -> Skein1024Ctx)
    -> (Skein1024Ctx -> Skein_1024_512_Ctx)
    -> Skein_1024_512_Ctx
    -> Key
    -> Skein_1024_512_Ctx
    forall internalCtx externalCtx.
    Storable internalCtx =>
    (Ptr internalCtx -> Ptr Word8 -> CSize -> IO CInt)
    -> (externalCtx -> internalCtx)
    -> (internalCtx -> externalCtx)
    -> externalCtx
    -> Key
    -> externalCtx
    updateCtxSkein Ptr Skein1024Ctx -> Ptr Word8 -> CSize -> IO CInt
    skein1024Update Skein_1024_512_Ctx -> Skein1024Ctx
    unS_1024_512_Ctx Skein1024Ctx -> Skein_1024_512_Ctx
    S_1024_512_Ctx
        finalize :: Skein_1024_512_Ctx -> Key -> Skein_1024_512
    finalize     = Int
    -> (Ptr Skein1024Ctx -> Ptr Word8 -> CSize -> IO CInt)
    -> (Ptr Skein1024Ctx -> Ptr Word8 -> IO CInt)
    -> (Skein_1024_512_Ctx -> Skein1024Ctx)
    -> (Key -> Skein_1024_512)
    -> Skein_1024_512_Ctx
    -> Key
    -> Skein_1024_512
    forall internalCtx externalCtx hash.
    Storable internalCtx =>
    Int
    -> (Ptr internalCtx -> Ptr Word8 -> CSize -> IO CInt)
    -> (Ptr internalCtx -> Ptr Word8 -> IO CInt)
    -> (externalCtx -> internalCtx)
    -> (Key -> hash)
    -> externalCtx
    -> Key
    -> hash
    finalizeSkein Int
    64 Ptr Skein1024Ctx -> Ptr Word8 -> CSize -> IO CInt
    skein1024Update Ptr Skein1024Ctx -> Ptr Word8 -> IO CInt
    skein1024Final Skein_1024_512_Ctx -> Skein1024Ctx
    unS_1024_512_Ctx Key -> Skein_1024_512
    S_1024_512

    instance SkeinMAC Skein_1024_512_Ctx where
        skeinMACCtx :: Key -> Skein_1024_512_Ctx
    skeinMACCtx = CSize
    -> (Ptr Skein1024Ctx
        -> CSize -> Word64 -> Ptr Word8 -> CSize -> IO CInt)
    -> (Skein1024Ctx -> Skein_1024_512_Ctx)
    -> Key
    -> Skein_1024_512_Ctx
    forall internalCtx externalCtx.
    Storable internalCtx =>
    CSize
    -> (Ptr internalCtx
        -> CSize -> Word64 -> Ptr Word8 -> CSize -> IO CInt)
    -> (internalCtx -> externalCtx)
    -> Key
    -> externalCtx
    skeinMACCtxSkein CSize
    512 Ptr Skein1024Ctx
    -> CSize -> Word64 -> Ptr Word8 -> CSize -> IO CInt
    skein1024InitExt Skein1024Ctx -> Skein_1024_512_Ctx
    S_1024_512_Ctx

    -- | Context of the Skein-1024-1024 hash function.
    newtype Skein_1024_1024_Ctx = S_1024_1024_Ctx {Skein_1024_1024_Ctx -> Skein1024Ctx
    unS_1024_1024_Ctx :: Skein1024Ctx}

    -- | Skein-1024-1024 hash.  You probably want to use 'encode' to
    -- obtain a 1024-bit (128-byte) 'B.ByteString'.  This is the
    -- ultra-conservative variant.  Even if some future attack
    -- managed to break Skein-512, it's quite likely that Skein-1024
    -- would remain secure.
    newtype Skein_1024_1024 = S_1024_1024 B.ByteString deriving (Skein_1024_1024 -> Skein_1024_1024 -> Bool
    (Skein_1024_1024 -> Skein_1024_1024 -> Bool)
    -> (Skein_1024_1024 -> Skein_1024_1024 -> Bool)
    -> Eq Skein_1024_1024
    forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
    $c== :: Skein_1024_1024 -> Skein_1024_1024 -> Bool
    == :: Skein_1024_1024 -> Skein_1024_1024 -> Bool
    $c/= :: Skein_1024_1024 -> Skein_1024_1024 -> Bool
    /= :: Skein_1024_1024 -> Skein_1024_1024 -> Bool
    Eq, Eq Skein_1024_1024
    Eq Skein_1024_1024 =>
    (Skein_1024_1024 -> Skein_1024_1024 -> Ordering)
    -> (Skein_1024_1024 -> Skein_1024_1024 -> Bool)
    -> (Skein_1024_1024 -> Skein_1024_1024 -> Bool)
    -> (Skein_1024_1024 -> Skein_1024_1024 -> Bool)
    -> (Skein_1024_1024 -> Skein_1024_1024 -> Bool)
    -> (Skein_1024_1024 -> Skein_1024_1024 -> Skein_1024_1024)
    -> (Skein_1024_1024 -> Skein_1024_1024 -> Skein_1024_1024)
    -> Ord Skein_1024_1024
    Skein_1024_1024 -> Skein_1024_1024 -> Bool
    Skein_1024_1024 -> Skein_1024_1024 -> Ordering
    Skein_1024_1024 -> Skein_1024_1024 -> Skein_1024_1024
    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 :: Skein_1024_1024 -> Skein_1024_1024 -> Ordering
    compare :: Skein_1024_1024 -> Skein_1024_1024 -> Ordering
    $c< :: Skein_1024_1024 -> Skein_1024_1024 -> Bool
    < :: Skein_1024_1024 -> Skein_1024_1024 -> Bool
    $c<= :: Skein_1024_1024 -> Skein_1024_1024 -> Bool
    <= :: Skein_1024_1024 -> Skein_1024_1024 -> Bool
    $c> :: Skein_1024_1024 -> Skein_1024_1024 -> Bool
    > :: Skein_1024_1024 -> Skein_1024_1024 -> Bool
    $c>= :: Skein_1024_1024 -> Skein_1024_1024 -> Bool
    >= :: Skein_1024_1024 -> Skein_1024_1024 -> Bool
    $cmax :: Skein_1024_1024 -> Skein_1024_1024 -> Skein_1024_1024
    max :: Skein_1024_1024 -> Skein_1024_1024 -> Skein_1024_1024
    $cmin :: Skein_1024_1024 -> Skein_1024_1024 -> Skein_1024_1024
    min :: Skein_1024_1024 -> Skein_1024_1024 -> Skein_1024_1024
    Ord)

    instance Serialize Skein_1024_1024 where
        put :: Putter Skein_1024_1024
    put (S_1024_1024 Key
    bs) = Putter Key
    putByteString Key
    bs
        get :: Get Skein_1024_1024
    get = (Key -> Skein_1024_1024) -> Get Key -> Get Skein_1024_1024
    forall a b. (a -> b) -> Get a -> Get b
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap Key -> Skein_1024_1024
    S_1024_1024 (Get Key -> Get Skein_1024_1024) -> Get Key -> Get Skein_1024_1024
    forall a b. (a -> b) -> a -> b
    $ Int -> Get Key
    getByteString Int
    128

    instance Hash Skein_1024_1024_Ctx Skein_1024_1024 where
        outputLength :: Tagged Skein_1024_1024 Int
    outputLength = Int -> Tagged Skein_1024_1024 Int
    forall {k} (s :: k) b. b -> Tagged s b
    Tagged Int
    1024
        blockLength :: Tagged Skein_1024_1024 Int
    blockLength  = Int -> Tagged Skein_1024_1024 Int
    forall {k} (s :: k) b. b -> Tagged s b
    Tagged Int
    1024
        initialCtx :: Skein_1024_1024_Ctx
    initialCtx   = CSize
    -> (Ptr Skein1024Ctx -> CSize -> IO CInt)
    -> (Skein1024Ctx -> Skein_1024_1024_Ctx)
    -> Skein_1024_1024_Ctx
    forall internalCtx externalCtx.
    Storable internalCtx =>
    CSize
    -> (Ptr internalCtx -> CSize -> IO CInt)
    -> (internalCtx -> externalCtx)
    -> externalCtx
    initialCtxSkein CSize
    1024 Ptr Skein1024Ctx -> CSize -> IO CInt
    skein1024Init Skein1024Ctx -> Skein_1024_1024_Ctx
    S_1024_1024_Ctx
        updateCtx :: Skein_1024_1024_Ctx -> Key -> Skein_1024_1024_Ctx
    updateCtx    = (Ptr Skein1024Ctx -> Ptr Word8 -> CSize -> IO CInt)
    -> (Skein_1024_1024_Ctx -> Skein1024Ctx)
    -> (Skein1024Ctx -> Skein_1024_1024_Ctx)
    -> Skein_1024_1024_Ctx
    -> Key
    -> Skein_1024_1024_Ctx
    forall internalCtx externalCtx.
    Storable internalCtx =>
    (Ptr internalCtx -> Ptr Word8 -> CSize -> IO CInt)
    -> (externalCtx -> internalCtx)
    -> (internalCtx -> externalCtx)
    -> externalCtx
    -> Key
    -> externalCtx
    updateCtxSkein Ptr Skein1024Ctx -> Ptr Word8 -> CSize -> IO CInt
    skein1024Update Skein_1024_1024_Ctx -> Skein1024Ctx
    unS_1024_1024_Ctx Skein1024Ctx -> Skein_1024_1024_Ctx
    S_1024_1024_Ctx
        finalize :: Skein_1024_1024_Ctx -> Key -> Skein_1024_1024
    finalize     = Int
    -> (Ptr Skein1024Ctx -> Ptr Word8 -> CSize -> IO CInt)
    -> (Ptr Skein1024Ctx -> Ptr Word8 -> IO CInt)
    -> (Skein_1024_1024_Ctx -> Skein1024Ctx)
    -> (Key -> Skein_1024_1024)
    -> Skein_1024_1024_Ctx
    -> Key
    -> Skein_1024_1024
    forall internalCtx externalCtx hash.
    Storable internalCtx =>
    Int
    -> (Ptr internalCtx -> Ptr Word8 -> CSize -> IO CInt)
    -> (Ptr internalCtx -> Ptr Word8 -> IO CInt)
    -> (externalCtx -> internalCtx)
    -> (Key -> hash)
    -> externalCtx
    -> Key
    -> hash
    finalizeSkein Int
    128 Ptr Skein1024Ctx -> Ptr Word8 -> CSize -> IO CInt
    skein1024Update Ptr Skein1024Ctx -> Ptr Word8 -> IO CInt
    skein1024Final Skein_1024_1024_Ctx -> Skein1024Ctx
    unS_1024_1024_Ctx Key -> Skein_1024_1024
    S_1024_1024

    instance SkeinMAC Skein_1024_1024_Ctx where
        skeinMACCtx :: Key -> Skein_1024_1024_Ctx
    skeinMACCtx = CSize
    -> (Ptr Skein1024Ctx
        -> CSize -> Word64 -> Ptr Word8 -> CSize -> IO CInt)
    -> (Skein1024Ctx -> Skein_1024_1024_Ctx)
    -> Key
    -> Skein_1024_1024_Ctx
    forall internalCtx externalCtx.
    Storable internalCtx =>
    CSize
    -> (Ptr internalCtx
        -> CSize -> Word64 -> Ptr Word8 -> CSize -> IO CInt)
    -> (internalCtx -> externalCtx)
    -> Key
    -> externalCtx
    skeinMACCtxSkein CSize
    1024 Ptr Skein1024Ctx
    -> CSize -> Word64 -> Ptr Word8 -> CSize -> IO CInt
    skein1024InitExt Skein1024Ctx -> Skein_1024_1024_Ctx
    S_1024_1024_Ctx