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