ppad-sha512 0.2.0 → 0.2.1
raw patch · 4 files changed
+75/−1 lines, 4 filesdep +quickcheck-instancesdep +tasty-quickcheckPVP ok
version bump matches the API change (PVP)
Dependencies added: quickcheck-instances, tasty-quickcheck
API changes (from Hackage documentation)
Files
- CHANGELOG +4/−0
- ppad-sha512.cabal +4/−1
- test/Main.hs +2/−0
- test/Property.hs +65/−0
CHANGELOG view
@@ -1,5 +1,9 @@ # Changelog +- 0.2.1 (2026-01-11)+ * Adds a basic quickcheck test suite for asserting memory safety of+ library functions on random inputs.+ - 0.2.0 (2026-01-10) * The HMAC functions now produce a value of type MAC, which is a newtype over a ByteString. The 'Eq' instance for MAC compares values
ppad-sha512.cabal view
@@ -1,6 +1,6 @@ cabal-version: 3.0 name: ppad-sha512-version: 0.2.0+version: 0.2.1 synopsis: The SHA-512 and HMAC-SHA512 algorithms license: MIT license-file: LICENSE@@ -49,6 +49,7 @@ hs-source-dirs: test main-is: Main.hs other-modules:+ Property Wycheproof ghc-options:@@ -60,8 +61,10 @@ , bytestring , ppad-base16 , ppad-sha512+ , quickcheck-instances , tasty , tasty-hunit+ , tasty-quickcheck , text benchmark sha512-bench
test/Main.hs view
@@ -14,6 +14,7 @@ import qualified Data.Text.IO as TIO import Test.Tasty import Test.Tasty.HUnit+import qualified Property import qualified Wycheproof as W main :: IO ()@@ -24,6 +25,7 @@ Just w -> defaultMain $ testGroup "ppad-sha512" [ unit_tests , wycheproof_tests w+ , Property.properties ] wycheproof_tests :: W.Wycheproof -> TestTree
+ test/Property.hs view
@@ -0,0 +1,65 @@+{-# OPTIONS_GHC -fno-warn-orphans #-}++module Property (+ properties+ ) where++import qualified Data.ByteString as BS+import qualified Data.ByteString.Lazy as BL+import Crypto.Hash.SHA512+import Test.Tasty+import qualified Test.Tasty.QuickCheck as Q+import Test.QuickCheck.Instances.ByteString ()++-- strict/lazy hash equivalence+hash_equiv :: BS.ByteString -> Bool+hash_equiv bs = hash bs == hash_lazy (BL.fromStrict bs)++-- strict/lazy hmac equivalence+hmac_equiv :: BS.ByteString -> BS.ByteString -> Bool+hmac_equiv k m = hmac k m == hmac_lazy k (BL.fromStrict m)++-- hash output is always 64 bytes+hash_length :: BS.ByteString -> Bool+hash_length bs = BS.length (hash bs) == 64++-- hmac output is always 64 bytes+hmac_length :: BS.ByteString -> BS.ByteString -> Bool+hmac_length k m = let MAC h = hmac k m in BS.length h == 64++-- hash_lazy produces same result regardless of chunking+hash_chunking :: BS.ByteString -> [Q.Positive Int] -> Bool+hash_chunking bs chunks =+ let lazy_single = BL.fromStrict bs+ lazy_chunked = BL.fromChunks (chunk_by (map Q.getPositive chunks) bs)+ in hash_lazy lazy_single == hash_lazy lazy_chunked++-- hmac_lazy produces same result regardless of chunking+hmac_chunking :: BS.ByteString -> BS.ByteString -> [Q.Positive Int] -> Bool+hmac_chunking k m chunks =+ let lazy_single = BL.fromStrict m+ lazy_chunked = BL.fromChunks (chunk_by (map Q.getPositive chunks) m)+ in hmac_lazy k lazy_single == hmac_lazy k lazy_chunked++chunk_by :: [Int] -> BS.ByteString -> [BS.ByteString]+chunk_by _ bs | BS.null bs = []+chunk_by [] bs = [bs]+chunk_by (n:ns) bs =+ let (h, t) = BS.splitAt n bs+ in h : chunk_by ns t++properties :: TestTree+properties = testGroup "properties" [+ Q.testProperty "hash == hash_lazy" $+ Q.withMaxSuccess 1000 hash_equiv+ , Q.testProperty "hmac == hmac_lazy" $+ Q.withMaxSuccess 1000 hmac_equiv+ , Q.testProperty "hash output is 64 bytes" $+ Q.withMaxSuccess 1000 hash_length+ , Q.testProperty "hmac output is 64 bytes" $+ Q.withMaxSuccess 1000 hmac_length+ , Q.testProperty "hash_lazy chunking-invariant" $+ Q.withMaxSuccess 1000 hash_chunking+ , Q.testProperty "hmac_lazy chunking-invariant" $+ Q.withMaxSuccess 1000 hmac_chunking+ ]