saltine-0.2.2.0: src/Crypto/Saltine/Internal/Hash.hs
{-# LANGUAGE DeriveDataTypeable, GeneralizedNewtypeDeriving, DeriveGeneric, ForeignFunctionInterface #-}
-- |
-- Module : Crypto.Saltine.Internal.Hash
-- Copyright : (c) Max Amanshauser 2021
-- License : MIT
--
-- Maintainer : max@lambdalifting.org
-- Stability : experimental
-- Portability : non-portable
--
module Crypto.Saltine.Internal.Hash (
hash_bytes
, shorthash_bytes
, shorthash_keybytes
, generichash_bytes_max
, generichash_keybytes_max
, hash_sha256_bytes
, c_hash
, c_shorthash
, c_generichash
, c_hash_sha256
, nullShKey
, shorthash
, ShorthashKey(..)
, GenerichashKey(..)
, GenerichashOutLen(..)
) where
import Control.DeepSeq
import Crypto.Saltine.Class
import Crypto.Saltine.Internal.Util as U
import Data.ByteString (ByteString)
import Data.Data (Data, Typeable)
import Data.Hashable (Hashable)
import Data.Monoid
import Foreign.C
import Foreign.Ptr
import GHC.Generics (Generic)
import qualified Data.ByteString as S
import qualified Data.ByteString.Char8 as S8
-- | An opaque 'shorthash' cryptographic secret key.
newtype ShorthashKey = ShK { unShK :: ByteString } deriving (Ord, Hashable, Data, Typeable, Generic, NFData)
instance Eq ShorthashKey where
ShK a == ShK b = U.compare a b
instance Show ShorthashKey where
show k = "Hash.ShorthashKey {hashesTo = \"" <> (bin2hex . shorthash nullShKey $ encode k) <> "\"}"
-- | Used for our `Show` instances
nullShKey :: ShorthashKey
nullShKey = ShK (S8.replicate shorthash_keybytes '\NUL')
-- | Computes a very short, fast keyed hash.
-- This function is defined here to break circulat module imports
shorthash :: ShorthashKey
-> ByteString
-- ^ Message
-> ByteString
-- ^ Hash
shorthash (ShK k) m = snd . buildUnsafeByteString shorthash_bytes $ \ph ->
constByteStrings [k, m] $ \[(pk, _), (pm, _)] ->
c_shorthash ph pm (fromIntegral $ S.length m) pk
instance IsEncoding ShorthashKey where
decode v = if S.length v == shorthash_keybytes
then Just (ShK v)
else Nothing
{-# INLINE decode #-}
encode (ShK v) = v
{-# INLINE encode #-}
-- | An opaque 'generichash' cryptographic secret key.
newtype GenerichashKey = GhK { unGhK :: ByteString } deriving (Ord, Hashable, Data, Typeable, Generic, NFData)
instance Eq GenerichashKey where
GhK a == GhK b = U.compare a b
instance Show GenerichashKey where
show k = "Hash.GenerichashKey {hashesTo = \"" <> (bin2hex . shorthash nullShKey $ encode k) <> "\"}"
instance IsEncoding GenerichashKey where
decode v = if S.length v <= generichash_keybytes_max
then Just (GhK v)
else Nothing
{-# INLINE decode #-}
encode (GhK v) = v
{-# INLINE encode #-}
newtype GenerichashOutLen = GhOL { unGhOL :: Int } deriving (Eq, Ord, Hashable, Data, Typeable, Generic, NFData)
hash_bytes, shorthash_bytes, shorthash_keybytes, generichash_bytes_max, generichash_keybytes_max, hash_sha256_bytes :: Int
-- Hashes
-- | The size of a hash resulting from
-- 'Crypto.Saltine.Internal.Hash.hash'.
hash_bytes = fromIntegral c_crypto_hash_bytes
-- | The size of a keyed hash resulting from
-- 'Crypto.Saltine.Internal.Hash.shorthash'.
shorthash_bytes = fromIntegral c_crypto_shorthash_bytes
-- | The size of a hashing key for the keyed hash function
-- 'Crypto.Saltine.Internal.Hash.shorthash'.
shorthash_keybytes = fromIntegral c_crypto_shorthash_keybytes
-- | The maximum output size of the generic hash function
-- 'Crypto.Saltine.Core.Hash.generichash'
generichash_bytes_max = fromIntegral c_crypto_generichash_bytes_max
-- | The maximum key size of the generic hash function
-- 'Crypto.Saltine.Core.Hash.generichash'
generichash_keybytes_max = fromIntegral c_crypto_generichash_keybytes_max
-- | The size of a hash resulting from
-- 'Crypto.Saltine.Core.Hash.sha256'.
hash_sha256_bytes = fromIntegral c_crypto_hash_sha256_bytes
-- src/libsodium/crypto_generichash/crypto_generichash.c
foreign import ccall "crypto_generichash_bytes_max"
c_crypto_generichash_bytes_max :: CSize
foreign import ccall "crypto_generichash_keybytes_max"
c_crypto_generichash_keybytes_max :: CSize
-- src/libsodium/crypto_hash/crypto_hash.c
-- src/libsodium/include/sodium/crypto_hash.h
foreign import ccall "crypto_hash_bytes"
c_crypto_hash_bytes :: CSize
-- src/libsodium/crypto_shorthash/crypto_shorthash.c
-- src/libsodium/include/sodium/crypto_shorthash.h
foreign import ccall "crypto_shorthash_bytes"
c_crypto_shorthash_bytes :: CSize
foreign import ccall "crypto_shorthash_keybytes"
c_crypto_shorthash_keybytes :: CSize
-- src/libsodium/crypto_hash/sha256/hash_sha256.c
-- src/libsodium/include/sodium/crypto_hash_sha256.h
foreign import ccall "crypto_hash_sha256_bytes"
c_crypto_hash_sha256_bytes :: CSize
foreign import ccall "crypto_hash"
c_hash :: Ptr CChar
-- ^ Output hash buffer
-> Ptr CChar
-- ^ Constant message buffer
-> CULLong
-- ^ Constant message buffer length
-> IO CInt
-- ^ Always 0
foreign import ccall "crypto_shorthash"
c_shorthash :: Ptr CChar
-- ^ Output hash buffer
-> Ptr CChar
-- ^ Constant message buffer
-> CULLong
-- ^ Message buffer length
-> Ptr CChar
-- ^ Constant Key buffer
-> IO CInt
-- ^ Always 0
foreign import ccall "crypto_generichash"
c_generichash :: Ptr CChar
-- ^ Output hash buffer
-> CULLong
-- ^ Output hash length
-> Ptr CChar
-- ^ Constant message buffer
-> CULLong
-- ^ Message buffer length
-> Ptr CChar
-- ^ Constant Key buffer
-> CULLong
-- ^ Key buffer length
-> IO CInt
-- ^ Always 0
foreign import ccall "crypto_hash_sha256"
c_hash_sha256 :: Ptr CChar
-- ^ Output hash buffer
-> Ptr CChar
-- ^ Constant message buffer
-> CULLong
-- ^ Message buffer length
-> IO CInt
-- ^ Always 0