{-# LANGUAGE OverloadedStrings #-} module Crypto.Hash.Tsuraan.Blake2.Parallel ( Ctx , init , init_key , update , finalize , hash , hash_key ) where import Data.ByteString ( ByteString ) import System.IO.Unsafe ( unsafePerformIO ) import Foreign.C ( CInt(..) ) import Foreign.Ptr ( Ptr ) import Foreign.Storable ( Storable(..) ) import Data.Word ( Word8 ) import Crypto.Hash.Tsuraan.Blake2.Internal ( BlakeState(..), runHasher, runInit, runInitKey, runUpdate, runFinalize ) import Prelude hiding ( init ) data Blake2bpState -- |Opaque type that tracks the Blake2 hashing state. The update and finalize -- functions mutate this context. newtype Ctx = Ctx (BlakeState Blake2bpState) deriving ( Show ) instance Storable Blake2bpState where sizeOf _ = unsafePerformIO blake2bp_size alignment _ = 64 -- from blake2.h; this should be automagical, I think peek _ = error "no peek" poke _a _b = error "no poke" foreign import ccall "blake2.h blake2bp" blake2bp :: Ptr Word8 -> Ptr Word8 -> Ptr Word8 -> Int -> Int -> Int -> IO CInt foreign import ccall "blake2.h blake2bp_init" blake2bp_init :: Ptr Blake2bpState -> Int -> IO CInt foreign import ccall "blake2.h blake2bp_init_key" blake2bp_init_key :: Ptr Blake2bpState -> Int -> Ptr Word8 -> Int -> IO CInt foreign import ccall "blake2.h blake2bp_update" blake2bp_update :: Ptr Blake2bpState -> Ptr Word8 -> Int -> IO CInt foreign import ccall "blake2.h blake2bp_final" blake2bp_final :: Ptr Blake2bpState -> Ptr Word8 -> Int -> IO CInt foreign import ccall "alloc.h blake2bp_size" blake2bp_size :: IO Int -- |Create a hashing context. init :: Int -- ^Desired digest size -> IO Ctx init outlen = Ctx `fmap` runInit blake2bp_init outlen -- |Create a hashing context for key-based hashing. init_key :: ByteString -- ^Desired hashing key -> Int -- ^Desired digest size -> IO Ctx init_key key outlen = Ctx `fmap` runInitKey blake2bp_init_key key outlen -- |Add more data to the hash. update :: Ctx -- ^Hashing context -> ByteString -- ^Data to add to the hash -> IO () update (Ctx ptr) bs = runUpdate blake2bp_update ptr bs -- |Finish hashing. This returns the digest of all the data that's been given -- to the 'update' function. finalize :: Ctx -- ^Hashing context -> IO ByteString finalize (Ctx state) = runFinalize blake2bp_final state -- |Hash a 'ByteString' into a digest 'ByteString' using a key. This function -- always runs in parallel, which is slower for very small strings but faster -- as the strings get larger. hash_key :: ByteString -- ^The key to hash with -> Int -- ^The digest size to generate; must be 1-64 -> ByteString -- ^The string to hash -> ByteString hash_key key hashlen bytes = runHasher blake2bp key hashlen bytes -- |Hash a 'ByteString' into a digest 'ByteString'. This function always runs -- in parallel, which is slower for very small strings but faster as the -- strings get larger. hash :: Int -- ^The digest size to generate; must be 1-64 -> ByteString -- ^The string to hash -> ByteString hash = hash_key ""