A Haskell implementation of SHA-256 and HMAC-SHA256 on strict and lazy ByteStrings, as specified by RFC's 6234 and 2104, that uses ARM SHA2 or x86 SHA intrinsics when available.
A sample GHCi session:
> :set -XOverloadedStrings
>
> -- import qualified
> import qualified Crypto.Hash.SHA256 as SHA256
>
> -- 'hash' and 'hmac' operate on strict bytestrings
> -- 'hmac' returns a value of type 'MAC' with a constant-time Eq instance
>
> let hash_s = SHA256.hash "strict bytestring input"
> let hmac_s = SHA256.hmac "strict secret" "strict bytestring input"
>
> -- 'hash_lazy' and 'hmac_lazy' operate on lazy bytestrings
> -- but note that the key for HMAC is always strict
>
> let hash_l = SHA256.hash_lazy "lazy bytestring input"
> let MAC hmac_l = SHA256.hmac_lazy "strict secret" "lazy bytestring input"
>
> -- digests are always unformatted 256-bit (32-byte) strict bytestrings
>
> import qualified Data.ByteString as BS
>
> BS.take 10 hash_s
"1\223\152Ha\USB\171V\a"
> BS.take 10 hmac_l
"\DELSOk\180\242\182'v\187"
>
> -- you can use third-party libraries for rendering if needed
> -- e.g., using ppad-base16:
>
> import qualified Data.ByteString.Base16 as B16
>
> B16.encode hash_s
"31df9848611f42ab5607ea9e6de84b05d5259085abb30a7917d85efcda42b0e3"
> B16.encode hmac_l
"7f534f6bb4f2b62776bba3d6466e384505f2ff89c91f39800d7a0d4623a4711e"
Haddocks (API documentation, etc.) are hosted at docs.ppad.tech/sha256.
The aim is best-in-class performance. We avail of hardware
acceleration via the ARM SHA2 extensions on aarch64, and the x86 SHA
extensions on x86_64, whenever the CPU supports them. 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 65.85 ns (65.76 ns .. 65.95 ns)
1.000 R² (1.000 R² .. 1.000 R²)
mean 65.90 ns (65.80 ns .. 65.99 ns)
std dev 307.5 ps (256.0 ps .. 392.9 ps)
benchmarking ppad-sha256/HMAC-SHA256 (32B input)/hmac
time 135.7 ns (135.2 ns .. 136.1 ns)
1.000 R² (1.000 R² .. 1.000 R²)
mean 136.3 ns (135.9 ns .. 136.7 ns)
std dev 1.298 ns (1.141 ns .. 1.474 ns)
You should compile with the 'llvm' flag for maximum performance.
The security properties of this library have been examined and defended in a security analysis at ppad.tech.
The HMAC-SHA256 functions within pass all Wycheproof vectors, as well as various other useful unit test vectors found around the internet.
If you discover any vulnerabilities, please disclose them via security@ppad.tech.
You'll require Nix with flake support enabled. Enter a development shell with:
$ nix develop
Then do e.g.:
$ cabal repl ppad-sha256
to get a REPL for the main library.
This implementation has benefitted immensely from the SHA package available on Hackage, which was used as a reference during development. Many parts wound up being direct translations.