{-# 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
DataType
Constr
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 -> DataType
SHA256Digest -> Constr
(forall b. Data b => b -> b) -> SHA256Digest -> SHA256Digest
(forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> SHA256Digest -> c SHA256Digest
(forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c 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)
$cSHA256Digest :: Constr
$tSHA256Digest :: DataType
gmapMo :: (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 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 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 :: Int -> (forall d. Data d => d -> u) -> SHA256Digest -> u
$cgmapQi :: forall u. Int -> (forall d. Data d => d -> u) -> SHA256Digest -> u
gmapQ :: (forall d. Data d => d -> u) -> SHA256Digest -> [u]
$cgmapQ :: forall u. (forall d. Data d => d -> u) -> SHA256Digest -> [u]
gmapQr :: (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 :: (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 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 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 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 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
$cp1Data :: Typeable SHA256Digest
Data, SHA256Digest -> SHA256Digest -> Bool
(SHA256Digest -> SHA256Digest -> Bool)
-> (SHA256Digest -> SHA256Digest -> Bool) -> Eq SHA256Digest
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. 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
$cto :: forall x. Rep SHA256Digest x -> SHA256Digest
$cfrom :: forall x. SHA256Digest -> Rep SHA256Digest x
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
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
$cp1Ord :: Eq SHA256Digest
Ord, SHA256Digest -> ()
(SHA256Digest -> ()) -> NFData 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 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