-- | -- Module : Crypto.Saltine.Core.Hash -- Copyright : (c) Joseph Abrahamson 2013 -- License : MIT -- -- Maintainer : me@jspha.com -- Stability : experimental -- Portability : non-portable -- -- Hashing: "Crypto.Saltine.Core.Hash" -- -- The 'hash' function hashes a message 'ByteString' and returns a -- hash. Hashes are always of length 'Bytes.hash'. The 'shorthash' -- function hashes a message 'ByteString' with respect to a secret key -- and returns a very short hash. Short hashes are always of length -- 'Bytes.shorthash'. -- -- The 'hash' function is designed to be usable as a strong component -- of DSA, RSA-PSS, key derivation, hash-based message-authentication -- codes, hash-based ciphers, and various other common -- applications. "Strong" means that the security of these -- applications, when instantiated with 'hash', is the same as the -- security of the applications against generic attacks. In -- particular, the 'hash' function is designed to make finding -- collisions difficult. -- -- 'hash' is currently an implementation of SHA-512. 'shorthash' is -- currently an implementation of SipHash-2-4 -- (). -- -- There has been considerable degradation of public confidence in the -- security conjectures for many hash functions, including -- SHA-512. However, for the moment, there do not appear to be -- alternatives that inspire satisfactory levels of confidence. One -- can hope that NIST's SHA-3 competition will improve the situation. -- -- Sodium includes an implementation of the Blake2 hash -- () but since this is not standard NaCl nor was -- Blake2 selected to be SHA-3 the library doesn't bind it. -- -- This is version 2010.08.30 of the hash.html web page. Information -- about SipHash has been added. module Crypto.Saltine.Core.Hash ( ShorthashKey, hash, shorthash, newShorthashKey ) where import Crypto.Saltine.Class import Crypto.Saltine.Internal.Util import qualified Crypto.Saltine.Internal.ByteSizes as Bytes import Foreign.C import Foreign.Ptr import qualified Data.ByteString as S import Data.ByteString (ByteString) import Control.Applicative -- | Computes a cryptographically collision-resistant hash making -- @hash m == hash m' ==> m == m'@ highly likely even when under -- attack. hash :: ByteString -- ^ Message -> ByteString -- ^ Hash hash m = snd . buildUnsafeCVector Bytes.hash $ \ph -> constVectors [m] $ \[(pm, _)] -> c_hash ph pm (fromIntegral $ S.length m) -- | An opaque 'shorthash' cryptographic secret key. newtype ShorthashKey = ShK ByteString deriving (Eq, Ord) instance IsEncoding ShorthashKey where decode v = case S.length v == Bytes.shorthashKey of True -> Just (ShK v) False -> Nothing {-# INLINE decode #-} encode (ShK v) = v {-# INLINE encode #-} -- | Randomly generates a new key for 'shorthash'. newShorthashKey :: IO ShorthashKey newShorthashKey = ShK <$> randomVector Bytes.shorthashKey -- | Computes a very short, fast keyed hash. shorthash :: ShorthashKey -> ByteString -- ^ Message -> ByteString -- ^ Hash shorthash (ShK k) m = snd . buildUnsafeCVector Bytes.shorthash $ \ph -> constVectors [k, m] $ \[(pk, _), (pm, _)] -> c_shorthash ph pm (fromIntegral $ S.length m) pk 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