    {-# 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 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 (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