packages feed

ppad-hmac-drbg 0.1.3 → 0.2.0

raw patch · 5 files changed

+39/−17 lines, 5 filesPVP ok

version bump matches the API change (PVP)

API changes (from Hackage documentation)

+ Crypto.DRBG.HMAC: MaxBytesExceeded :: Error
+ Crypto.DRBG.HMAC: ReseedRequired :: Error
+ Crypto.DRBG.HMAC: data Error
+ Crypto.DRBG.HMAC: instance GHC.Classes.Eq Crypto.DRBG.HMAC.Error
+ Crypto.DRBG.HMAC: instance GHC.Show.Show Crypto.DRBG.HMAC.Error
- Crypto.DRBG.HMAC: gen :: PrimMonad m => ByteString -> Word64 -> DRBG (PrimState m) -> m ByteString
+ Crypto.DRBG.HMAC: gen :: PrimMonad m => ByteString -> Word64 -> DRBG (PrimState m) -> m (Either Error ByteString)

Files

CHANGELOG view
@@ -1,5 +1,13 @@ # Changelog +- 0.2.0 (2026-01-10)+  * In order to better-match the spec, 'gen' now returns an+    'Either Error BS.ByteString'. The new 'Error' value is returned+    either in the exceptionally rare case that the DRBG needs a reseed+    (previously this was just "error <msg>"), or, more likely to occur+    in practice, if more than 65536 bytes are requested from the DRBG at+    a time.+ - 0.1.3 (2025-12-28)   * Adds an 'llvm' build flag and tests with GHC 9.10.3. 
bench/Main.hs view
@@ -22,14 +22,14 @@     bgroup "HMAC-SHA256" [       bench "new" $ whnfAppIO (DRBG.new SHA256.hmac mempty mempty) mempty     , bench "reseed" $ whnfAppIO (DRBG.reseed mempty mempty) drbg256-    , bench "gen (32B)"  $ nfAppIO (DRBG.gen mempty 32) drbg256-    , bench "gen (256B)" $ nfAppIO (DRBG.gen mempty 256) drbg256+    , bench "gen (32B)"  $ whnfAppIO (DRBG.gen mempty 32) drbg256+    , bench "gen (256B)" $ whnfAppIO (DRBG.gen mempty 256) drbg256     ]   , bgroup "HMAC-SHA512" [       bench "new" $ whnfAppIO (DRBG.new SHA512.hmac mempty mempty) mempty     , bench "reseed" $ whnfAppIO (DRBG.reseed mempty mempty) drbg512-    , bench "gen (32B)"  $ nfAppIO (DRBG.gen mempty 32) drbg512-    , bench "gen (256B)" $ nfAppIO (DRBG.gen mempty 256) drbg512+    , bench "gen (32B)"  $ whnfAppIO (DRBG.gen mempty 32) drbg512+    , bench "gen (256B)" $ whnfAppIO (DRBG.gen mempty 256) drbg512     ]   ] 
lib/Crypto/DRBG/HMAC.hs view
@@ -14,9 +14,10 @@ module Crypto.DRBG.HMAC (   -- * DRBG and HMAC function types     DRBG+  , HMAC+  , Error(..)   , _read_v   , _read_k-  , HMAC    -- * DRBG interaction   , new@@ -53,6 +54,12 @@  -- types ---------------------------------------------------------------------- +-- | A DRBG error.+data Error =+    MaxBytesExceeded -- ^ More than 65536 bytes have been requested.+  | ReseedRequired   -- ^ The DRBG must be reseeded (via 'reseed').+  deriving (Eq, Show)+ -- see SP 800-90A table 2 _RESEED_COUNTER :: Word64 _RESEED_COUNTER = (2 :: Word64) ^ (48 :: Word64)@@ -143,10 +150,14 @@ -- | Generate bytes from a DRBG, optionally injecting additional bytes --   per SP 800-90A. --+--   Per SP 800-90A, the maximum number of bytes that can be requested+--   on any invocation is 65536. Larger requests will return+--   'MaxBytesExceeded'.+-- --   >>> import qualified Data.ByteString.Base16 as B16 --   >>> drbg <- new SHA256.hmac entropy nonce personalization_string---   >>> bytes0 <- gen addl_bytes 16 drbg---   >>> bytes1 <- gen addl_bytes 16 drbg+--   >>> Right bytes0 <- gen addl_bytes 16 drbg+--   >>> Right bytes1 <- gen addl_bytes 16 drbg --   >>> B16.encode bytes0 --   "938d6ca6d0b797f7b3c653349d6e3135" --   >>> B16.encode bytes1@@ -156,12 +167,14 @@   => BS.ByteString       -- ^ additional bytes to inject   -> Word64              -- ^ number of bytes to generate   -> DRBG (PrimState m)-  -> m BS.ByteString+  -> m (Either Error BS.ByteString) gen addl bytes (DRBG mut) = do   drbg0 <- P.readMutVar mut-  let !(Pair bs drbg1) = gen_pure addl bytes drbg0-  P.writeMutVar mut drbg1-  pure bs+  case gen_pure addl bytes drbg0 of+    Left e -> pure (Left e)+    Right !(Pair bs drbg1) -> do+      P.writeMutVar mut drbg1+      pure (Right bs)  -- | Reseed a DRBG. --@@ -237,14 +250,15 @@   :: BS.ByteString   -> Word64   -> DRBGState-  -> Pair BS.ByteString DRBGState+  -> Either Error (Pair BS.ByteString DRBGState) gen_pure addl bytes drbg0@(DRBGState h@(HMACEnv hmac outlen) _ _ _)-    | r > _RESEED_COUNTER = error "ppad-hmac-drbg: reseed required"+    | bytes > 0x10000     = Left MaxBytesExceeded+    | r > _RESEED_COUNTER = Left ReseedRequired     | otherwise =         let !(Pair temp drbg1) = loop mempty 0 v1             returned_bits = BS.take (fi bytes) temp             drbg = update_pure addl drbg1-        in  Pair returned_bits drbg+        in  Right (Pair returned_bits drbg)   where     !(DRBGState _ r v1 k1)       | BS.null addl = drbg0
ppad-hmac-drbg.cabal view
@@ -1,6 +1,6 @@ cabal-version:      3.0 name:               ppad-hmac-drbg-version:            0.1.3+version:            0.2.0 synopsis:           HMAC-based deterministic random bit generator license:            MIT license-file:       LICENSE
test/Main.hs view
@@ -103,7 +103,7 @@   assertEqual "k0" k0 caseK0    DRBG.reseed caseEntropy1 caseAddl1 drbg-  _ <- DRBG.gen mempty bytes drbg+  Right _ <- DRBG.gen mempty bytes drbg   v1 <- DRBG._read_v drbg   k1 <- DRBG._read_k drbg @@ -111,7 +111,7 @@   assertEqual "k1" k1 caseK1    DRBG.reseed caseEntropy2 caseAddl2 drbg-  returned <- DRBG.gen mempty bytes drbg+  Right returned <- DRBG.gen mempty bytes drbg   v2 <- DRBG._read_v drbg   k2 <- DRBG._read_k drbg