commit 282fa90825bbc04c324c58186da473cb380d0fc2
parent ab0957e305dff0243dcab11e381470585849fd20
Author: Jared Tobin <jared@jtobin.io>
Date: Sun, 22 Jun 2025 13:12:10 +0400
lib: vertical integration
Diffstat:
5 files changed, 80 insertions(+), 36 deletions(-)
diff --git a/README.md b/README.md
@@ -58,42 +58,37 @@ Haddocks (API documentation, etc.) are hosted at
The aim is best-in-class performance for pure, highly-auditable Haskell
code.
-Current benchmark figures on my mid-2020 MacBook Air look like (use
+Current benchmark figures on an M4 Silicon MacBook Air look like (use
`cabal bench` to run the benchmark suite):
```
benchmarking ppad-sha256/SHA256 (32B input)/hash
- time 1.387 μs (1.365 μs .. 1.409 μs)
- 0.999 R² (0.998 R² .. 1.000 R²)
- mean 1.386 μs (1.378 μs .. 1.399 μs)
- std dev 34.07 ns (24.55 ns .. 52.14 ns)
- variance introduced by outliers: 31% (moderately inflated)
+ time 879.7 ns (879.5 ns .. 879.9 ns)
+ 1.000 R² (1.000 R² .. 1.000 R²)
+ mean 880.1 ns (879.5 ns .. 882.1 ns)
+ std dev 3.504 ns (994.6 ps .. 7.537 ns)
benchmarking ppad-sha256/HMAC-SHA256 (32B input)/hmac
- time 5.618 μs (5.564 μs .. 5.681 μs)
- 0.999 R² (0.999 R² .. 1.000 R²)
- mean 5.648 μs (5.603 μs .. 5.697 μs)
- std dev 159.1 ns (130.7 ns .. 194.1 ns)
- variance introduced by outliers: 34% (moderately inflated)
+ time 3.322 μs (3.322 μs .. 3.322 μs)
+ 1.000 R² (1.000 R² .. 1.000 R²)
+ mean 3.321 μs (3.317 μs .. 3.323 μs)
+ std dev 10.53 ns (4.987 ns .. 19.12 ns)
```
-Compare this to Hackage's famous SHA package:
+Compare this to Hackage's venerable SHA package:
```
benchmarking ppad-sha256/SHA256 (32B input)/SHA.sha256
- time 2.585 μs (2.565 μs .. 2.613 μs)
- 0.999 R² (0.999 R² .. 1.000 R²)
- mean 2.635 μs (2.616 μs .. 2.654 μs)
- std dev 68.00 ns (58.45 ns .. 80.94 ns)
- variance introduced by outliers: 32% (moderately inflated)
+ time 1.415 μs (1.414 μs .. 1.415 μs)
+ 1.000 R² (1.000 R² .. 1.000 R²)
+ mean 1.415 μs (1.415 μs .. 1.415 μs)
+ std dev 1.334 ns (1.158 ns .. 1.576 ns)
benchmarking ppad-sha256/HMAC-SHA256 (32B input)/SHA.hmacSha256
- time 9.672 μs (9.533 μs .. 9.810 μs)
- 0.998 R² (0.998 R² .. 0.999 R²)
- mean 9.715 μs (9.608 μs .. 9.858 μs)
- std dev 394.7 ns (315.3 ns .. 576.2 ns)
- variance introduced by outliers: 50% (moderately inflated)
-
+ time 5.157 μs (5.156 μs .. 5.158 μs)
+ 1.000 R² (1.000 R² .. 1.000 R²)
+ mean 5.158 μs (5.157 μs .. 5.159 μs)
+ std dev 2.947 ns (2.413 ns .. 3.606 ns)
```
Or the relevant SHA-256-based functions from a library with similar
diff --git a/flake.lock b/flake.lock
@@ -34,6 +34,37 @@
"type": "github"
}
},
+ "ppad-base16": {
+ "inputs": {
+ "flake-utils": [
+ "ppad-base16",
+ "ppad-nixpkgs",
+ "flake-utils"
+ ],
+ "nixpkgs": [
+ "ppad-base16",
+ "ppad-nixpkgs",
+ "nixpkgs"
+ ],
+ "ppad-nixpkgs": [
+ "ppad-nixpkgs"
+ ]
+ },
+ "locked": {
+ "lastModified": 1741625558,
+ "narHash": "sha256-ZBDXRD5fsVqA5bGrAlcnhiu67Eo50q0M9614nR3NBwY=",
+ "ref": "master",
+ "rev": "fb63457f2e894eda28250dfe65d0fcd1d195ac2f",
+ "revCount": 24,
+ "type": "git",
+ "url": "git://git.ppad.tech/base16.git"
+ },
+ "original": {
+ "ref": "master",
+ "type": "git",
+ "url": "git://git.ppad.tech/base16.git"
+ }
+ },
"ppad-nixpkgs": {
"inputs": {
"flake-utils": "flake-utils",
@@ -64,6 +95,7 @@
"ppad-nixpkgs",
"nixpkgs"
],
+ "ppad-base16": "ppad-base16",
"ppad-nixpkgs": "ppad-nixpkgs"
}
},
diff --git a/flake.nix b/flake.nix
@@ -7,11 +7,18 @@
url = "git://git.ppad.tech/nixpkgs.git";
ref = "master";
};
+ ppad-base16 = {
+ type = "git";
+ url = "git://git.ppad.tech/base16.git";
+ ref = "master";
+ inputs.ppad-nixpkgs.follows = "ppad-nixpkgs";
+ };
flake-utils.follows = "ppad-nixpkgs/flake-utils";
nixpkgs.follows = "ppad-nixpkgs/nixpkgs";
};
- outputs = { self, nixpkgs, flake-utils, ppad-nixpkgs }:
+ outputs = { self, nixpkgs, flake-utils, ppad-nixpkgs
+ , ppad-base16 }:
flake-utils.lib.eachDefaultSystem (system:
let
lib = "ppad-sha256";
@@ -19,8 +26,13 @@
pkgs = import nixpkgs { inherit system; };
hlib = pkgs.haskell.lib;
+ base16 = ppad-base16.packages.${system}.default;
+
hpkgs = pkgs.haskell.packages.ghc981.extend (new: old: {
- ${lib} = old.callCabal2nixWithOptions lib ./. "--enable-profiling" {};
+ ppad-base16 = base16;
+ ${lib} = old.callCabal2nixWithOptions lib ./. "--enable-profiling" {
+ ppad-base16 = new.ppad-base16;
+ };
});
cc = pkgs.stdenv.cc;
diff --git a/ppad-sha256.cabal b/ppad-sha256.cabal
@@ -43,8 +43,8 @@ test-suite sha256-tests
build-depends:
aeson
, base
- , base16-bytestring
, bytestring
+ , ppad-base16
, ppad-sha256
, tasty
, tasty-hunit
diff --git a/test/Main.hs b/test/Main.hs
@@ -36,11 +36,16 @@ execute_group W.MacTestGroup {..} =
where
msg = "keysize " <> show mtg_keySize <> ", tagsize " <> show mtg_tagSize
+decodeLenient :: BS.ByteString -> BS.ByteString
+decodeLenient bs = case B16.decode bs of
+ Nothing -> error "bang"
+ Just b -> b
+
execute :: Int -> W.MacTest -> TestTree
execute tag_size W.MacTest {..} = testCase t_msg $ do
- let key = B16.decodeLenient (TE.encodeUtf8 mt_key)
- msg = B16.decodeLenient (TE.encodeUtf8 mt_msg)
- pec = B16.decodeLenient (TE.encodeUtf8 mt_tag)
+ let key = decodeLenient (TE.encodeUtf8 mt_key)
+ msg = decodeLenient (TE.encodeUtf8 mt_msg)
+ pec = decodeLenient (TE.encodeUtf8 mt_tag)
out = BS.take bytes (SHA256.hmac key msg)
if mt_result == "invalid"
then assertBool "invalid" (pec /= out)
@@ -149,7 +154,7 @@ hv5_pec = "50e72a0e26442fe2552dc3938ac58658228c0cbfb1d2ca872ae435266fcd055e"
-- https://datatracker.ietf.org/doc/html/rfc4231#section-4.1
hmv1_key :: BS.ByteString
-hmv1_key = B16.decodeLenient "0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b"
+hmv1_key = decodeLenient "0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b"
hmv1_put :: BS.ByteString
hmv1_put = "Hi There"
@@ -167,25 +172,25 @@ hmv2_pec :: BS.ByteString
hmv2_pec = "5bdcc146bf60754e6a042426089575c75a003f089d2739839dec58b964ec3843"
hmv3_key :: BS.ByteString
-hmv3_key = B16.decodeLenient "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+hmv3_key = decodeLenient "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
hmv3_put :: BS.ByteString
-hmv3_put = B16.decodeLenient "dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd"
+hmv3_put = decodeLenient "dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd"
hmv3_pec :: BS.ByteString
hmv3_pec = "773ea91e36800e46854db8ebd09181a72959098b3ef8c122d9635514ced565fe"
hmv4_key :: BS.ByteString
-hmv4_key = B16.decodeLenient "0102030405060708090a0b0c0d0e0f10111213141516171819"
+hmv4_key = decodeLenient "0102030405060708090a0b0c0d0e0f10111213141516171819"
hmv4_put :: BS.ByteString
-hmv4_put = B16.decodeLenient "cdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd"
+hmv4_put = decodeLenient "cdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd"
hmv4_pec :: BS.ByteString
hmv4_pec = "82558a389a443c0ea4cc819899f2083a85f0faa3e578f8077a2e3ff46729665b"
hmv5_key :: BS.ByteString
-hmv5_key = B16.decodeLenient "0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c"
+hmv5_key = decodeLenient "0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c"
hmv5_put :: BS.ByteString
hmv5_put = "Test With Truncation"
@@ -194,7 +199,7 @@ hmv5_pec :: BS.ByteString
hmv5_pec = "a3b6167473100ee06e0c796c2955552b"
hmv6_key :: BS.ByteString
-hmv6_key = B16.decodeLenient "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+hmv6_key = decodeLenient "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
hmv6_put :: BS.ByteString
hmv6_put = "Test Using Larger Than Block-Size Key - Hash Key First"