hs-blake2-0.0.1: src/Crypto/Hash/Tsuraan/Blake2/Parallel.hs
{-# 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 ""