packages feed

phkdf-0.1.0.0: lib/Crypto/PHKDF/Subtle.hs

-------------------------------------------------------------------------------
-- |
-- Module:      Crypto.PHKDF.Subtle
-- Copyright:   (c) 2024 Auth Global
-- License:     Apache2
--
-------------------------------------------------------------------------------

module Crypto.PHKDF.Subtle
  ( PhkdfCtx(..)
  , phkdfCtx_unsafeFeed
  , PhkdfGen(..)
  ) where

import           Prelude hiding (null)
import           Crypto.Sha256 as Sha256
import           Crypto.PHKDF.HMAC (HmacKeyLike)
import           Data.ByteString (ByteString)
import qualified Data.ByteString as B
import           Data.Foldable(foldl', null)
import           Data.Word

-- I should be using the counter inside the sha256 ctx.
-- While this project is rapidly approaching maturity, it's still somewhat
-- proof of concept.  See the new SHA256 bindings WIP.

data PhkdfCtx = PhkdfCtx
  { phkdfCtx_byteCount :: !Word64
  , phkdfCtx_state :: !Sha256Ctx
  , phkdfCtx_hmacKeyLike :: !HmacKeyLike
  }

data P = P !Word64 !Sha256Ctx

phkdfCtx_unsafeFeed :: Foldable f => f ByteString -> PhkdfCtx -> PhkdfCtx
phkdfCtx_unsafeFeed strs ctx0 =
  if null strs then ctx0
  else ctx0 {
    phkdfCtx_byteCount = byteCount',
    phkdfCtx_state = state'
  }
  where
    delta (P len ctx) str = P (len + (fromIntegral (B.length str))) (sha256_update ctx str)

    p0 = P (phkdfCtx_byteCount ctx0) (phkdfCtx_state ctx0)

    P byteCount' state' = foldl' delta p0 strs

data PhkdfGen = PhkdfGen
  { phkdfGen_hmacKeyLike :: !HmacKeyLike
  , phkdfGen_extTag :: !ByteString
  , phkdfGen_counter :: !Word32
  , phkdfGen_state :: !ByteString
  , phkdfGen_initCtx :: !(Maybe Sha256Ctx)
  }