{-# LANGUAGE CPP #-} {-# LANGUAGE MultiParamTypeClasses #-} {-# LANGUAGE PackageImports #-} -- | -- Module : Crypto.Hash.CryptoAPI -- License : BSD-style -- Maintainer : Vincent Hanquez -- Stability : experimental -- Portability : unknown -- -- Cryptohash API exported through crypto-api. -- -- Note: Current version (0.10) of crypto-api suffers a small performance problem. -- see . -- Hopefully, future versions will fix this. -- module Crypto.Hash.CryptoAPI ( MD2 , MD4 , MD5 , SHA1 , SHA224 , SHA256 , SHA384 , SHA512 , Skein256_256 , Skein512_512 , RIPEMD160 , Tiger , Whirlpool , Hash(..) -- * Contexts , CTXMD2, CTXMD4, CTXMD5, CTXRIPEMD160, CTXSHA1, CTXSHA224 , CTXSHA256, CTXSHA384, CTXSHA512, CTXSkein256_256, CTXSkein512_512 , CTXTiger, CTXWhirlpool ) where import qualified "cryptonite" Crypto.Hash as H import qualified Data.ByteString.Lazy as L import Control.Monad (liftM) import Data.ByteString (ByteString) import Data.Serialize (Serialize(..)) import Data.Serialize.Get (getByteString) import Data.Serialize.Put (putByteString) import Data.Tagged (Tagged(..)) import Crypto.Classes (Hash(..), hash, hash') import qualified Data.ByteArray as B (convert) -- -- need to redefine a context wrapper to not clash with the already existing -- and avoid the "function dependencies conflict between instance declaration" error. -- -- unfortunately haskell uses cpp in traditional mode to avoid problem, but traditional mode -- doesn't do proper token concatenation, so need to define the ctxname in the macro -- #define DEFINE_TYPE_AND_INSTANCES_SIMPLE(CTXNAME, MODULENAME, OUTPUTLEN, BLOCKLEN) \ DEFINE_TYPE_AND_INSTANCES(CTXNAME, MODULENAME, MODULENAME, OUTPUTLEN, BLOCKLEN) #define DEFINE_TYPE_AND_INSTANCES(CTXNAME, NAME, MODULENAME, OUTPUTLEN, BLOCKLEN) \ \ data NAME = NAME !ByteString deriving (Eq,Ord,Show); \ \ instance Serialize NAME where \ { get = liftM NAME (getByteString OUTPUTLEN) \ ; put (NAME d) = putByteString d \ }; \ \ instance Hash CTXNAME NAME where \ { outputLength = Tagged (OUTPUTLEN * 8) \ ; blockLength = Tagged (BLOCKLEN * 8) \ ; initialCtx = CTXNAME H.hashInit \ ; updateCtx (CTXNAME ctx) = CTXNAME . H.hashUpdate ctx \ ; finalize (CTXNAME ctx) bs = NAME $ B.convert $ H.hashFinalize (H.hashUpdate ctx bs) \ #define DEFINE_TYPE_AND_INSTANCES_WITHLEN(CTXNAME, NAME, ILEN, MODULENAME, OUTPUTLEN, BLOCKLEN) \ \ data NAME = NAME !ByteString deriving (Eq,Ord,Show); \ \ instance Serialize NAME where \ { get = liftM NAME (getByteString OUTPUTLEN) \ ; put (NAME d) = putByteString d \ }; \ \ instance Hash CTXNAME NAME where \ { outputLength = Tagged (OUTPUTLEN * 8) \ ; blockLength = Tagged (BLOCKLEN * 8) \ ; initialCtx = CTXNAME (H.hashInit) \ ; updateCtx (CTXNAME ctx) = CTXNAME . H.hashUpdate ctx \ ; finalize (CTXNAME ctx) bs = NAME $ B.convert $ H.hashFinalize (H.hashUpdate ctx bs) \ newtype CTXMD2 = CTXMD2 (H.Context H.MD2) newtype CTXMD4 = CTXMD4 (H.Context H.MD4) newtype CTXMD5 = CTXMD5 (H.Context H.MD5) newtype CTXSHA1 = CTXSHA1 (H.Context H.SHA1) newtype CTXSHA224 = CTXSHA224 (H.Context H.SHA224) newtype CTXSHA256 = CTXSHA256 (H.Context H.SHA256) newtype CTXSHA384 = CTXSHA384 (H.Context H.SHA384) newtype CTXSHA512 = CTXSHA512 (H.Context H.SHA512) newtype CTXRIPEMD160 = CTXRIPEMD160 (H.Context H.RIPEMD160) newtype CTXTiger = CTXTiger (H.Context H.Tiger) newtype CTXWhirlpool = CTXWhirlpool (H.Context H.Whirlpool) newtype CTXSkein256_256 = CTXSkein256_256 (H.Context H.Skein256_256) newtype CTXSkein512_512 = CTXSkein512_512 (H.Context H.Skein512_512) DEFINE_TYPE_AND_INSTANCES_SIMPLE(CTXMD2, MD2, 16, 16) ; hash = MD2 . B.convert . (H.hashlazy :: L.ByteString -> H.Digest H.MD2) ; hash' = MD2 . B.convert . (H.hashWith H.MD2) }; DEFINE_TYPE_AND_INSTANCES_SIMPLE(CTXMD4, MD4, 16, 64) ; hash = MD4 . B.convert . (H.hashlazy :: L.ByteString -> H.Digest H.MD4) ; hash' = MD4 . B.convert . (H.hashWith H.MD4) }; DEFINE_TYPE_AND_INSTANCES_SIMPLE(CTXMD5, MD5, 16, 64) ; hash = MD5 . B.convert . (H.hashlazy :: L.ByteString -> H.Digest H.MD5) ; hash' = MD5 . B.convert . (H.hashWith H.MD5) }; DEFINE_TYPE_AND_INSTANCES_SIMPLE(CTXSHA1, SHA1, 20, 64) ; hash = SHA1 . B.convert . (H.hashlazy :: L.ByteString -> H.Digest H.SHA1) ; hash' = SHA1 . B.convert . (H.hashWith H.SHA1) }; DEFINE_TYPE_AND_INSTANCES_SIMPLE(CTXSHA224, SHA224, 28, 64) ; hash = SHA224 . B.convert . (H.hashlazy :: L.ByteString -> H.Digest H.SHA224) ; hash' = SHA224 . B.convert . (H.hashWith H.SHA224) }; DEFINE_TYPE_AND_INSTANCES_SIMPLE(CTXSHA256, SHA256, 32, 64) ; hash = SHA256 . B.convert . (H.hashlazy :: L.ByteString -> H.Digest H.SHA256) ; hash' = SHA256 . B.convert . (H.hashWith H.SHA256) }; DEFINE_TYPE_AND_INSTANCES_SIMPLE(CTXSHA384, SHA384, 48, 128) ; hash = SHA384 . B.convert . (H.hashlazy :: L.ByteString -> H.Digest H.SHA384) ; hash' = SHA384 . B.convert . (H.hashWith H.SHA384) }; DEFINE_TYPE_AND_INSTANCES_SIMPLE(CTXSHA512, SHA512, 64, 128) ; hash = SHA512 . B.convert . (H.hashlazy :: L.ByteString -> H.Digest H.SHA512) ; hash' = SHA512 . B.convert . (H.hashWith H.SHA512) }; DEFINE_TYPE_AND_INSTANCES_SIMPLE(CTXRIPEMD160, RIPEMD160, 20, 64) ; hash = RIPEMD160 . B.convert . (H.hashlazy :: L.ByteString -> H.Digest H.RIPEMD160) ; hash' = RIPEMD160 . B.convert . (H.hashWith H.RIPEMD160) }; DEFINE_TYPE_AND_INSTANCES_SIMPLE(CTXTiger, Tiger, 24, 64) ; hash = Tiger . B.convert . (H.hashlazy :: L.ByteString -> H.Digest H.Tiger) ; hash' = Tiger . B.convert . (H.hashWith H.Tiger) }; DEFINE_TYPE_AND_INSTANCES_SIMPLE(CTXWhirlpool, Whirlpool, 64, 64) ; hash = Whirlpool . B.convert . (H.hashlazy :: L.ByteString -> H.Digest H.Whirlpool) ; hash' = Whirlpool . B.convert . (H.hashWith H.Whirlpool) }; DEFINE_TYPE_AND_INSTANCES_WITHLEN(CTXSkein256_256, Skein256_256, 256, Skein256, 32, 32) ; hash = Skein256_256 . B.convert . (H.hashlazy :: L.ByteString -> H.Digest H.Skein256_256) ; hash' = Skein256_256 . B.convert . (H.hashWith H.Skein256_256) }; DEFINE_TYPE_AND_INSTANCES_WITHLEN(CTXSkein512_512, Skein512_512, 512, Skein512, 64, 64) ; hash = Skein512_512 . B.convert . (H.hashlazy :: L.ByteString -> H.Digest H.Skein512_512) ; hash' = Skein512_512 . B.convert . (H.hashWith H.Skein512_512) };