cryptohash-sha1 0.11.7.2 → 0.11.100.0
raw patch · 4 files changed
+104/−11 lines, 4 filesPVP ok
version bump matches the API change (PVP)
API changes (from Hackage documentation)
+ Crypto.Hash.SHA1: hmac :: ByteString -> ByteString -> ByteString
+ Crypto.Hash.SHA1: hmaclazy :: ByteString -> ByteString -> ByteString
Files
- changelog.md +5/−0
- cryptohash-sha1.cabal +2/−1
- src-tests/test-sha1.hs +48/−6
- src/Crypto/Hash/SHA1.hs +49/−4
changelog.md view
@@ -1,3 +1,8 @@+## 0.11.100.0++ - new `hmac` and `hmaclazy` functions providing HMAC-SHA1+ computation conforming to RFC2104 and RFC2202+ ## 0.11.7.2 - switch to 'safe' FFI for calls where overhead becomes neglible
cryptohash-sha1.cabal view
@@ -1,8 +1,9 @@ name: cryptohash-sha1-version: 0.11.7.2+version: 0.11.100.0 description: A practical incremental and one-pass, pure API to the <https://en.wikipedia.org/wiki/SHA-1 SHA-1 hash algorithm>+ (including <https://en.wikipedia.org/wiki/HMAC HMAC> support) with performance close to the fastest implementations available in other languages. . The implementation is made in C with a haskell FFI wrapper that hides the C implementation.
src-tests/test-sha1.hs view
@@ -90,13 +90,40 @@ where vecXL = BL.fromChunks (replicate 16777216 "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmno") - splitB :: Int -> ByteString -> [ByteString]- splitB l b- | B.length b > l = b1 : splitB l b2- | otherwise = [b]+splitB :: Int -> ByteString -> [ByteString]+splitB l b+ | B.length b > l = b1 : splitB l b2+ | otherwise = [b]+ where+ (b1, b2) = B.splitAt l b+++rfc2202Vectors :: [(ByteString,ByteString,ByteString)]+rfc2202Vectors = -- (secrect,msg,mac)+ [ (rep 20 0x0b, "Hi There", x"b617318655057264e28bc0b6fb378c8ef146be00")+ , ("Jefe", "what do ya want for nothing?", x"effcdf6ae5eb2fa2d27416d5f184df9c259a7c79")+ , (rep 20 0xaa, rep 50 0xdd, x"125d7342b9ac11cd91a39af48aa17b4f63f175d3")+ , (B.pack [1..25], rep 50 0xcd, x"4c9007f4026250c6bc8414f9bf50c86c2d7235da")+ , (rep 20 0x0c, "Test With Truncation", x"4c1a03424b55e07fe7f27be1d58bb9324a9a5a04")+ , (rep 80 0xaa, "Test Using Larger Than Block-Size Key - Hash Key First", x"aa4ae5e15272d00e95705637ce8a3b55ed402112")+ , (rep 80 0xaa, "Test Using Larger Than Block-Size Key and Larger Than One Block-Size Data", x"e8e99d0f45237d786d6bbaa7965c7808bbff1a91")+ , (rep 80 0xaa, "Test Using Larger Than Block-Size Key - Hash Key First", x"aa4ae5e15272d00e95705637ce8a3b55ed402112")+ , (rep 80 0xaa, "Test Using Larger Than Block-Size Key and Larger Than One Block-Size Data", x"e8e99d0f45237d786d6bbaa7965c7808bbff1a91")+ ]+ where+ x = fst.B16.decode+ rep n c = B.replicate n c++rfc2202Tests = zipWith makeTest [1::Int ..] rfc2202Vectors+ where+ makeTest i (key, msg, mac) = testGroup ("vec"++show i) $+ [ testCase "hmac" (hex mac @=? hex (IUT.hmac key msg))+ , testCase "hmaclazy" (hex mac @=? hex (IUT.hmaclazy key lazymsg))+ ] where- (b1, b2) = B.splitAt l b+ lazymsg = BL.fromChunks . splitB 1 $ msg + hex = B16.encode -- define own 'foldl' here to avoid RULE rewriting to 'hashlazy' myfoldl' :: (b -> a -> b) -> b -> [a] -> b@@ -129,6 +156,8 @@ refImplTests = [ testProperty "hash" prop_hash , testProperty "hashlazy" prop_hashlazy+ , testProperty "hmac" prop_hmac+ , testProperty "hmaclazy" prop_hmaclazy ] where prop_hash (RandBS bs)@@ -137,12 +166,24 @@ prop_hashlazy (RandLBS bs) = ref_hashlazy bs == IUT.hashlazy bs + prop_hmac (RandBS k) (RandBS bs)+ = ref_hmac k bs == IUT.hmac k bs++ prop_hmaclazy (RandBS k) (RandLBS bs)+ = ref_hmaclazy k bs == IUT.hmaclazy k bs+ ref_hash :: ByteString -> ByteString- ref_hash = toStrict . REF.bytestringDigest . REF.sha1 . fromStrict+ ref_hash = ref_hashlazy . fromStrict ref_hashlazy :: BL.ByteString -> ByteString ref_hashlazy = toStrict . REF.bytestringDigest . REF.sha1 + ref_hmac :: ByteString -> ByteString -> ByteString+ ref_hmac secret = ref_hmaclazy secret . fromStrict++ ref_hmaclazy :: ByteString -> BL.ByteString -> ByteString+ ref_hmaclazy secret = toStrict . REF.bytestringDigest . REF.hmacSha1 (fromStrict secret)+ -- toStrict/fromStrict only available with bytestring-0.10 and later toStrict = B.concat . BL.toChunks fromStrict = BL.fromChunks . (:[])@@ -150,5 +191,6 @@ main :: IO () main = defaultMain $ testGroup "cryptohash-sha1" [ testGroup "KATs" katTests+ , testGroup "RFC2202" rfc2202Tests , testGroup "REF" refImplTests ]
src/Crypto/Hash/SHA1.hs view
@@ -63,7 +63,15 @@ -- package is recommended. , hash -- :: ByteString -> ByteString- , hashlazy -- :: ByteString -> ByteString+ , hashlazy -- :: L.ByteString -> ByteString++ -- ** HMAC-SHA1+ --+ -- | <https://tools.ietf.org/html/rfc2104 RFC2104>-compatible+ -- <https://en.wikipedia.org/wiki/HMAC HMAC>-SHA1 digests++ , hmac -- :: ByteString -> ByteString -> ByteString+ , hmaclazy -- :: ByteString -> L.ByteString -> ByteString ) where import Prelude hiding (init)@@ -76,6 +84,7 @@ import Data.ByteString (ByteString) import Data.ByteString.Unsafe (unsafeUseAsCStringLen) import Data.ByteString.Internal (create, toForeignPtr, memcpy)+import Data.Bits (xor) import Data.Word import System.IO.Unsafe (unsafeDupablePerformIO) @@ -195,20 +204,56 @@ | otherwise = error "SHA1.updates: invalid Ctx" {-# NOINLINE finalize #-}--- | finalize the context into a digest bytestring (16 bytes)+-- | finalize the context into a digest bytestring (20 bytes) finalize :: Ctx -> ByteString finalize ctx | validCtx ctx = unsafeDoIO $ withCtxThrow ctx finalizeInternalIO | otherwise = error "SHA1.finalize: invalid Ctx" {-# NOINLINE hash #-}--- | hash a strict bytestring into a digest bytestring (16 bytes)+-- | hash a strict bytestring into a digest bytestring (20 bytes) hash :: ByteString -> ByteString hash d = unsafeDoIO $ withCtxNewThrow $ \ptr -> do c_sha1_init ptr >> updateInternalIO ptr d >> finalizeInternalIO ptr {-# NOINLINE hashlazy #-}--- | hash a lazy bytestring into a digest bytestring (16 bytes)+-- | hash a lazy bytestring into a digest bytestring (20 bytes) hashlazy :: L.ByteString -> ByteString hashlazy l = unsafeDoIO $ withCtxNewThrow $ \ptr -> do c_sha1_init ptr >> mapM_ (updateInternalIO ptr) (L.toChunks l) >> finalizeInternalIO ptr+++{-# NOINLINE hmac #-}+-- | Compute 20-byte <https://tools.ietf.org/html/rfc2104 RFC2104>-compatible+-- HMAC-SHA1 digest for a strict bytestring message+--+-- @since 0.11.100.0+hmac :: ByteString -- ^ secret+ -> ByteString -- ^ message+ -> ByteString+hmac secret msg = hash $ B.append opad (hash $ B.append ipad msg)+ where+ opad = B.map (xor 0x5c) k'+ ipad = B.map (xor 0x36) k'++ k' = B.append kt pad+ kt = if B.length secret > 64 then hash secret else secret+ pad = B.replicate (64 - B.length kt) 0+++{-# NOINLINE hmaclazy #-}+-- | Compute 20-byte <https://tools.ietf.org/html/rfc2104 RFC2104>-compatible+-- HMAC-SHA1 digest for a lazy bytestring message+--+-- @since 0.11.100.0+hmaclazy :: ByteString -- ^ secret+ -> L.ByteString -- ^ message+ -> ByteString+hmaclazy secret msg = hash $ B.append opad (hashlazy $ L.append ipad msg)+ where+ opad = B.map (xor 0x5c) k'+ ipad = L.fromChunks [B.map (xor 0x36) k']++ k' = B.append kt pad+ kt = if B.length secret > 64 then hash secret else secret+ pad = B.replicate (64 - B.length kt) 0