module Botan.Hash.SHA2
( SHA2(..)
, SHA2Digest(..)
, sha2
, sha2Lazy
, SHA2_512_256(..)
, SHA2_512_256Digest(..)
, sha2_512_256
, sha2_512_256Lazy
) where

import GHC.TypeLits

import Data.Maybe
import Data.Proxy

import Data.Type.Bool
import Data.Type.Equality

import qualified Data.ByteString as ByteString
import qualified Data.ByteString.Lazy as Lazy
import qualified Data.Text as Text

import qualified Botan.Hash as Botan
import qualified Botan.Utility as Botan

import Botan.Hash.Class
import Botan.Prelude

-- SHA2 type

data SHA2 (n :: Nat)

type SHA2Size (n :: Nat) = (KnownNat n, (n == 224 || n == 256 || n == 384 || n == 512) ~ True)

type SHA2Digest n = Digest (SHA2 n)

newtype instance Digest (SHA2 n) = SHA2Digest
    { forall (n :: Nat). Digest (SHA2 n) -> ByteString
getSHA2ByteString :: ByteString {- ByteVector n -} }
    deriving newtype (Digest (SHA2 n) -> Digest (SHA2 n) -> Bool
(Digest (SHA2 n) -> Digest (SHA2 n) -> Bool)
-> (Digest (SHA2 n) -> Digest (SHA2 n) -> Bool)
-> Eq (Digest (SHA2 n))
forall (n :: Nat). Digest (SHA2 n) -> Digest (SHA2 n) -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: forall (n :: Nat). Digest (SHA2 n) -> Digest (SHA2 n) -> Bool
== :: Digest (SHA2 n) -> Digest (SHA2 n) -> Bool
$c/= :: forall (n :: Nat). Digest (SHA2 n) -> Digest (SHA2 n) -> Bool
/= :: Digest (SHA2 n) -> Digest (SHA2 n) -> Bool
Eq, Eq (Digest (SHA2 n))
Eq (Digest (SHA2 n)) =>
(Digest (SHA2 n) -> Digest (SHA2 n) -> Ordering)
-> (Digest (SHA2 n) -> Digest (SHA2 n) -> Bool)
-> (Digest (SHA2 n) -> Digest (SHA2 n) -> Bool)
-> (Digest (SHA2 n) -> Digest (SHA2 n) -> Bool)
-> (Digest (SHA2 n) -> Digest (SHA2 n) -> Bool)
-> (Digest (SHA2 n) -> Digest (SHA2 n) -> Digest (SHA2 n))
-> (Digest (SHA2 n) -> Digest (SHA2 n) -> Digest (SHA2 n))
-> Ord (Digest (SHA2 n))
Digest (SHA2 n) -> Digest (SHA2 n) -> Bool
Digest (SHA2 n) -> Digest (SHA2 n) -> Ordering
Digest (SHA2 n) -> Digest (SHA2 n) -> Digest (SHA2 n)
forall (n :: Nat). Eq (Digest (SHA2 n))
forall (n :: Nat). Digest (SHA2 n) -> Digest (SHA2 n) -> Bool
forall (n :: Nat). Digest (SHA2 n) -> Digest (SHA2 n) -> Ordering
forall (n :: Nat).
Digest (SHA2 n) -> Digest (SHA2 n) -> Digest (SHA2 n)
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 :: forall (n :: Nat). Digest (SHA2 n) -> Digest (SHA2 n) -> Ordering
compare :: Digest (SHA2 n) -> Digest (SHA2 n) -> Ordering
$c< :: forall (n :: Nat). Digest (SHA2 n) -> Digest (SHA2 n) -> Bool
< :: Digest (SHA2 n) -> Digest (SHA2 n) -> Bool
$c<= :: forall (n :: Nat). Digest (SHA2 n) -> Digest (SHA2 n) -> Bool
<= :: Digest (SHA2 n) -> Digest (SHA2 n) -> Bool
$c> :: forall (n :: Nat). Digest (SHA2 n) -> Digest (SHA2 n) -> Bool
> :: Digest (SHA2 n) -> Digest (SHA2 n) -> Bool
$c>= :: forall (n :: Nat). Digest (SHA2 n) -> Digest (SHA2 n) -> Bool
>= :: Digest (SHA2 n) -> Digest (SHA2 n) -> Bool
$cmax :: forall (n :: Nat).
Digest (SHA2 n) -> Digest (SHA2 n) -> Digest (SHA2 n)
max :: Digest (SHA2 n) -> Digest (SHA2 n) -> Digest (SHA2 n)
$cmin :: forall (n :: Nat).
Digest (SHA2 n) -> Digest (SHA2 n) -> Digest (SHA2 n)
min :: Digest (SHA2 n) -> Digest (SHA2 n) -> Digest (SHA2 n)
Ord)

