hkdf

Pure Haskell HMAC-based KDF (docs.ppad.tech/hkdf).
git clone git://git.ppad.tech/hkdf.git
Log | Files | Refs | README | LICENSE

commit 15b0f34e698b09de41f2e3a507a4a9fe00b036e7
parent 6091e423277423f574674649ed32ec640db8433d
Author: Jared Tobin <jared@jtobin.io>
Date:   Sun, 28 Dec 2025 12:25:13 -0330

release: v0.3.1

Diffstat:
MCHANGELOG | 3+++
MREADME.md | 13+++++++------
Mflake.lock | 50++++++++++++++++++++++++++++----------------------
Mflake.nix | 29+++++++++++++++++++++++------
Mppad-hkdf.cabal | 11+++++++++--
5 files changed, 70 insertions(+), 36 deletions(-)

diff --git a/CHANGELOG b/CHANGELOG @@ -1,5 +1,8 @@ # Changelog +- 0.3.1 (2025-12-28) + * Adds an 'llvm' build flag and tests with GHC 9.10.3. + - 0.3.0 (2025-06-21) * The 'derive' function is now total, returning 'Nothing' when supplied with bad inputs. diff --git a/README.md b/README.md @@ -39,16 +39,17 @@ Current benchmark figures on an M4 Silicon MacBook Air look like (use ``` benchmarking ppad-hkdf/HKDF-SHA256/derive (outlen 32) - time 6.787 μs (6.780 μs .. 6.792 μs) + time 1.549 μs (1.547 μs .. 1.553 μs) 1.000 R² (1.000 R² .. 1.000 R²) - mean 6.774 μs (6.769 μs .. 6.778 μs) - std dev 16.89 ns (14.95 ns .. 19.57 ns) + mean 1.565 μs (1.560 μs .. 1.572 μs) + std dev 20.80 ns (18.40 ns .. 24.68 ns) + variance introduced by outliers: 12% (moderately inflated) benchmarking ppad-hkdf/HKDF-SHA512/derive (outlen 32) - time 7.014 μs (7.007 μs .. 7.019 μs) + time 2.089 μs (2.088 μs .. 2.090 μs) 1.000 R² (1.000 R² .. 1.000 R²) - mean 7.003 μs (6.999 μs .. 7.008 μs) - std dev 16.60 ns (13.60 ns .. 20.14 ns) + mean 2.090 μs (2.088 μs .. 2.092 μs) + std dev 5.637 ns (3.965 ns .. 8.886 ns) ``` ## Security diff --git a/flake.lock b/flake.lock @@ -5,11 +5,11 @@ "systems": "systems" }, "locked": { - "lastModified": 1710146030, - "narHash": "sha256-SZ5L6eA7HJ/nmkzGG7/ISclqe6oZdOZTNoesiInkXPQ=", + "lastModified": 1731533236, + "narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=", "owner": "numtide", "repo": "flake-utils", - "rev": "b1d9ab70662946ef0850d488da1c9019f3a9752a", + "rev": "11707dc2f618dd54ca8739b309ec4fc024de578b", "type": "github" }, "original": { @@ -20,11 +20,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1725910328, - "narHash": "sha256-n9pCtzGZ0httmTwMuEbi5E78UQ4ZbQMr1pzi5N0LAG8=", + "lastModified": 1766840161, + "narHash": "sha256-Ss/LHpJJsng8vz1Pe33RSGIWUOcqM1fjrehjUkdrWio=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "5775c2583f1801df7b790bf7f7d710a19bac66f4", + "rev": "3edc4a30ed3903fdf6f90c837f961fa6b49582d1", "type": "github" }, "original": { @@ -51,11 +51,11 @@ ] }, "locked": { - "lastModified": 1741625558, - "narHash": "sha256-ZBDXRD5fsVqA5bGrAlcnhiu67Eo50q0M9614nR3NBwY=", + "lastModified": 1766934151, + "narHash": "sha256-BUFpuLfrGXE2xi3Wa9TYCEhhRhFp175Ghxnr0JRbG2I=", "ref": "master", - "rev": "fb63457f2e894eda28250dfe65d0fcd1d195ac2f", - "revCount": 24, + "rev": "58dfb7922401a60d5de76825fcd5f6ecbcd7afe0", + "revCount": 26, "type": "git", "url": "git://git.ppad.tech/base16.git" }, @@ -71,11 +71,11 @@ "nixpkgs": "nixpkgs" }, "locked": { - "lastModified": 1737297101, - "narHash": "sha256-EnXnq+JLflbWt+DvaGGnY2gfAqsGNOm5vPgHh3hkfwQ=", + "lastModified": 1766932084, + "narHash": "sha256-GvVsbTfW+B7IQ9K/QP2xcXJAm1lhBin1jYZWNjOzT+o=", "ref": "master", - "rev": "f29823875250bc99b3891f7373535ccde9a29a44", - "revCount": 1, + "rev": "353e61763b959b960a55321a85423501e3e9ed7a", + "revCount": 2, "type": "git", "url": "git://git.ppad.tech/nixpkgs.git" }, @@ -97,16 +97,19 @@ "ppad-nixpkgs", "nixpkgs" ], + "ppad-base16": [ + "ppad-base16" + ], "ppad-nixpkgs": [ "ppad-nixpkgs" ] }, "locked": { - "lastModified": 1740802974, - "narHash": "sha256-GTD9UrxwMa5zY7hxzDSXjKXKUwMK4r3FBHLG0nvgapk=", + "lastModified": 1766934663, + "narHash": "sha256-QFHvRxg/AN9/FHF9EyVui1os0sTxpawzsmxcHqcdhoc=", "ref": "master", - "rev": "ab0957e305dff0243dcab11e381470585849fd20", - "revCount": 94, + "rev": "0d9a7a2f83fc95bf3ac1d335d1c0237d397e44bc", + "revCount": 98, "type": "git", "url": "git://git.ppad.tech/sha256.git" }, @@ -128,16 +131,19 @@ "ppad-nixpkgs", "nixpkgs" ], + "ppad-base16": [ + "ppad-base16" + ], "ppad-nixpkgs": [ "ppad-nixpkgs" ] }, "locked": { - "lastModified": 1740802979, - "narHash": "sha256-6VAXmA1XiIT/WFcP+eFb6uK3YyfgVqIgDv3ASNIoCMs=", + "lastModified": 1766934908, + "narHash": "sha256-39ElMaWIjMW0BbHqINaHDjzpL8PsWNyvZn14QAKgPOo=", "ref": "master", - "rev": "ff165b29fb21b99749460ae7e3fdca42a85c822b", - "revCount": 28, + "rev": "4bb34de9a798e1954e09ec3b6d8d8b8db645e5d7", + "revCount": 32, "type": "git", "url": "git://git.ppad.tech/sha512.git" }, diff --git a/flake.nix b/flake.nix @@ -17,12 +17,14 @@ type = "git"; url = "git://git.ppad.tech/sha256.git"; ref = "master"; + inputs.ppad-base16.follows = "ppad-base16"; inputs.ppad-nixpkgs.follows = "ppad-nixpkgs"; }; ppad-sha512 = { type = "git"; url = "git://git.ppad.tech/sha512.git"; ref = "master"; + inputs.ppad-base16.follows = "ppad-base16"; inputs.ppad-nixpkgs.follows = "ppad-nixpkgs"; }; flake-utils.follows = "ppad-nixpkgs/flake-utils"; @@ -38,15 +40,30 @@ pkgs = import nixpkgs { inherit system; }; hlib = pkgs.haskell.lib; + llvm = pkgs.llvmPackages_19.llvm; base16 = ppad-base16.packages.${system}.default; + base16-llvm = + hlib.addBuildTools + (hlib.enableCabalFlag base16 "llvm") + [ llvm ]; + sha256 = ppad-sha256.packages.${system}.default; + sha256-llvm = + hlib.addBuildTools + (hlib.enableCabalFlag sha256 "llvm") + [ llvm ]; + sha512 = ppad-sha512.packages.${system}.default; + sha512-llvm = + hlib.addBuildTools + (hlib.enableCabalFlag sha512 "llvm") + [ llvm ]; - hpkgs = pkgs.haskell.packages.ghc981.extend (new: old: { - ppad-base16 = base16; - ppad-sha256 = sha256; - ppad-sha512 = sha512; + hpkgs = pkgs.haskell.packages.ghc910.extend (new: old: { + ppad-base16 = base16-llvm; + ppad-sha256 = sha256-llvm; + ppad-sha512 = sha512-llvm; ${lib} = new.callCabal2nix lib ./. { ppad-base16 = new.ppad-base16; ppad-sha256 = new.ppad-sha256; @@ -69,10 +86,9 @@ buildInputs = [ cabal cc + llvm ]; - inputsFrom = builtins.attrValues self.packages.${system}; - doBenchmark = true; shellHook = '' @@ -81,6 +97,7 @@ echo "cc: $(${cc}/bin/cc --version)" echo "ghc: $(${ghc}/bin/ghc --version)" echo "cabal: $(${cabal}/bin/cabal --version)" + echo "llc: $(${llvm}/bin/llc --version | head -2 | tail -1)" ''; }; } diff --git a/ppad-hkdf.cabal b/ppad-hkdf.cabal @@ -1,6 +1,6 @@ cabal-version: 3.0 name: ppad-hkdf -version: 0.3.0 +version: 0.3.1 synopsis: A HMAC-based key derivation function license: MIT license-file: LICENSE @@ -8,12 +8,17 @@ author: Jared Tobin maintainer: jared@ppad.tech category: Cryptography build-type: Simple -tested-with: GHC == { 9.8.1 } +tested-with: GHC == 9.10.3 extra-doc-files: CHANGELOG description: A pure implementation of the HMAC-based extract-and-expand key derivation function, per RFC5869. +flag llvm + description: Use GHC's LLVM backend. + default: False + manual: True + source-repository head type: git location: git.ppad.tech/hkdf.git @@ -23,6 +28,8 @@ library hs-source-dirs: lib ghc-options: -Wall + if flag(llvm) + ghc-options: -fllvm -O2 exposed-modules: Crypto.KDF.HMAC build-depends: