commit 5812ff7eedc5bb03f1166ef7b3843b6ec9cdcc0f
parent e4be3c94d2dd8cec85892fdc7c07eb3576502089
Author: Jared Tobin <jared@jtobin.io>
Date: Fri, 10 Jan 2025 18:28:19 +0400
lib: s/hkdf/derive
Gels nicer with a qualified import.
Diffstat:
4 files changed, 20 insertions(+), 14 deletions(-)
diff --git a/README.md b/README.md
@@ -9,11 +9,14 @@ A sample GHCi session:
```
> :set -XOverloadedStrings
+ > -- import qualified
+ > import qualified Crypto.KDF.HMAC as KDF
+ >
> -- supply your own HMAC function
> import qualified Crypto.Hash.SHA256 as SHA256
>
> -- derive a 32-byte key from a secret
- > hkdf SHA256.hmac "my salt" "my optional info" 32 "my secret input"
+ > KDF.derive SHA256.hmac "my salt" "my optional info" 32 "my secret input"
"\EM\232\v\140\202\230\f2:\221n\221\209\233\US\209>\174_!\138\255\\C\150\237^X\226\tt\252"
```
@@ -31,14 +34,14 @@ Current benchmark figures on my mid-2020 MacBook Air look like (use
`cabal bench` to run the benchmark suite):
```
- benchmarking ppad-hkdf/HKDF-SHA256/32
+ benchmarking ppad-hkdf/HKDF-SHA256/derive (outlen 32)
time 12.69 μs (12.58 μs .. 12.84 μs)
0.999 R² (0.999 R² .. 1.000 R²)
mean 12.82 μs (12.75 μs .. 12.89 μs)
std dev 231.0 ns (190.1 ns .. 299.9 ns)
variance introduced by outliers: 16% (moderately inflated)
- benchmarking ppad-hkdf/HKDF-SHA512/32
+ benchmarking ppad-hkdf/HKDF-SHA512/derive (outlen 32)
time 12.24 μs (12.16 μs .. 12.31 μs)
1.000 R² (1.000 R² .. 1.000 R²)
mean 12.27 μs (12.22 μs .. 12.32 μs)
diff --git a/bench/Main.hs b/bench/Main.hs
@@ -3,7 +3,7 @@
module Main where
import Criterion.Main
-import qualified Crypto.KDF.HMAC as K
+import qualified Crypto.KDF.HMAC as KDF
import qualified Crypto.Hash.SHA256 as SHA256
import qualified Crypto.Hash.SHA512 as SHA512
@@ -16,10 +16,12 @@ suite :: Benchmark
suite =
bgroup "ppad-hkdf" [
bgroup "HKDF-SHA256" [
- bench "32" $ nf (K.hkdf SHA256.hmac "muh salt" "muh info" 32) "muh secret"
+ bench "derive (outlen 32)" $
+ nf (KDF.derive SHA256.hmac "muh salt" "muh info" 32) "muh secret"
]
, bgroup "HKDF-SHA512" [
- bench "32" $ nf (K.hkdf SHA512.hmac "muh salt" "muh info" 32) "muh secret"
+ bench "derive (outlen 32)" $
+ nf (KDF.derive SHA512.hmac "muh salt" "muh info" 32) "muh secret"
]
]
diff --git a/lib/Crypto/KDF/HMAC.hs b/lib/Crypto/KDF/HMAC.hs
@@ -13,7 +13,7 @@
module Crypto.KDF.HMAC (
-- * HMAC-based KDF
- hkdf
+ derive
, HMAC
-- internals
@@ -75,22 +75,23 @@ expand (HMACEnv hmac hashlen) info (fi -> len) prk
in go (succ j) (t <> BSB.byteString nt) nt
{-# INLINE expand #-}
--- | HMAC-based key derivation function.
+-- | Derive a key from a secret, via a HMAC-based key derivation
+-- function.
--
-- The /salt/ and /info/ arguments are optional to the KDF, and may
-- be simply passed as 'mempty'. An empty salt will be replaced by
-- /hashlen/ zero bytes.
--
-- >>> import qualified Crypto.Hash.SHA256 as SHA256
--- >>> hkdf SHA256.hmac "my public salt" mempty 64 "my secret input"
+-- >>> derive SHA256.hmac "my public salt" mempty 64 "my secret input"
-- <64-byte output keying material>
-hkdf
+derive
:: HMAC -- ^ HMAC function
-> BS.ByteString -- ^ salt
-> BS.ByteString -- ^ optional context and application-specific info
-> Word64 -- ^ bytelength of output keying material (<= 255 * hashlen)
-> BS.ByteString -- ^ input keying material
-> BS.ByteString -- ^ output keying material
-hkdf hmac salt info len = expand env info len . extract env salt where
+derive hmac salt info len = expand env info len . extract env salt where
env = HMACEnv hmac (fi (BS.length (hmac mempty mempty)))
diff --git a/test/Main.hs b/test/Main.hs
@@ -6,7 +6,7 @@ module Main where
import Control.Exception
import qualified Crypto.Hash.SHA256 as SHA256
import qualified Crypto.Hash.SHA512 as SHA512
-import qualified Crypto.KDF.HMAC as H
+import qualified Crypto.KDF.HMAC as KDF
import qualified Data.ByteString as BS
import qualified Data.Aeson as A
import qualified Data.Text.IO as TIO
@@ -52,13 +52,13 @@ execute h W.HkdfTest {..} = testCase t_msg $ do
pec = ht_okm
if ht_result == "invalid"
then do
- out <- try (pure $! H.hkdf hmac sal inf siz ikm)
+ out <- try (pure $! KDF.derive hmac sal inf siz ikm)
:: IO (Either ErrorCall BS.ByteString)
case out of
Left _ -> assertBool "invalid" True
Right o -> assertBool "invalid" (pec /= o)
else do
- let out = H.hkdf hmac sal inf siz ikm
+ let out = KDF.derive hmac sal inf siz ikm
assertEqual mempty pec out
where
hmac = case h of