Copyright | (c) 2024 Jared Tobin |
---|---|
License | MIT |
Maintainer | Jared Tobin <jared@ppad.tech> |
Safe Haskell | Safe-Inferred |
Language | Haskell2010 |
A pure HMAC-DRBG implementation, as specified by NIST SP-800-90A.
Synopsis
- data DRBG s
- type HMAC = ByteString -> ByteString -> ByteString
- new :: PrimMonad m => HMAC -> ByteString -> ByteString -> ByteString -> m (DRBG (PrimState m))
- gen :: PrimMonad m => ByteString -> Word64 -> DRBG (PrimState m) -> m ByteString
- reseed :: PrimMonad m => ByteString -> ByteString -> DRBG (PrimState m) -> m ()
DRBG and HMAC function types
A deterministic random bit generator (DRBG).
Create a DRBG with new
, and then use and reuse it to generate
bytes as needed.
type HMAC = ByteString -> ByteString -> ByteString Source #
A HMAC function, taking a key as the first argument and the input value as the second, producing a MAC digest.
>>>
import qualified Crypto.Hash.SHA256 as SHA256
>>>
:t SHA256.hmac
SHA256.hmac :: BS.ByteString -> BS.ByteString -> BS.ByteString
DRBG interaction
:: PrimMonad m | |
=> HMAC | HMAC function |
-> ByteString | entropy |
-> ByteString | nonce |
-> ByteString | personalization string |
-> m (DRBG (PrimState m)) |
Create a DRBG from the supplied HMAC function, entropy, nonce, and personalization string.
You can instantiate the DRBG using any appropriate HMAC function;
it should merely take a key and value as input, as is standard, and
return a MAC digest, each being a strict ByteString
.
The DRBG is returned in any PrimMonad
, e.g. ST
or IO
.
>>>
import qualified Crypto.Hash.SHA256 as SHA256
>>>
new SHA256.hmac entropy nonce personalization_string
"<drbg>"
:: PrimMonad m | |
=> ByteString | additional bytes to inject |
-> Word64 | number of bytes to generate |
-> DRBG (PrimState m) | |
-> m ByteString |
Generate bytes from a DRBG, optionally injecting additional bytes per SP 800-90A.
>>>
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
>>>
B16.encode bytes0
"938d6ca6d0b797f7b3c653349d6e3135">>>
B16.encode bytes1
"5f379d16de6f2c6f8a35c56f13f9e5a5"
:: PrimMonad m | |
=> ByteString | entropy to inject |
-> ByteString | additional bytes to inject |
-> DRBG (PrimState m) | |
-> m () |
Reseed a DRBG.
Each DRBG has an internal reseed counter that tracks the number of requests made to the generator (note requests made, not bytes generated). SP 800-90A specifies that a HMAC-DRBG should support 2 ^ 48 requests before requiring a reseed, so in practice you're unlikely to ever need to use this to actually reset the counter.
Note however that reseed
can be used to implement "explicit"
prediction resistance, per SP 800-90A, by injecting entropy generated
elsewhere into the DRBG.
>>>
import qualified System.Entropy as E
>>>
entropy <- E.getEntropy 32
>>>
reseed entropy addl_bytes drbg
"<reseeded drbg>"