{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE TypeFamilies               #-}
{-# LANGUAGE FlexibleInstances          #-}

-- |
--
-- Module      : Raaz.Primitive.Keyed.Internal
-- Description : Keyed hashing primitives.
-- Copyright   : (c) Piyush P Kurur, 2019
-- License     : Apache-2.0 OR BSD-3-Clause
-- Maintainer  : Piyush P Kurur <ppk@iitpkd.ac.in>
-- Stability   : experimental
--

module Raaz.Primitive.Keyed.Internal
       ( -- * Keyed Hashing.
         -- $keyedhash$
         --
         Keyed(..), KeyedHash(..), Key(..), unsafeToKeyed, unsafeToPrim
       ) where

import Data.ByteString  as BS
import Foreign.Storable ( Storable )

import Raaz.Core

-- $keyedhash$
--
-- The keyed version of a cryptographic hash. Certain hashes like
-- blake2 can be used for message authentication where the message is
-- essentially appended to the key and hashed. This module is meant to
-- handle such keyed primitives.  Note that this naive message
-- authentication is vulnerable to length extension attack when
-- combined with a Merkel-Damgrad like hash like the sha2 family of
-- hashes; they require a more complicated HMAC construction.

-- | Class of primitives, typically cryptographic hashes, that when
-- used as a keyed hash gives a safe MAC.
class KeyedHash prim where
  -- The initialisation used by the hash can depend on the length of
  -- the key used.
  hashInit :: BYTES Int -> prim

-- | The message authentication code associated with the hashes.
newtype Keyed prim = Keyed prim
                 deriving (Keyed prim -> Keyed prim -> Bool
(Keyed prim -> Keyed prim -> Bool)
-> (Keyed prim -> Keyed prim -> Bool) -> Eq (Keyed prim)
forall prim. Eq prim => Keyed prim -> Keyed prim -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: forall prim. Eq prim => Keyed prim -> Keyed prim -> Bool
== :: Keyed prim -> Keyed prim -> Bool
$c/= :: forall prim. Eq prim => Keyed prim -> Keyed prim -> Bool
/= :: Keyed prim -> Keyed prim -> Bool
Eq, Keyed prim -> Keyed prim -> Result
(Keyed prim -> Keyed prim -> Result) -> Equality (Keyed prim)
forall prim. Equality prim => Keyed prim -> Keyed prim -> Result
forall a. (a -> a -> Result) -> Equality a
$ceq :: forall prim. Equality prim => Keyed prim -> Keyed prim -> Result
eq :: Keyed prim -> Keyed prim -> Result
Equality, Ptr (Keyed prim) -> IO (Keyed prim)
Ptr (Keyed prim) -> Int -> IO (Keyed prim)
Ptr (Keyed prim) -> Int -> Keyed prim -> IO ()
Ptr (Keyed prim) -> Keyed prim -> IO ()
Keyed prim -> Int
(Keyed prim -> Int)
-> (Keyed prim -> Int)
-> (Ptr (Keyed prim) -> Int -> IO (Keyed prim))
-> (Ptr (Keyed prim) -> Int -> Keyed prim -> IO ())
-> (forall b. Ptr b -> Int -> IO (Keyed prim))
-> (forall b. Ptr b -> Int -> Keyed prim -> IO ())
-> (Ptr (Keyed prim) -> IO (Keyed prim))
-> (Ptr (Keyed prim) -> Keyed prim -> IO ())
-> Storable (Keyed prim)
forall b. Ptr b -> Int -> IO (Keyed prim)
forall b. Ptr b -> Int -> Keyed prim -> IO ()
forall prim. Storable prim => Ptr (Keyed prim) -> IO (Keyed prim)
forall prim.
Storable prim =>
Ptr (Keyed prim) -> Int -> IO (Keyed prim)
forall prim.
Storable prim =>
Ptr (Keyed prim) -> Int -> Keyed prim -> IO ()
forall prim.
Storable prim =>
Ptr (Keyed prim) -> Keyed prim -> IO ()
forall prim. Storable prim => Keyed prim -> Int
forall prim b. Storable prim => Ptr b -> Int -> IO (Keyed prim)
forall prim b. Storable prim => Ptr b -> Int -> Keyed prim -> IO ()
forall a.
(a -> Int)
-> (a -> Int)
-> (Ptr a -> Int -> IO a)
-> (Ptr a -> Int -> a -> IO ())
-> (forall b. Ptr b -> Int -> IO a)
-> (forall b. Ptr b -> Int -> a -> IO ())
-> (Ptr a -> IO a)
-> (Ptr a -> a -> IO ())
-> Storable a
$csizeOf :: forall prim. Storable prim => Keyed prim -> Int
sizeOf :: Keyed prim -> Int
$calignment :: forall prim. Storable prim => Keyed prim -> Int
alignment :: Keyed prim -> Int
$cpeekElemOff :: forall prim.
Storable prim =>
Ptr (Keyed prim) -> Int -> IO (Keyed prim)
peekElemOff :: Ptr (Keyed prim) -> Int -> IO (Keyed prim)
$cpokeElemOff :: forall prim.
Storable prim =>
Ptr (Keyed prim) -> Int -> Keyed prim -> IO ()
pokeElemOff :: Ptr (Keyed prim) -> Int -> Keyed prim -> IO ()
$cpeekByteOff :: forall prim b. Storable prim => Ptr b -> Int -> IO (Keyed prim)
peekByteOff :: forall b. Ptr b -> Int -> IO (Keyed prim)
$cpokeByteOff :: forall prim b. Storable prim => Ptr b -> Int -> Keyed prim -> IO ()
pokeByteOff :: forall b. Ptr b -> Int -> Keyed prim -> IO ()
$cpeek :: forall prim. Storable prim => Ptr (Keyed prim) -> IO (Keyed prim)
peek :: Ptr (Keyed prim) -> IO (Keyed prim)
$cpoke :: forall prim.
Storable prim =>
Ptr (Keyed prim) -> Keyed prim -> IO ()
poke :: Ptr (Keyed prim) -> Keyed prim -> IO ()
Storable, Storable (Keyed prim)
Ptr (Keyed prim) -> IO (Keyed prim)
Ptr (Keyed prim) -> Int -> IO ()
Ptr (Keyed prim) -> Keyed prim -> IO ()
Storable (Keyed prim) =>
(Ptr (Keyed prim) -> Keyed prim -> IO ())
-> (Ptr (Keyed prim) -> IO (Keyed prim))
-> (Ptr (Keyed prim) -> Int -> IO ())
-> EndianStore (Keyed prim)
forall w.
Storable w =>
(Ptr w -> w -> IO ())
-> (Ptr w -> IO w) -> (Ptr w -> Int -> IO ()) -> EndianStore w
forall prim. EndianStore prim => Storable (Keyed prim)
forall prim.
EndianStore prim =>
Ptr (Keyed prim) -> IO (Keyed prim)
forall prim. EndianStore prim => Ptr (Keyed prim) -> Int -> IO ()
forall prim.
EndianStore prim =>
Ptr (Keyed prim) -> Keyed prim -> IO ()
$cstore :: forall prim.
EndianStore prim =>
Ptr (Keyed prim) -> Keyed prim -> IO ()
store :: Ptr (Keyed prim) -> Keyed prim -> IO ()
$cload :: forall prim.
EndianStore prim =>
Ptr (Keyed prim) -> IO (Keyed prim)
load :: Ptr (Keyed prim) -> IO (Keyed prim)
$cadjustEndian :: forall prim. EndianStore prim => Ptr (Keyed prim) -> Int -> IO ()
adjustEndian :: Ptr (Keyed prim) -> Int -> IO ()
EndianStore, ByteString -> Maybe (Keyed prim)
ByteString -> Keyed prim
Keyed prim -> ByteString
(Keyed prim -> ByteString)
-> (ByteString -> Maybe (Keyed prim))
-> (ByteString -> Keyed prim)
-> Encodable (Keyed prim)
forall prim. Encodable prim => ByteString -> Maybe (Keyed prim)
forall prim. Encodable prim => ByteString -> Keyed prim
forall prim. Encodable prim => Keyed prim -> ByteString
forall a.
(a -> ByteString)
-> (ByteString -> Maybe a) -> (ByteString -> a) -> Encodable a
$ctoByteString :: forall prim. Encodable prim => Keyed prim -> ByteString
toByteString :: Keyed prim -> ByteString
$cfromByteString :: forall prim. Encodable prim => ByteString -> Maybe (Keyed prim)
fromByteString :: ByteString -> Maybe (Keyed prim)
$cunsafeFromByteString :: forall prim. Encodable prim => ByteString -> Keyed prim
unsafeFromByteString :: ByteString -> Keyed prim
Encodable)

instance IsString prim => IsString (Keyed prim) where
  fromString :: String -> Keyed prim
fromString = prim -> Keyed prim
forall prim. prim -> Keyed prim
unsafeToKeyed (prim -> Keyed prim) -> (String -> prim) -> String -> Keyed prim
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> prim
forall a. IsString a => String -> a
fromString

instance Show prim => Show (Keyed prim) where
  show :: Keyed prim -> String
show = prim -> String
forall a. Show a => a -> String
show (prim -> String) -> (Keyed prim -> prim) -> Keyed prim -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Keyed prim -> prim
forall prim. Keyed prim -> prim
unsafeToPrim

instance Primitive prim => Primitive (Keyed prim) where
  type WordType      (Keyed prim)  = WordType prim
  type WordsPerBlock (Keyed prim)  = WordsPerBlock prim

--------------- Key used by the keyed prim -----------------------------

newtype instance Key (Keyed prim) = Key ByteString

instance IsString (Key (Keyed prim)) where
  fromString :: String -> Key (Keyed prim)
fromString = ByteString -> Key (Keyed prim)
forall prim. ByteString -> Key (Keyed prim)
Key (ByteString -> Key (Keyed prim))
-> (String -> ByteString) -> String -> Key (Keyed prim)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> ByteString
forall a. Encodable a => String -> a
fromBase16

instance Show (Key (Keyed prim)) where
  show :: Key (Keyed prim) -> String
show (Key ByteString
hkey) = ByteString -> String
forall a. Encodable a => a -> String
showBase16 ByteString
hkey

instance Encodable (Key (Keyed prim)) where
  toByteString :: Key (Keyed prim) -> ByteString
toByteString   (Key ByteString
bs) = ByteString
bs
  fromByteString :: ByteString -> Maybe (Key (Keyed prim))
fromByteString          = Key (Keyed prim) -> Maybe (Key (Keyed prim))
forall a. a -> Maybe a
Just (Key (Keyed prim) -> Maybe (Key (Keyed prim)))
-> (ByteString -> Key (Keyed prim))
-> ByteString
-> Maybe (Key (Keyed prim))
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> Key (Keyed prim)
forall prim. ByteString -> Key (Keyed prim)
Key
  unsafeFromByteString :: ByteString -> Key (Keyed prim)
unsafeFromByteString    = ByteString -> Key (Keyed prim)
forall prim. ByteString -> Key (Keyed prim)
Key

-- | Converts a Keyed value to the corresponding hash value. This
-- function violates the principle that semantically distinct values
-- should be of distinct types and hence should be considered unsafe
unsafeToPrim :: Keyed prim -> prim
unsafeToPrim :: forall prim. Keyed prim -> prim
unsafeToPrim (Keyed prim
p) = prim
p


-- | Converts the hash value to the corresponding @`Keyed`@
-- value. This function violates the principle that semantically
-- distinct values should be of distinct types and hence should be
-- considered unsafe.
unsafeToKeyed :: prim -> Keyed prim
unsafeToKeyed :: forall prim. prim -> Keyed prim
unsafeToKeyed = prim -> Keyed prim
forall prim. prim -> Keyed prim
Keyed