    {-# LANGUAGE DeriveDataTypeable         #-}
    {-# LANGUAGE DeriveGeneric              #-}
    {-# LANGUAGE GeneralizedNewtypeDeriving #-}

    {-| This module provides implementations of cryptographic utilities that only
        work for GHC (as opposed to GHCJS)
    -}

    module Dhall.Crypto (
          SHA256Digest(..)
        , sha256DigestFromByteString
        , sha256Hash
        , toString
        ) where

    import Control.DeepSeq         (NFData)
    import Data.ByteString         (ByteString)
    import Data.Data               (Data)
    import GHC.Generics            (Generic)

    import qualified Crypto.Hash.SHA256
    import qualified Data.ByteString        as ByteString
    import qualified Data.ByteString.Base16 as Base16
    import qualified Data.ByteString.Char8  as ByteString.Char8

    -- | A SHA256 digest
    newtype SHA256Digest = SHA256Digest { SHA256Digest -> ByteString
    unSHA256Digest :: ByteString }
      deriving (Typeable SHA256Digest
    Typeable SHA256Digest =>
    (forall (c :: * -> *).
     (forall d b. Data d => c (d -> b) -> d -> c b)
     -> (forall g. g -> c g) -> SHA256Digest -> c SHA256Digest)
    -> (forall (c :: * -> *).
        (forall b r. Data b => c (b -> r) -> c r)
        -> (forall r. r -> c r) -> Constr -> c SHA256Digest)
    -> (SHA256Digest -> Constr)
    -> (SHA256Digest -> DataType)
    -> (forall (t :: * -> *) (c :: * -> *).
        Typeable t =>
        (forall d. Data d => c (t d)) -> Maybe (c SHA256Digest))
    -> (forall (t :: * -> * -> *) (c :: * -> *).
        Typeable t =>
        (forall d e. (Data d, Data e) => c (t d e))
        -> Maybe (c SHA256Digest))
    -> ((forall b. Data b => b -> b) -> SHA256Digest -> SHA256Digest)
    -> (forall r r'.
        (r -> r' -> r)
        -> r -> (forall d. Data d => d -> r') -> SHA256Digest -> r)
    -> (forall r r'.
        (r' -> r -> r)
        -> r -> (forall d. Data d => d -> r') -> SHA256Digest -> r)
    -> (forall u. (forall d. Data d => d -> u) -> SHA256Digest -> [u])
    -> (forall u.
        Int -> (forall d. Data d => d -> u) -> SHA256Digest -> u)
    -> (forall (m :: * -> *).
        Monad m =>
        (forall d. Data d => d -> m d) -> SHA256Digest -> m SHA256Digest)
    -> (forall (m :: * -> *).
        MonadPlus m =>
        (forall d. Data d => d -> m d) -> SHA256Digest -> m SHA256Digest)
    -> (forall (m :: * -> *).
        MonadPlus m =>
        (forall d. Data d => d -> m d) -> SHA256Digest -> m SHA256Digest)
    -> Data SHA256Digest
    SHA256Digest -> Constr
    SHA256Digest -> DataType
    (forall b. Data b => b -> b) -> SHA256Digest -> SHA256Digest
    forall a.
    Typeable a =>
    (forall (c :: * -> *).
     (forall d b. Data d => c (d -> b) -> d -> c b)
     -> (forall g. g -> c g) -> a -> c a)
    -> (forall (c :: * -> *).
        (forall b r. Data b => c (b -> r) -> c r)
        -> (forall r. r -> c r) -> Constr -> c a)
    -> (a -> Constr)
    -> (a -> DataType)
    -> (forall (t :: * -> *) (c :: * -> *).
        Typeable t =>
        (forall d. Data d => c (t d)) -> Maybe (c a))
    -> (forall (t :: * -> * -> *) (c :: * -> *).
        Typeable t =>
        (forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c a))
    -> ((forall b. Data b => b -> b) -> a -> a)
    -> (forall r r'.
        (r -> r' -> r) -> r -> (forall d. Data d => d -> r') -> a -> r)
    -> (forall r r'.
        (r' -> r -> r) -> r -> (forall d. Data d => d -> r') -> a -> r)
    -> (forall u. (forall d. Data d => d -> u) -> a -> [u])
    -> (forall u. Int -> (forall d. Data d => d -> u) -> a -> u)
    -> (forall (m :: * -> *).
        Monad m =>
        (forall d. Data d => d -> m d) -> a -> m a)
    -> (forall (m :: * -> *).
        MonadPlus m =>
        (forall d. Data d => d -> m d) -> a -> m a)
    -> (forall (m :: * -> *).
        MonadPlus m =>
        (forall d. Data d => d -> m d) -> a -> m a)
    -> Data a
    forall u. Int -> (forall d. Data d => d -> u) -> SHA256Digest -> u
    forall u. (forall d. Data d => d -> u) -> SHA256Digest -> [u]
    forall r r'.
    (r -> r' -> r)
    -> r -> (forall d. Data d => d -> r') -> SHA256Digest -> r
    forall r r'.
    (r' -> r -> r)
    -> r -> (forall d. Data d => d -> r') -> SHA256Digest -> r
    forall (m :: * -> *).
    Monad m =>
    (forall d. Data d => d -> m d) -> SHA256Digest -> m SHA256Digest
    forall (m :: * -> *).
    MonadPlus m =>
    (forall d. Data d => d -> m d) -> SHA256Digest -> m SHA256Digest
    forall (c :: * -> *).
    (forall b r. Data b => c (b -> r) -> c r)
    -> (forall r. r -> c r) -> Constr -> c SHA256Digest
    forall (c :: * -> *).
    (forall d b. Data d => c (d -> b) -> d -> c b)
    -> (forall g. g -> c g) -> SHA256Digest -> c SHA256Digest
    forall (t :: * -> *) (c :: * -> *).
    Typeable t =>
    (forall d. Data d => c (t d)) -> Maybe (c SHA256Digest)
    forall (t :: * -> * -> *) (c :: * -> *).
    Typeable t =>
    (forall d e. (Data d, Data e) => c (t d e))
    -> Maybe (c SHA256Digest)
    $cgfoldl :: forall (c :: * -> *).
    (forall d b. Data d => c (d -> b) -> d -> c b)
    -> (forall g. g -> c g) -> SHA256Digest -> c SHA256Digest
    gfoldl :: forall (c :: * -> *).
    (forall d b. Data d => c (d -> b) -> d -> c b)
    -> (forall g. g -> c g) -> SHA256Digest -> c SHA256Digest
    $cgunfold :: forall (c :: * -> *).
    (forall b r. Data b => c (b -> r) -> c r)
    -> (forall r. r -> c r) -> Constr -> c SHA256Digest
    gunfold :: forall (c :: * -> *).
    (forall b r. Data b => c (b -> r) -> c r)
    -> (forall r. r -> c r) -> Constr -> c SHA256Digest
    $ctoConstr :: SHA256Digest -> Constr
    toConstr :: SHA256Digest -> Constr
    $cdataTypeOf :: SHA256Digest -> DataType
    dataTypeOf :: SHA256Digest -> DataType
    $cdataCast1 :: forall (t :: * -> *) (c :: * -> *).
    Typeable t =>
    (forall d. Data d => c (t d)) -> Maybe (c SHA256Digest)
    dataCast1 :: forall (t :: * -> *) (c :: * -> *).
    Typeable t =>
    (forall d. Data d => c (t d)) -> Maybe (c SHA256Digest)
    $cdataCast2 :: forall (t :: * -> * -> *) (c :: * -> *).
    Typeable t =>
    (forall d e. (Data d, Data e) => c (t d e))
    -> Maybe (c SHA256Digest)
    dataCast2 :: forall (t :: * -> * -> *) (c :: * -> *).
    Typeable t =>
    (forall d e. (Data d, Data e) => c (t d e))
    -> Maybe (c SHA256Digest)
    $cgmapT :: (forall b. Data b => b -> b) -> SHA256Digest -> SHA256Digest
    gmapT :: (forall b. Data b => b -> b) -> SHA256Digest -> SHA256Digest
    $cgmapQl :: forall r r'.
    (r -> r' -> r)
    -> r -> (forall d. Data d => d -> r') -> SHA256Digest -> r
    gmapQl :: forall r r'.
    (r -> r' -> r)
    -> r -> (forall d. Data d => d -> r') -> SHA256Digest -> r
    $cgmapQr :: forall r r'.
    (r' -> r -> r)
    -> r -> (forall d. Data d => d -> r') -> SHA256Digest -> r
    gmapQr :: forall r r'.
    (r' -> r -> r)
    -> r -> (forall d. Data d => d -> r') -> SHA256Digest -> r
    $cgmapQ :: forall u. (forall d. Data d => d -> u) -> SHA256Digest -> [u]
    gmapQ :: forall u. (forall d. Data d => d -> u) -> SHA256Digest -> [u]
    $cgmapQi :: forall u. Int -> (forall d. Data d => d -> u) -> SHA256Digest -> u
    gmapQi :: forall u. Int -> (forall d. Data d => d -> u) -> SHA256Digest -> u
    $cgmapM :: forall (m :: * -> *).
    Monad m =>
    (forall d. Data d => d -> m d) -> SHA256Digest -> m SHA256Digest
    gmapM :: forall (m :: * -> *).
    Monad m =>
    (forall d. Data d => d -> m d) -> SHA256Digest -> m SHA256Digest
    $cgmapMp :: forall (m :: * -> *).
    MonadPlus m =>
    (forall d. Data d => d -> m d) -> SHA256Digest -> m SHA256Digest
    gmapMp :: forall (m :: * -> *).
    MonadPlus m =>
    (forall d. Data d => d -> m d) -> SHA256Digest -> m SHA256Digest
    $cgmapMo :: forall (m :: * -> *).
    MonadPlus m =>
    (forall d. Data d => d -> m d) -> SHA256Digest -> m SHA256Digest
    gmapMo :: forall (m :: * -> *).
    MonadPlus m =>
    (forall d. Data d => d -> m d) -> SHA256Digest -> m SHA256Digest
    Data, SHA256Digest -> SHA256Digest -> Bool
    (SHA256Digest -> SHA256Digest -> Bool)
    -> (SHA256Digest -> SHA256Digest -> Bool) -> Eq SHA256Digest
    forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
    $c== :: SHA256Digest -> SHA256Digest -> Bool
    == :: SHA256Digest -> SHA256Digest -> Bool
    $c/= :: SHA256Digest -> SHA256Digest -> Bool
    /= :: SHA256Digest -> SHA256Digest -> Bool
    Eq, (forall x. SHA256Digest -> Rep SHA256Digest x)
    -> (forall x. Rep SHA256Digest x -> SHA256Digest)
    -> Generic SHA256Digest
    forall x. Rep SHA256Digest x -> SHA256Digest
    forall x. SHA256Digest -> Rep SHA256Digest x
    forall a.
    (forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
    $cfrom :: forall x. SHA256Digest -> Rep SHA256Digest x
    from :: forall x. SHA256Digest -> Rep SHA256Digest x
    $cto :: forall x. Rep SHA256Digest x -> SHA256Digest
    to :: forall x. Rep SHA256Digest x -> SHA256Digest
    Generic, Eq SHA256Digest
    Eq SHA256Digest =>
    (SHA256Digest -> SHA256Digest -> Ordering)
    -> (SHA256Digest -> SHA256Digest -> Bool)
    -> (SHA256Digest -> SHA256Digest -> Bool)
    -> (SHA256Digest -> SHA256Digest -> Bool)
    -> (SHA256Digest -> SHA256Digest -> Bool)
    -> (SHA256Digest -> SHA256Digest -> SHA256Digest)
    -> (SHA256Digest -> SHA256Digest -> SHA256Digest)
    -> Ord SHA256Digest
    SHA256Digest -> SHA256Digest -> Bool
    SHA256Digest -> SHA256Digest -> Ordering
    SHA256Digest -> SHA256Digest -> SHA256Digest
    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 :: SHA256Digest -> SHA256Digest -> Ordering
    compare :: SHA256Digest -> SHA256Digest -> Ordering
    $c< :: SHA256Digest -> SHA256Digest -> Bool
    < :: SHA256Digest -> SHA256Digest -> Bool
    $c<= :: SHA256Digest -> SHA256Digest -> Bool
    <= :: SHA256Digest -> SHA256Digest -> Bool
    $c> :: SHA256Digest -> SHA256Digest -> Bool
    > :: SHA256Digest -> SHA256Digest -> Bool
    $c>= :: SHA256Digest -> SHA256Digest -> Bool
    >= :: SHA256Digest -> SHA256Digest -> Bool
    $cmax :: SHA256Digest -> SHA256Digest -> SHA256Digest
    max :: SHA256Digest -> SHA256Digest -> SHA256Digest
    $cmin :: SHA256Digest -> SHA256Digest -> SHA256Digest
    min :: SHA256Digest -> SHA256Digest -> SHA256Digest
    Ord, SHA256Digest -> ()
    (SHA256Digest -> ()) -> NFData SHA256Digest
    forall a. (a -> ()) -> NFData a
    $crnf :: SHA256Digest -> ()
    rnf :: SHA256Digest -> ()
    NFData)

    instance Show SHA256Digest where
      show :: SHA256Digest -> String
    show = SHA256Digest -> String
    toString

    {-| Attempt to interpret a `ByteString` as a `SHA256Digest`, returning
        `Nothing` if the conversion fails
    -}
    sha256DigestFromByteString :: ByteString -> Maybe SHA256Digest
    sha256DigestFromByteString :: ByteString -> Maybe SHA256Digest
    sha256DigestFromByteString ByteString
    bytes
      | ByteString -> Int
    ByteString.length ByteString
    bytes Int -> Int -> Bool
    forall a. Eq a => a -> a -> Bool
    == Int
    32 = SHA256Digest -> Maybe SHA256Digest
    forall a. a -> Maybe a
    Just (ByteString -> SHA256Digest
    SHA256Digest ByteString
    bytes)
      | Bool
    otherwise                     = Maybe SHA256Digest
    forall a. Maybe a
    Nothing

    -- | Hash a `ByteString` and return the hash as a `SHA256Digest`
    sha256Hash :: ByteString -> SHA256Digest
    sha256Hash :: ByteString -> SHA256Digest
    sha256Hash = ByteString -> SHA256Digest
    SHA256Digest (ByteString -> SHA256Digest)
    -> (ByteString -> ByteString) -> ByteString -> SHA256Digest
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . ByteString -> ByteString
    Crypto.Hash.SHA256.hash

    -- | 'String' representation of a 'SHA256Digest'
    toString :: SHA256Digest -> String
    toString :: SHA256Digest -> String
    toString (SHA256Digest ByteString
    bytes) = ByteString -> String
    ByteString.Char8.unpack (ByteString -> String) -> ByteString -> String
    forall a b. (a -> b) -> a -> b
    $ ByteString -> ByteString
    Base16.encode ByteString
    bytes