1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
|
-- |
-- Module : Crypto.PubKey.MaskGenFunction
-- License : BSD-style
-- Maintainer : Vincent Hanquez <vincent@snarc.org>
-- Stability : experimental
-- Portability : Good
--
{-# LANGUAGE BangPatterns #-}
module Crypto.PubKey.MaskGenFunction
( MaskGenAlgorithm
, mgf1
) where
import Crypto.Number.Serialize (i2ospOf_)
import Crypto.Hash
import Crypto.Internal.ByteArray (ByteArrayAccess, ByteArray, Bytes)
import qualified Crypto.Internal.ByteArray as B
-- | 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)
|