hmac-drbg

Pure Haskell HMAC-DRBG (docs.ppad.tech/hmac-drbg).
git clone git://git.ppad.tech/hmac-drbg.git
Log | Files | Refs | README | LICENSE

commit c4b5f63bcf084357cf1b9b958e58cf4b1165871d
parent de2e199b2f48e3e10fb804a89fabde63163bd12c
Author: Jared Tobin <jared@jtobin.io>
Date:   Sun,  1 Feb 2026 15:53:09 +0400

meta: update readme

Diffstat:
MREADME.md | 37++++++++++++++++++-------------------
1 file changed, 18 insertions(+), 19 deletions(-)

diff --git a/README.md b/README.md @@ -18,47 +18,44 @@ A sample GHCi session: > import qualified Data.ByteString.Base16 as B16 > > -- import qualified - > import qualified Crypto.DRBG.HMAC as DRBG - > - > -- supply your own HMAC function - > import qualified Crypto.Hash.SHA256 as SHA256 + > import qualified Crypto.DRBG.HMAC.SHA256 as DRBG > > -- instantiate a DRBG > let entropy = "very random" > let nonce = "very unused" > let personalization_string = "very personal" > - > drbg <- DRBG.new SHA256.hmac entropy nonce personalization_string + > drbg <- DRBG.new entropy nonce personalization_string > > -- use it to generate some bytes > - > fmap B16.encode (DRBG.gen mempty 32 drbg) - "e4d17210810c4b343f6eae2c19e3d82395b555294b1b16a85f91dbea67e5f277" + > fmap B16.encode <$> DRBG.gen drbg mempty 32 + Right "e4d17210810c4b343f6eae2c19e3d82395b555294b1b16a85f91dbea67e5f277" > > -- reuse the generator to get more; the state is updated automatically > - > fmap B16.encode (DRBG.gen mempty 16 drbg) - "5d867730d99eb5335f16b1d622f03023" + > fmap B16.encode <$> DRBG.gen drbg mempty 16 + Right "5d867730d99eb5335f16b1d622f03023" > > -- this DRBG was instantiated in the IO monad: > > :t drbg drbg :: DRBG.DRBG ghc-prim:GHC.Prim.RealWorld > - > -- but you can also use use ST to keep things pure: + > -- but you can also use ST to keep things pure: > > import Control.Monad.ST > > :{ - ghci| let drbg_pure = DRBG.new SHA256.hmac mempty mempty mempty :: + ghci| let drbg_pure = DRBG.new mempty mempty mempty :: ghci| forall s. ST s (DRBG.DRBG s) ghci| :} > > :t drbg_pure drbg_pure :: ST s (DRBG.DRBG s) > - > runST $ drbg_pure >>= fmap B16.encode . DRBG.gen mempty 16 - "b44299907e4e42aa4fded5d6153e8bac" + > runST $ drbg_pure >>= fmap (fmap B16.encode) . (\d -> DRBG.gen d mempty 16) + Right "b44299907e4e42aa4fded5d6153e8bac" ``` ## Documentation @@ -102,9 +99,7 @@ Current benchmark figures on an M4 Silicon MacBook Air look like (use std dev 15.77 ns (12.15 ns .. 21.36 ns) ``` -You should compile with the 'llvm' flag (and ensure that -[ppad-sha256][sh256] has been compiled with the 'llvm' flag) for -maximum performance. +You should compile with the 'llvm' flag for maximum performance. ## Security @@ -113,9 +108,13 @@ garbage-collected language under an optimizing compiler such as GHC, in which strict constant-timeness can be [challenging to achieve][const]. The HMAC-DRBG implementation within has been tested against the -NIST DRBGVS vectors available for SHA-256 and SHA-512, using the -HMAC functions from [ppad-sha256][sh256] and [ppad-sha512][sh512] -respectively. +NIST DRBGVS vectors available for SHA-256 and SHA-512. + +DRBG internal state, which must be kept secret, is kept in a single, +pinned, heap-allocated mutable buffer. It is never copied, is guaranteed +never to be moved around by the garbage collector, and its components +are never allocated anywhere else on the heap. You should zero out the +DRBG state via the 'wipe' function when you've finished using it. If you discover any vulnerabilities, please disclose them via security@ppad.tech.