module Crypto.Random.DRBG.HashDF where import qualified Data.ByteString as B import qualified Data.ByteString.Lazy as L import Crypto.Classes import Data.Serialize (encode) import Data.Serialize.Put (runPut, putWord32be) import Data.Word (Word8, Word32) import Crypto.Random.DRBG.Types -- Section 10.4.1, pg 65 hash_df :: Hash c d => (L.ByteString -> d) -> B.ByteString -> BitLen -> B.ByteString hash_df hashF str reqBits = B.take reqBytes $ getT B.empty (1 :: Word8) where reqBytes = reqBits `div` 8 outlen = outputLength .::. (hashF undefined) hash = encode . hashF . L.fromChunks . \x -> [x] getT tmp cnt | B.length tmp >= reqBytes = tmp | otherwise = let new = hash (B.concat [B.singleton cnt, reqBitsBS, str]) in getT (B.append tmp new) (cnt + 1) len = (if reqBits `rem` outlen == 0 then reqBits `div` outlen else (reqBits + outlen) `div` outlen) reqBitsBS = runPut $ putWord32be (fromIntegral reqBits :: Word32)