cryptohash 0.10.0 → 0.11.0
raw patch · 23 files changed
+180/−74 lines, 23 filesdep ~base
Dependency ranges changed: base
Files
- Bench/BenchHMAC.hs +12/−0
- Crypto/Hash.hs +99/−61
- Crypto/Hash/MD2.hs +1/−0
- Crypto/Hash/MD4.hs +1/−0
- Crypto/Hash/MD5.hs +1/−0
- Crypto/Hash/RIPEMD160.hs +1/−0
- Crypto/Hash/SHA1.hs +1/−0
- Crypto/Hash/SHA224.hs +1/−0
- Crypto/Hash/SHA256.hs +1/−0
- Crypto/Hash/SHA3.hs +1/−0
- Crypto/Hash/SHA384.hs +1/−0
- Crypto/Hash/SHA512.hs +1/−0
- Crypto/Hash/SHA512t.hs +1/−0
- Crypto/Hash/Skein256.hs +1/−0
- Crypto/Hash/Skein512.hs +1/−0
- Crypto/Hash/Tiger.hs +1/−0
- Crypto/Hash/Types.hs +3/−0
- Crypto/Hash/Utils.hs +2/−0
- Crypto/Hash/Whirlpool.hs +1/−0
- README.md +3/−3
- Tests/KAT.hs +29/−6
- cbits/bitfn.h +6/−0
- cryptohash.cabal +11/−4
+ Bench/BenchHMAC.hs view
@@ -0,0 +1,12 @@++import Criterion.Main+import Crypto.Hash+import qualified Data.ByteString as B+import Data.Byteable++main = do+ let b32 = B.replicate 32 0+ defaultMain+ [ bench "hmac-md5" $ whnf (toBytes . hmac MD5 b32) b32+ , bench "hmac-sha1" $ whnf (toBytes . hmac SHA1 b32) b32+ ]
Crypto/Hash.hs view
@@ -1,4 +1,3 @@-{-# LANGUAGE EmptyDataDecls #-} {-# LANGUAGE CPP #-} -- | -- Module : Crypto.Hash@@ -23,33 +22,34 @@ , hash , hashlazy , hashUpdate+ , hashInitAlg -- * hash algorithms- , MD2- , MD4- , MD5- , SHA1- , SHA224- , SHA256- , SHA384- , SHA512- , RIPEMD160- , Tiger- , SHA3_224- , SHA3_256- , SHA3_384- , SHA3_512- , Skein256_224- , Skein256_256- , Skein512_224- , Skein512_256- , Skein512_384- , Skein512_512- , Whirlpool+ , MD2(..)+ , MD4(..)+ , MD5(..)+ , SHA1(..)+ , SHA224(..)+ , SHA256(..)+ , SHA384(..)+ , SHA512(..)+ , RIPEMD160(..)+ , Tiger(..)+ , SHA3_224(..)+ , SHA3_256(..)+ , SHA3_384(..)+ , SHA3_512(..)+ , Skein256_224(..)+ , Skein256_256(..)+ , Skein512_224(..)+ , Skein512_256(..)+ , Skein512_384(..)+ , Skein512_512(..)+ , Whirlpool(..) -- * MAC algorithms , HMAC(..) , hmac- )- where+ , hmacAlg+ ) where import Crypto.Hash.Types import Crypto.Hash.Utils@@ -96,71 +96,109 @@ digestToHexByteString :: Digest a -> ByteString digestToHexByteString = toHex . toBytes -#define DEFINE_INSTANCE(NAME, MODULENAME) \-data NAME; \+#define DEFINE_INSTANCE(NAME, MODULENAME, BLOCKSIZE) \+data NAME = NAME deriving Show; \ instance HashAlgorithm NAME where \ { hashInit = Context c where { (MODULENAME.Ctx c) = MODULENAME.init } \+ ; hashBlockSize ~(Context _) = BLOCKSIZE \ ; hashUpdates (Context c) bs = Context nc where { (MODULENAME.Ctx nc) = MODULENAME.updates (MODULENAME.Ctx c) bs } \ ; hashFinalize (Context c) = Digest $ MODULENAME.finalize (MODULENAME.Ctx c) \ ; digestFromByteString bs = if B.length bs == len then (Just $ Digest bs) else Nothing where { len = B.length (MODULENAME.finalize MODULENAME.init) } \ }; -#define DEFINE_INSTANCE_LEN(NAME, MODULENAME, LEN) \-data NAME; \+#define DEFINE_INSTANCE_LEN(NAME, MODULENAME, LEN, BLOCKSIZE) \+data NAME = NAME deriving Show; \ instance HashAlgorithm NAME where \ { hashInit = Context c where { (MODULENAME.Ctx c) = MODULENAME.init LEN } \+ ; hashBlockSize ~(Context _) = BLOCKSIZE \ ; hashUpdates (Context c) bs = Context nc where { (MODULENAME.Ctx nc) = MODULENAME.updates (MODULENAME.Ctx c) bs } \ ; hashFinalize (Context c) = Digest $ MODULENAME.finalize (MODULENAME.Ctx c) \ ; digestFromByteString bs = if B.length bs == len then (Just $ Digest bs) else Nothing where { len = B.length (MODULENAME.finalize (MODULENAME.init LEN)) } \ }; -DEFINE_INSTANCE(MD2, MD2)-DEFINE_INSTANCE(MD4, MD4)-DEFINE_INSTANCE(MD5, MD5)-DEFINE_INSTANCE(SHA1, SHA1)-DEFINE_INSTANCE(SHA224, SHA224)-DEFINE_INSTANCE(SHA256, SHA256)-DEFINE_INSTANCE(SHA384, SHA384)-DEFINE_INSTANCE(SHA512, SHA512)+-- | MD2 cryptographic hash+DEFINE_INSTANCE(MD2, MD2, 16)+-- | MD4 cryptographic hash+DEFINE_INSTANCE(MD4, MD4, 64)+-- | MD5 cryptographic hash+DEFINE_INSTANCE(MD5, MD5, 64)+-- | SHA1 cryptographic hash+DEFINE_INSTANCE(SHA1, SHA1, 64)+-- | SHA224 cryptographic hash+DEFINE_INSTANCE(SHA224, SHA224, 64)+-- | SHA256 cryptographic hash+DEFINE_INSTANCE(SHA256, SHA256, 64)+-- | SHA384 cryptographic hash+DEFINE_INSTANCE(SHA384, SHA384, 128)+-- | SHA512 cryptographic hash+DEFINE_INSTANCE(SHA512, SHA512, 128) -DEFINE_INSTANCE(RIPEMD160, RIPEMD160)-DEFINE_INSTANCE(Whirlpool, Whirlpool)-DEFINE_INSTANCE(Tiger, Tiger)+-- | RIPEMD160 cryptographic hash+DEFINE_INSTANCE(RIPEMD160, RIPEMD160, 64)+-- | Whirlpool cryptographic hash+DEFINE_INSTANCE(Whirlpool, Whirlpool, 64)+-- | Tiger cryptographic hash+DEFINE_INSTANCE(Tiger, Tiger, 64) -DEFINE_INSTANCE_LEN(SHA3_224, SHA3, 224)-DEFINE_INSTANCE_LEN(SHA3_256, SHA3, 256)-DEFINE_INSTANCE_LEN(SHA3_384, SHA3, 384)-DEFINE_INSTANCE_LEN(SHA3_512, SHA3, 512)+-- | SHA3 (224 bits version) cryptographic hash+DEFINE_INSTANCE_LEN(SHA3_224, SHA3, 224, 144)+-- | SHA3 (256 bits version) cryptographic hash+DEFINE_INSTANCE_LEN(SHA3_256, SHA3, 256, 136)+-- | SHA3 (384 bits version) cryptographic hash+DEFINE_INSTANCE_LEN(SHA3_384, SHA3, 384, 104)+-- | SHA3 (512 bits version) cryptographic hash+DEFINE_INSTANCE_LEN(SHA3_512, SHA3, 512, 72) -DEFINE_INSTANCE_LEN(Skein256_224, Skein256, 224)-DEFINE_INSTANCE_LEN(Skein256_256, Skein256, 256)+-- | Skein256 (224 bits version) cryptographic hash+DEFINE_INSTANCE_LEN(Skein256_224, Skein256, 224, 32)+-- | Skein256 (256 bits version) cryptographic hash+DEFINE_INSTANCE_LEN(Skein256_256, Skein256, 256, 32) -DEFINE_INSTANCE_LEN(Skein512_224, Skein512, 224)-DEFINE_INSTANCE_LEN(Skein512_256, Skein512, 256)-DEFINE_INSTANCE_LEN(Skein512_384, Skein512, 384)-DEFINE_INSTANCE_LEN(Skein512_512, Skein512, 512)+-- | Skein512 (224 bits version) cryptographic hash+DEFINE_INSTANCE_LEN(Skein512_224, Skein512, 224, 64)+-- | Skein512 (256 bits version) cryptographic hash+DEFINE_INSTANCE_LEN(Skein512_256, Skein512, 256, 64)+-- | Skein512 (384 bits version) cryptographic hash+DEFINE_INSTANCE_LEN(Skein512_384, Skein512, 384, 64)+-- | Skein512 (512 bits version) cryptographic hash+DEFINE_INSTANCE_LEN(Skein512_512, Skein512, 512, 64) +-- | Initialize a new context for a specified hash algorithm+hashInitAlg :: HashAlgorithm alg => alg -> Context alg+hashInitAlg _ = hashInit+ -- | Represent an HMAC that is a phantom type with the hash used to produce the mac. -- -- The Eq instance is constant time.-data HMAC a = HMAC ByteString+newtype HMAC a = HMAC { hmacGetDigest :: Digest a } instance Byteable (HMAC a) where- toBytes (HMAC b) = b+ toBytes (HMAC b) = toBytes b instance Eq (HMAC a) where- (HMAC b1) == (HMAC b2) = constEqBytes b1 b2+ (HMAC b1) == (HMAC b2) = constEqBytes (toBytes b1) (toBytes b2) -- | compute a MAC using the supplied hashing function-hmac :: HashFunctionBS a -- ^ Hash function to use- -> Int -- ^ Block size in bytes of the hash function- -> ByteString -- ^ Secret key+hmac :: HashAlgorithm a+ => ByteString -- ^ Secret key -> ByteString -- ^ Message to MAC -> HMAC a-hmac hashF blockSize secret msg = HMAC $ toBytes $ hashF $ B.append opad (toBytes $ hashF $ B.append ipad msg)- where opad = B.map (xor 0x5c) k'- ipad = B.map (xor 0x36) k'+hmac secret msg = doHMAC hashInit+ where doHMAC :: HashAlgorithm a => Context a -> HMAC a+ doHMAC ctxInit = HMAC $ hashF $ B.append opad (toBytes $ hashF $ 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 > fromIntegral blockSize then toBytes (hashF secret) else secret- pad = B.replicate (fromIntegral blockSize - B.length kt) 0+ k' = B.append kt pad+ kt = if B.length secret > fromIntegral blockSize then toBytes (hashF secret) else secret+ pad = B.replicate (fromIntegral blockSize - B.length kt) 0+ hashF = hashFinalize . hashUpdate ctxInit+ blockSize = hashBlockSize ctxInit++-- | compute a HMAC using a specified algorithm+hmacAlg :: HashAlgorithm a+ => a -- ^ the hash algorithm the actual value is unused.+ -> ByteString -- ^ Secret key+ -> ByteString -- ^ Message to MAC+ -> HMAC a+hmacAlg _ secret msg = hmac secret msg
Crypto/Hash/MD2.hs view
@@ -36,6 +36,7 @@ import Data.Word import Crypto.Hash.Internal (unsafeDoIO) +-- | MD2 Context newtype Ctx = Ctx ByteString {-# INLINE digestSize #-}
Crypto/Hash/MD4.hs view
@@ -36,6 +36,7 @@ import Data.Word import Crypto.Hash.Internal (unsafeDoIO) +-- | MD4 Context newtype Ctx = Ctx ByteString {-# INLINE digestSize #-}
Crypto/Hash/MD5.hs view
@@ -36,6 +36,7 @@ import Data.Word import Crypto.Hash.Internal (unsafeDoIO) +-- | MD5 Context newtype Ctx = Ctx ByteString {-# INLINE digestSize #-}
Crypto/Hash/RIPEMD160.hs view
@@ -36,6 +36,7 @@ import Data.Word import Crypto.Hash.Internal (unsafeDoIO) +-- | RIPEMD160 Context newtype Ctx = Ctx ByteString {-# INLINE digestSize #-}
Crypto/Hash/SHA1.hs view
@@ -36,6 +36,7 @@ import Data.Word import Crypto.Hash.Internal (unsafeDoIO) +-- | SHA1 Context newtype Ctx = Ctx ByteString {-# INLINE digestSize #-}
Crypto/Hash/SHA224.hs view
@@ -36,6 +36,7 @@ import Data.Word import Crypto.Hash.Internal (unsafeDoIO) +-- | SHA224 Context newtype Ctx = Ctx ByteString {-# INLINE digestSize #-}
Crypto/Hash/SHA256.hs view
@@ -36,6 +36,7 @@ import Data.Word import Crypto.Hash.Internal (unsafeDoIO) +-- | SHA256 Context newtype Ctx = Ctx ByteString {-# INLINE digestSize #-}
Crypto/Hash/SHA3.hs view
@@ -35,6 +35,7 @@ import Data.Word import Crypto.Hash.Internal (unsafeDoIO) +-- | SHA3 Context newtype Ctx = Ctx ByteString {-# INLINE sizeCtx #-}
Crypto/Hash/SHA384.hs view
@@ -36,6 +36,7 @@ import Data.Word import Crypto.Hash.Internal (unsafeDoIO) +-- | SHA384 Context newtype Ctx = Ctx ByteString {-# INLINE digestSize #-}
Crypto/Hash/SHA512.hs view
@@ -37,6 +37,7 @@ import Data.Word import Crypto.Hash.Internal (unsafeDoIO) +-- | SHA512 Context newtype Ctx = Ctx ByteString {-# INLINE digestSize #-}
Crypto/Hash/SHA512t.hs view
@@ -28,6 +28,7 @@ import qualified Crypto.Hash.SHA512 as SHA512 +-- | SHA512 Context with variable size output data Ctx = Ctx !Int !SHA512.Ctx -- | init a context
Crypto/Hash/Skein256.hs view
@@ -35,6 +35,7 @@ import Data.Word import Crypto.Hash.Internal (unsafeDoIO) +-- | Skein256 Context newtype Ctx = Ctx ByteString {-# INLINE sizeCtx #-}
Crypto/Hash/Skein512.hs view
@@ -35,6 +35,7 @@ import Data.Word import Crypto.Hash.Internal (unsafeDoIO) +-- | Skein512 Context newtype Ctx = Ctx ByteString {-# INLINE sizeCtx #-}
Crypto/Hash/Tiger.hs view
@@ -36,6 +36,7 @@ import Data.Word import Crypto.Hash.Internal (unsafeDoIO) +-- | Tiger Context newtype Ctx = Ctx ByteString {-# INLINE digestSize #-}
Crypto/Hash/Types.hs view
@@ -31,6 +31,9 @@ -- finalize : finalize the context into a digest -- class HashAlgorithm a where+ -- | Block size in bytes the hash algorithm operates on+ hashBlockSize :: Context a -> Int+ -- | Initialize a new context for this hash algorithm hashInit :: Context a
Crypto/Hash/Utils.hs view
@@ -23,6 +23,8 @@ import Crypto.Hash.Utils.Cpu import Data.Bits (testBit) +-- | Convert a bytestring to the hexadecimal equivalent+-- using 0123456789abcdef as digit toHex :: ByteString -> ByteString toHex (B.PS fp off len) = B.unsafeCreate (len*2) $ \d -> withForeignPtr fp $ \s -> start d (s `plusPtr` off)
Crypto/Hash/Whirlpool.hs view
@@ -36,6 +36,7 @@ import Data.Word import Crypto.Hash.Internal (unsafeDoIO) +-- | Whirlpool Context newtype Ctx = Ctx ByteString {-# INLINE digestSize #-}
README.md view
@@ -42,7 +42,7 @@ * finalize: finalize the context and returns a digest bytestring. all those operations are completely pure, and instead of changing the-context as usual in others language, it re-allocate a new context each time.+context as usual in others language, it re-allocates a new context each time. One Pass API ------------@@ -63,7 +63,7 @@ Both those types are parametrized with the HashAlgorithm used. The API is very similar to each single hash module, except the types are-slightly differents.+slightly different. import Crypto.Hash @@ -84,5 +84,5 @@ Performance ----------- -Cryptohash uses C implementations to provides maximum performance.+Cryptohash uses C implementations to provide maximum performance. see the cbits directory for more information
Tests/KAT.hs view
@@ -4,6 +4,7 @@ import Data.Bits import Data.Word import Data.ByteString (ByteString)+import Data.Byteable import qualified Data.ByteString as B import qualified Data.ByteString.Char8 as BC import qualified Crypto.Hash.MD2 as MD2@@ -22,7 +23,6 @@ import qualified Crypto.Hash.Skein512 as Skein512 import qualified Crypto.Hash.Whirlpool as Whirlpool import Crypto.Hash-import qualified Crypto.MAC.HMAC as HMAC import Test.Framework (Test, defaultMain, testGroup) import Test.Framework.Providers.QuickCheck2 (testProperty)@@ -239,14 +239,37 @@ , MACVector "key" v1 "\xf7\xbc\x83\xf4\x30\x53\x84\x24\xb1\x32\x98\xe6\xaa\x6f\xb1\x43\xef\x4d\x59\xa1\x49\x46\x17\x59\x97\x47\x9d\xbc\x2d\x1a\x3c\xd8" ] +sha3_key1 = "\x4a\x65\x66\x65"+sha3_data1 = "\x77\x68\x61\x74\x20\x64\x6f\x20\x79\x61\x20\x77\x61\x6e\x74\x20\x66\x6f\x72\x20\x6e\x6f\x74\x68\x69\x6e\x67\x3f"++sha3_224_MAC_Vectors =+ [ MACVector sha3_key1 sha3_data1 "\xe8\x24\xfe\xc9\x6c\x07\x4f\x22\xf9\x92\x35\xbb\x94\x2d\xa1\x98\x26\x64\xab\x69\x2c\xa8\x50\x10\x53\xcb\xd4\x14"+ ]++sha3_256_MAC_Vectors =+ [ MACVector sha3_key1 sha3_data1 "\xaa\x9a\xed\x44\x8c\x7a\xbc\x8b\x5e\x32\x6f\xfa\x6a\x01\xcd\xed\xf7\xb4\xb8\x31\x88\x14\x68\xc0\x44\xba\x8d\xd4\x56\x63\x69\xa1"+ ]++sha3_384_MAC_Vectors =+ [ MACVector sha3_key1 sha3_data1 "\x5a\xf5\xc9\xa7\x7a\x23\xa6\xa9\x3d\x80\x64\x9e\x56\x2a\xb7\x7f\x4f\x35\x52\xe3\xc5\xca\xff\xd9\x3b\xdf\x8b\x3c\xfc\x69\x20\xe3\x02\x3f\xc2\x67\x75\xd9\xdf\x1f\x3c\x94\x61\x31\x46\xad\x2c\x9d"+ ]++sha3_512_MAC_Vectors =+ [ MACVector sha3_key1 sha3_data1 "\xc2\x96\x2e\x5b\xbe\x12\x38\x00\x78\x52\xf7\x9d\x81\x4d\xbb\xec\xd4\x68\x2e\x6f\x09\x7d\x37\xa3\x63\x58\x7c\x03\xbf\xa2\xeb\x08\x59\xd8\xd9\xc7\x01\xe0\x4c\xec\xec\xfd\x3d\xd7\xbf\xd4\x38\xf2\x0b\x8b\x64\x8e\x01\xbf\x8c\x11\xd2\x68\x24\xb9\x6c\xeb\xbd\xcb"+ ]+ macTests :: [Test] macTests =- [ testGroup "hmac-md5" $ map (toMACTest MD5.hash 64) $ zip [0..] md5MACVectors- , testGroup "hmac-sha1" $ map (toMACTest SHA1.hash 64) $ zip [0..] sha1MACVectors- , testGroup "hmac-sha256" $ map (toMACTest SHA256.hash 64) $ zip [0..] sha256MACVectors+ [ testGroup "hmac-md5" $ map (toMACTest MD5) $ zip [0..] md5MACVectors+ , testGroup "hmac-sha1" $ map (toMACTest SHA1) $ zip [0..] sha1MACVectors+ , testGroup "hmac-sha256" $ map (toMACTest SHA256) $ zip [0..] sha256MACVectors+ , testGroup "hmac-sha3-224" $ map (toMACTest SHA3_224) $ zip [0..] sha3_224_MAC_Vectors+ , testGroup "hmac-sha3-256" $ map (toMACTest SHA3_256) $ zip [0..] sha3_256_MAC_Vectors+ , testGroup "hmac-sha3-384" $ map (toMACTest SHA3_384) $ zip [0..] sha3_384_MAC_Vectors+ , testGroup "hmac-sha3-512" $ map (toMACTest SHA3_512) $ zip [0..] sha3_512_MAC_Vectors ]- where toMACTest hashF blockSize (i, macVector) =- testCase (show i) (macResult macVector @=? HMAC.hmac hashF blockSize (macKey macVector) (macSecret macVector))+ where toMACTest hashAlg (i, macVector) =+ testCase (show i) (macResult macVector @=? toBytes (hmac hashAlg (macKey macVector) (macSecret macVector))) main = defaultMain [ testGroup "KATs" katTests
cbits/bitfn.h view
@@ -169,6 +169,12 @@ # include <machine/endian.h> #elif defined( BSD ) && ( BSD >= 199103 ) # include <machine/endian.h>+#elif defined( __QNXNTO__ ) && defined( __LITTLEENDIAN__ )+ # define LITTLE_ENDIAN 1234+ # define BYTE_ORDER LITTLE_ENDIAN+#elif defined( __QNXNTO__ ) && defined( __BIGENDIAN__ )+ # define BIG_ENDIAN 1234+ # define BYTE_ORDER BIG_ENDIAN #else # include <endian.h> #endif
cryptohash.cabal view
@@ -1,8 +1,8 @@ Name: cryptohash-Version: 0.10.0+Version: 0.11.0 Description: A collection of crypto hashes, with a practical incremental and one-pass, pure APIs,- with performance close to the fastest implementations available in others languages.+ with performance close to the fastest implementations available in other languages. . The implementations are made in C with a haskell FFI wrapper that hide the C implementation. .@@ -20,7 +20,7 @@ . > import qualified Crypto.Hash.SHA1 as SHA1 >- > main = putStrLn $ show $ SHA1.hash (Data.ByteString.pack [1..256])+ > main = putStrLn $ show $ SHA1.hash (Data.ByteString.pack [0..255]) . > import qualified Crypto.Hash.SHA3 as SHA3 >@@ -38,13 +38,13 @@ Build-Type: Simple Cabal-Version: >=1.8 Homepage: http://github.com/vincenthz/hs-cryptohash-data-files: README.md extra-source-files: cbits/bitfn.h cbits/md2.h cbits/md4.h cbits/md5.h cbits/ripemd.h cbits/sha1.h cbits/sha256.h cbits/sha512.h cbits/sha3.h cbits/skein.h cbits/skein256.h cbits/skein512.h cbits/tiger.h cbits/whirlpool.h+ README.md Library Build-Depends: base >= 4 && < 6, bytestring, byteable, ghc-prim@@ -95,6 +95,7 @@ Main-Is: KAT.hs Build-depends: base >= 4 && < 5 , bytestring+ , byteable , HUnit , QuickCheck >= 2 , test-framework >= 0.3.3@@ -107,6 +108,12 @@ hs-source-dirs: Bench type: exitcode-stdio-1.0 Build-depends: base >= 4, bytestring, criterion, cryptohash++Benchmark bench-hmac+ Main-Is: BenchHMAC.hs+ hs-source-dirs: Bench+ type: exitcode-stdio-1.0+ Build-depends: base >= 4, bytestring, criterion, cryptohash, byteable Benchmark bench-api Main-Is: BenchAPI.hs