instance Show (Digest (SHA2 n)) where
    show :: Digest (SHA2 n) -> String
    show :: Digest (SHA2 n) -> String
show (SHA2Digest ByteString
bytes) = Text -> String
Text.unpack (Text -> String) -> Text -> String
forall a b. (a -> b) -> a -> b
$ ByteString -> HexCase -> Text
Botan.hexEncode ByteString
bytes HexCase
Botan.Lower

instance (SHA2Size n) => Hash (SHA2 n) where
    hash :: ByteString -> Digest (SHA2 n)
    hash :: ByteString -> Digest (SHA2 n)
hash = ByteString -> Digest (SHA2 n)
forall (n :: Nat). ByteString -> Digest (SHA2 n)
SHA2Digest (ByteString -> Digest (SHA2 n))
-> (ByteString -> ByteString) -> ByteString -> Digest (SHA2 n)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Hash -> ByteString -> ByteString
Botan.hash Hash
h where
        n :: Int
n = Integer -> Int
forall a. Num a => Integer -> a
fromInteger (Integer -> Int) -> Integer -> Int
forall a b. (a -> b) -> a -> b
$ Proxy n -> Integer
forall (n :: Nat) (proxy :: Nat -> *).
KnownNat n =>
proxy n -> Integer
natVal (Proxy n -> Integer) -> Proxy n -> Integer
forall a b. (a -> b) -> a -> b
$ forall (t :: Nat). Proxy t
forall {k} (t :: k). Proxy t
Proxy @n
        h :: Hash
h = Maybe Hash -> Hash
forall a. HasCallStack => Maybe a -> a
fromJust (Maybe Hash -> Hash) -> Maybe Hash -> Hash
forall a b. (a -> b) -> a -> b
$ Int -> Maybe Hash
Botan.sha2 Int
n

instance (SHA2Size n) => IncrementalHash (SHA2 n) where
    hashLazy :: Lazy.ByteString -> Digest (SHA2 n)
    hashLazy :: ByteString -> Digest (SHA2 n)
hashLazy = ByteString -> Digest (SHA2 n)
forall (n :: Nat). ByteString -> Digest (SHA2 n)
SHA2Digest (ByteString -> Digest (SHA2 n))
-> (ByteString -> ByteString) -> ByteString -> Digest (SHA2 n)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Hash -> ByteString -> ByteString
Botan.hashLazy Hash
h where
        n :: Int
n = Integer -> Int
forall a. Num a => Integer -> a
fromInteger (Integer -> Int) -> Integer -> Int
forall a b. (a -> b) -> a -> b
$ Proxy n -> Integer
forall (n :: Nat) (proxy :: Nat -> *).
KnownNat n =>
proxy n -> Integer
natVal (Proxy n -> Integer) -> Proxy n -> Integer
forall a b. (a -> b) -> a -> b
$ forall (t :: Nat). Proxy t
forall {k} (t :: k). Proxy t
Proxy @n
        h :: Hash
h = Maybe Hash -> Hash
forall a. HasCallStack => Maybe a -> a
fromJust (Maybe Hash -> Hash) -> Maybe Hash -> Hash
forall a b. (a -> b) -> a -> b
$ Int -> Maybe Hash
Botan.sha2 Int
n

-- SHA2 hash

sha2 :: (SHA2Size n) => ByteString -> SHA2Digest n
sha2 :: forall (n :: Nat). SHA2Size n => ByteString -> Digest (SHA2 n)
sha2 = ByteString -> Digest (SHA2 n)
forall hash. Hash hash => ByteString -> Digest hash
hash

sha2Lazy :: (SHA2Size n) => Lazy.ByteString -> SHA2Digest n
sha2Lazy :: forall (n :: Nat). SHA2Size n => ByteString -> Digest (SHA2 n)
sha2Lazy = ByteString -> Digest (SHA2 n)
forall hash. IncrementalHash hash => ByteString -> Digest hash
hashLazy

-- SHA2_512_256 type

data SHA2_512_256

