{-# LANGUAGE BangPatterns #-} -- | -- Module : Crypto.PubKey.MaskGenFunction -- License : BSD-style -- Maintainer : Vincent Hanquez -- Stability : experimental -- Portability : Good module Crypto.PubKey.MaskGenFunction ( MaskGenAlgorithm, mgf1, ) where import Crypto.Hash import Crypto.Internal.ByteArray (ByteArray, ByteArrayAccess, Bytes) import qualified Crypto.Internal.ByteArray as B import Crypto.Number.Serialize (i2ospOf_) -- | Represent a mask generation algorithm type MaskGenAlgorithm seed output = seed -- ^ seed -> Int -- ^ length to generate -> output -- | Mask generation algorithm MGF1 mgf1 :: (ByteArrayAccess seed, ByteArray output, HashAlgorithm hashAlg) => hashAlg -> seed -> Int -> output mgf1 hashAlg seed len = let !seededCtx = hashUpdate (hashInitWith hashAlg) seed in B.take len $ B.concat $ map (hashCounter seededCtx) [0 .. fromIntegral (maxCounter - 1)] where digestLen = hashDigestSize hashAlg (chunks, left) = len `divMod` digestLen maxCounter = if left > 0 then chunks + 1 else chunks hashCounter :: HashAlgorithm a => Context a -> Integer -> Digest a hashCounter ctx counter = hashFinalize $ hashUpdate ctx (i2ospOf_ 4 counter :: Bytes)