--
-- MinIO Haskell SDK, (C) 2017 MinIO, Inc.
--
-- Licensed under the Apache License, Version 2.0 (the "License");
-- you may not use this file except in compliance with the License.
-- You may obtain a copy of the License at
--
--     http://www.apache.org/licenses/LICENSE-2.0
--
-- Unless required by applicable law or agreed to in writing, software
-- distributed under the License is distributed on an "AS IS" BASIS,
-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-- See the License for the specific language governing permissions and
-- limitations under the License.
--

module Network.Minio.Data.Crypto
  ( hashSHA256,
    hashSHA256FromSource,
    hashMD5,
    hashMD5ToBase64,
    hashMD5FromSource,
    hmacSHA256,
    hmacSHA256RawBS,
    digestToBS,
    digestToBase16,
    encodeToBase64,
  )
where

import Crypto.Hash
  ( Digest,
    MD5 (..),
    SHA256 (..),
    hashWith,
  )
import Crypto.Hash.Conduit (sinkHash)
import Crypto.MAC.HMAC (HMAC, hmac)
import Data.ByteArray (ByteArrayAccess, convert)
import Data.ByteArray.Encoding (Base (Base16, Base64), convertToBase)
import qualified Data.Conduit as C

hashSHA256 :: ByteString -> ByteString
hashSHA256 :: ByteString -> ByteString
hashSHA256 = forall a. ByteArrayAccess a => a -> ByteString
digestToBase16 forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall ba alg.
(ByteArrayAccess ba, HashAlgorithm alg) =>
alg -> ba -> Digest alg
hashWith SHA256
SHA256

hashSHA256FromSource :: (Monad m) => C.ConduitM () ByteString m () -> m ByteString
hashSHA256FromSource :: forall (m :: * -> *).
Monad m =>
ConduitM () ByteString m () -> m ByteString
hashSHA256FromSource ConduitM () ByteString m ()
src = do
  Digest SHA256
digest <- forall (m :: * -> *) a r.
Monad m =>
ConduitT () a m () -> ConduitT a Void m r -> m r
C.connect ConduitM () ByteString m ()
src forall (m :: * -> *).
Monad m =>
ConduitM ByteString Void m (Digest SHA256)
sinkSHA256Hash
  forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ forall a. ByteArrayAccess a => a -> ByteString
digestToBase16 Digest SHA256
digest
  where
    -- To help with type inference
    sinkSHA256Hash :: (Monad m) => C.ConduitM ByteString Void m (Digest SHA256)
    sinkSHA256Hash :: forall (m :: * -> *).
Monad m =>
ConduitM ByteString Void m (Digest SHA256)
sinkSHA256Hash = forall (m :: * -> *) hash.
(Monad m, HashAlgorithm hash) =>
Consumer ByteString m (Digest hash)
sinkHash

-- Returns MD5 hash hex encoded.
hashMD5 :: ByteString -> ByteString
hashMD5 :: ByteString -> ByteString
hashMD5 = forall a. ByteArrayAccess a => a -> ByteString
digestToBase16 forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall ba alg.
(ByteArrayAccess ba, HashAlgorithm alg) =>
alg -> ba -> Digest alg
hashWith MD5
MD5

hashMD5FromSource :: (Monad m) => C.ConduitM () ByteString m () -> m ByteString
hashMD5FromSource :: forall (m :: * -> *).
Monad m =>
ConduitM () ByteString m () -> m ByteString
hashMD5FromSource ConduitM () ByteString m ()
src = do
  Digest MD5
digest <- forall (m :: * -> *) a r.
Monad m =>
ConduitT () a m () -> ConduitT a Void m r -> m r
C.connect ConduitM () ByteString m ()
src forall (m :: * -> *).
Monad m =>
ConduitM ByteString Void m (Digest MD5)
sinkMD5Hash
  forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ forall a. ByteArrayAccess a => a -> ByteString
digestToBase16 Digest MD5
digest
  where
    -- To help with type inference
    sinkMD5Hash :: (Monad m) => C.ConduitM ByteString Void m (Digest MD5)
    sinkMD5Hash :: forall (m :: * -> *).
Monad m =>
ConduitM ByteString Void m (Digest MD5)
sinkMD5Hash = forall (m :: * -> *) hash.
(Monad m, HashAlgorithm hash) =>
Consumer ByteString m (Digest hash)
sinkHash

hmacSHA256 :: ByteString -> ByteString -> HMAC SHA256
hmacSHA256 :: ByteString -> ByteString -> HMAC SHA256
hmacSHA256 ByteString
message ByteString
key = forall key message a.
(ByteArrayAccess key, ByteArrayAccess message, HashAlgorithm a) =>
key -> message -> HMAC a
hmac ByteString
key ByteString
message

hmacSHA256RawBS :: ByteString -> ByteString -> ByteString
hmacSHA256RawBS :: ByteString -> ByteString -> ByteString
hmacSHA256RawBS ByteString
message ByteString
key = forall bin bout.
(ByteArrayAccess bin, ByteArray bout) =>
bin -> bout
convert forall a b. (a -> b) -> a -> b
$ ByteString -> ByteString -> HMAC SHA256
hmacSHA256 ByteString
message ByteString
key

digestToBS :: (ByteArrayAccess a) => a -> ByteString
digestToBS :: forall a. ByteArrayAccess a => a -> ByteString
digestToBS = forall bin bout.
(ByteArrayAccess bin, ByteArray bout) =>
bin -> bout
convert

digestToBase16 :: (ByteArrayAccess a) => a -> ByteString
digestToBase16 :: forall a. ByteArrayAccess a => a -> ByteString
digestToBase16 = forall bin bout.
(ByteArrayAccess bin, ByteArray bout) =>
Base -> bin -> bout
convertToBase Base
Base16

-- Returns MD5 hash base 64 encoded.
hashMD5ToBase64 :: (ByteArrayAccess a) => a -> ByteString
hashMD5ToBase64 :: forall a. ByteArrayAccess a => a -> ByteString
hashMD5ToBase64 = forall bin bout.
(ByteArrayAccess bin, ByteArray bout) =>
Base -> bin -> bout
convertToBase Base
Base64 forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall ba alg.
(ByteArrayAccess ba, HashAlgorithm alg) =>
alg -> ba -> Digest alg
hashWith MD5
MD5

encodeToBase64 :: (ByteArrayAccess a) => a -> ByteString
encodeToBase64 :: forall a. ByteArrayAccess a => a -> ByteString
encodeToBase64 = forall bin bout.
(ByteArrayAccess bin, ByteArray bout) =>
Base -> bin -> bout
convertToBase Base
Base64