--
-- 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 = Digest SHA256 -> ByteString
forall a. ByteArrayAccess a => a -> ByteString
digestToBase16 (Digest SHA256 -> ByteString)
-> (ByteString -> Digest SHA256) -> ByteString -> ByteString
forall b c a. (b -> c) -> (a -> b) -> a -> c
. SHA256 -> ByteString -> Digest SHA256
forall ba alg.
(ByteArrayAccess ba, HashAlgorithm alg) =>
alg -> ba -> Digest alg
hashWith SHA256
SHA256

hashSHA256FromSource :: Monad m => C.ConduitM () ByteString m () -> m ByteString
hashSHA256FromSource :: ConduitM () ByteString m () -> m ByteString
hashSHA256FromSource ConduitM () ByteString m ()
src = do
  Digest SHA256
digest <- ConduitM () ByteString m ()
-> ConduitT ByteString Void m (Digest SHA256) -> m (Digest SHA256)
forall (m :: * -> *) a r.
Monad m =>
ConduitT () a m () -> ConduitT a Void m r -> m r
C.connect ConduitM () ByteString m ()
src ConduitT ByteString Void m (Digest SHA256)
forall (m :: * -> *).
Monad m =>
ConduitM ByteString Void m (Digest SHA256)
sinkSHA256Hash
  ByteString -> m ByteString
forall (m :: * -> *) a. Monad m => a -> m a
return (ByteString -> m ByteString) -> ByteString -> m ByteString
forall a b. (a -> b) -> a -> b
$ Digest SHA256 -> ByteString
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 :: ConduitM ByteString Void m (Digest SHA256)
sinkSHA256Hash = ConduitM ByteString Void m (Digest SHA256)
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 = Digest MD5 -> ByteString
forall a. ByteArrayAccess a => a -> ByteString
digestToBase16 (Digest MD5 -> ByteString)
-> (ByteString -> Digest MD5) -> ByteString -> ByteString
forall b c a. (b -> c) -> (a -> b) -> a -> c
. MD5 -> ByteString -> Digest MD5
forall ba alg.
(ByteArrayAccess ba, HashAlgorithm alg) =>
alg -> ba -> Digest alg
hashWith MD5
MD5

hashMD5FromSource :: Monad m => C.ConduitM () ByteString m () -> m ByteString
hashMD5FromSource :: ConduitM () ByteString m () -> m ByteString
hashMD5FromSource ConduitM () ByteString m ()
src = do
  Digest MD5
digest <- ConduitM () ByteString m ()
-> ConduitT ByteString Void m (Digest MD5) -> m (Digest MD5)
forall (m :: * -> *) a r.
Monad m =>
ConduitT () a m () -> ConduitT a Void m r -> m r
C.connect ConduitM () ByteString m ()
src ConduitT ByteString Void m (Digest MD5)
forall (m :: * -> *).
Monad m =>
ConduitM ByteString Void m (Digest MD5)
sinkMD5Hash
  ByteString -> m ByteString
forall (m :: * -> *) a. Monad m => a -> m a
return (ByteString -> m ByteString) -> ByteString -> m ByteString
forall a b. (a -> b) -> a -> b
$ Digest MD5 -> ByteString
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 :: ConduitM ByteString Void m (Digest MD5)
sinkMD5Hash = ConduitM ByteString Void m (Digest MD5)
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 = ByteString -> ByteString -> HMAC SHA256
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 = HMAC SHA256 -> ByteString
forall bin bout.
(ByteArrayAccess bin, ByteArray bout) =>
bin -> bout
convert (HMAC SHA256 -> ByteString) -> HMAC SHA256 -> ByteString
forall a b. (a -> b) -> a -> b
$ ByteString -> ByteString -> HMAC SHA256
hmacSHA256 ByteString
message ByteString
key

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

digestToBase16 :: ByteArrayAccess a => a -> ByteString
digestToBase16 :: a -> ByteString
digestToBase16 = Base -> a -> ByteString
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 :: a -> ByteString
hashMD5ToBase64 = Base -> Digest MD5 -> ByteString
forall bin bout.
(ByteArrayAccess bin, ByteArray bout) =>
Base -> bin -> bout
convertToBase Base
Base64 (Digest MD5 -> ByteString) -> (a -> Digest MD5) -> a -> ByteString
forall b c a. (b -> c) -> (a -> b) -> a -> c
. MD5 -> a -> Digest MD5
forall ba alg.
(ByteArrayAccess ba, HashAlgorithm alg) =>
alg -> ba -> Digest alg
hashWith MD5
MD5

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