newtype instance Digest SHA2_512_256 = SHA2_512_256Digest
    { Digest SHA2_512_256 -> ByteString
getSHA2_512_256ByteString :: ByteString {- ByteVector n -} }
    deriving newtype (Digest SHA2_512_256 -> Digest SHA2_512_256 -> Bool
(Digest SHA2_512_256 -> Digest SHA2_512_256 -> Bool)
-> (Digest SHA2_512_256 -> Digest SHA2_512_256 -> Bool)
-> Eq (Digest SHA2_512_256)
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: Digest SHA2_512_256 -> Digest SHA2_512_256 -> Bool
== :: Digest SHA2_512_256 -> Digest SHA2_512_256 -> Bool
$c/= :: Digest SHA2_512_256 -> Digest SHA2_512_256 -> Bool
/= :: Digest SHA2_512_256 -> Digest SHA2_512_256 -> Bool
Eq, Eq (Digest SHA2_512_256)
Eq (Digest SHA2_512_256) =>
(Digest SHA2_512_256 -> Digest SHA2_512_256 -> Ordering)
-> (Digest SHA2_512_256 -> Digest SHA2_512_256 -> Bool)
-> (Digest SHA2_512_256 -> Digest SHA2_512_256 -> Bool)
-> (Digest SHA2_512_256 -> Digest SHA2_512_256 -> Bool)
-> (Digest SHA2_512_256 -> Digest SHA2_512_256 -> Bool)
-> (Digest SHA2_512_256
    -> Digest SHA2_512_256 -> Digest SHA2_512_256)
-> (Digest SHA2_512_256
    -> Digest SHA2_512_256 -> Digest SHA2_512_256)
-> Ord (Digest SHA2_512_256)
Digest SHA2_512_256 -> Digest SHA2_512_256 -> Bool
Digest SHA2_512_256 -> Digest SHA2_512_256 -> Ordering
Digest SHA2_512_256 -> Digest SHA2_512_256 -> Digest SHA2_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 :: Digest SHA2_512_256 -> Digest SHA2_512_256 -> Ordering
compare :: Digest SHA2_512_256 -> Digest SHA2_512_256 -> Ordering
$c< :: Digest SHA2_512_256 -> Digest SHA2_512_256 -> Bool
< :: Digest SHA2_512_256 -> Digest SHA2_512_256 -> Bool
$c<= :: Digest SHA2_512_256 -> Digest SHA2_512_256 -> Bool
<= :: Digest SHA2_512_256 -> Digest SHA2_512_256 -> Bool
$c> :: Digest SHA2_512_256 -> Digest SHA2_512_256 -> Bool
> :: Digest SHA2_512_256 -> Digest SHA2_512_256 -> Bool
$c>= :: Digest SHA2_512_256 -> Digest SHA2_512_256 -> Bool
>= :: Digest SHA2_512_256 -> Digest SHA2_512_256 -> Bool
$cmax :: Digest SHA2_512_256 -> Digest SHA2_512_256 -> Digest SHA2_512_256
max :: Digest SHA2_512_256 -> Digest SHA2_512_256 -> Digest SHA2_512_256
$cmin :: Digest SHA2_512_256 -> Digest SHA2_512_256 -> Digest SHA2_512_256
min :: Digest SHA2_512_256 -> Digest SHA2_512_256 -> Digest SHA2_512_256
Ord)

type SHA2_512_256Digest = Digest SHA2_512_256

instance Show (Digest SHA2_512_256) where
    show :: Digest SHA2_512_256 -> String
    show :: Digest SHA2_512_256 -> String
show (SHA2_512_256Digest ByteString
bytes) = Text -> String
Text.unpack (Text -> String) -> Text -> String
forall a b. (a -> b) -> a -> b
$ ByteString -> HexCase -> Text
Botan.hexEncode ByteString
bytes HexCase
Botan.Lower

instance Hash SHA2_512_256 where
    hash :: ByteString -> Digest SHA2_512_256
    hash :: ByteString -> Digest SHA2_512_256
hash = ByteString -> Digest SHA2_512_256
SHA2_512_256Digest (ByteString -> Digest SHA2_512_256)
-> (ByteString -> ByteString) -> ByteString -> Digest SHA2_512_256
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Hash -> ByteString -> ByteString
Botan.hash Hash
Botan.sha2_512_256

instance IncrementalHash SHA2_512_256 where
    hashLazy :: Lazy.ByteString -> Digest SHA2_512_256
    hashLazy :: ByteString -> Digest SHA2_512_256
hashLazy = ByteString -> Digest SHA2_512_256
SHA2_512_256Digest (ByteString -> Digest SHA2_512_256)
-> (ByteString -> ByteString) -> ByteString -> Digest SHA2_512_256
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Hash -> ByteString -> ByteString
Botan.hashLazy Hash
Botan.sha2_512_256

-- SHA2_512_256 hash

sha2_512_256 :: ByteString -> SHA2_512_256Digest
sha2_512_256 :: ByteString -> Digest SHA2_512_256
sha2_512_256 = ByteString -> Digest SHA2_512_256
forall hash. Hash hash => ByteString -> Digest hash
hash

sha2_512_256Lazy :: Lazy.ByteString -> SHA2_512_256Digest
sha2_512_256Lazy :: ByteString -> Digest SHA2_512_256
sha2_512_256Lazy = ByteString -> Digest SHA2_512_256
forall hash. IncrementalHash hash => ByteString -> Digest hash
hashLazy