packages feed

cryptohash-sha256 (empty) → 0.11.7.1

raw patch · 10 files changed

+898/−0 lines, 10 filesdep +basedep +bytestringdep +criterionsetup-changed

Dependencies added: base, bytestring, criterion, cryptohash-sha256, tasty, tasty-hunit, tasty-quickcheck

Files

+ Bench/Bench.hs view
@@ -0,0 +1,33 @@+{-# LANGUAGE BangPatterns #-}+import Criterion.Main+import qualified Data.ByteString as B+import qualified Data.ByteString.Lazy as L+import qualified Crypto.Hash.SHA256 as SHA256++hashmany (i,u,f) = f . foldl u i++allHashs =+    [ ("SHA2-256",SHA256.hash, hashmany (SHA256.init,SHA256.update,SHA256.finalize))+    ]++benchHash :: a -> (a -> B.ByteString) -> Benchmarkable+benchHash bs f = whnf f bs++withHashesFilter out f = map f $ filter (\(n,_,_) -> not (n `elem` out)) allHashs+withHashes f = map f allHashs++main = do+    let !bs32     = B.replicate 32 0+        !bs256    = B.replicate 256 0+        !bs4096   = B.replicate 4096 0+        !bs1M     = B.replicate (1*1024*1024) 0+    let !lbs64x256 = (map (const (B.replicate 64 0)) [0..3])+        !lbs64x4096 = (map (const (B.replicate 64 0)) [0..63])+    defaultMain+        [ bgroup "hash-32b" (withHashes (\(name, f,_) -> bench name $ benchHash bs32 f))+        , bgroup "hash-256b" (withHashes (\(name, f,_) -> bench name $ benchHash bs256 f))+        , bgroup "hash-4Kb" (withHashes (\(name, f,_) -> bench name $ benchHash bs4096 f))+        , bgroup "hash-1Mb" (withHashesFilter ["MD2"] (\(name, f,_) -> bench name $ benchHash bs1M f))+        , bgroup "iuf-64x256" (withHashes (\(name, _,f) -> bench name $ benchHash lbs64x256 f))+        , bgroup "iuf-64x4096" (withHashes (\(name, _,f) -> bench name $ benchHash lbs64x4096 f))+        ]
+ Bench/BenchAPI.hs view
@@ -0,0 +1,39 @@+{-# LANGUAGE BangPatterns #-}+import Criterion.Main+import qualified Data.ByteString as B+import qualified Data.ByteString.Lazy as L+import qualified Crypto.Hash.SHA256 as SHA256++sha256F = ( "SHA256"+        , SHA256.hash+        , SHA256.finalize . SHA256.update SHA256.init+        )++main = do+    let !bs32     = B.replicate 32 0+        !bs256    = B.replicate 256 0+        !bs4096   = B.replicate 4096 0+        !bs1M     = B.replicate (1*1024*1024) 0+    let !lbs64x256 = (map (const (B.replicate 64 0)) [0..3])+        !lbs64x4096 = (map (const (B.replicate 64 0)) [0..63])++    let (fname, fHash, fIncr) = sha256F+    let benchName ty z = fname ++ "." ++ ty -- ++ " " ++ show z+    defaultMain+        [ bgroup "hash-0b"+            [ bench (benchName "hash" 0) $ whnf fHash B.empty+            , bench (benchName "incr" 0) $ whnf fIncr B.empty+            ]+        , bgroup "hash-32b"+            [ bench (benchName "hash" 32) $ whnf fHash bs32+            , bench (benchName "incr" 32) $ whnf fIncr bs32+            ]+        , bgroup "hash-256b"+            [ bench (benchName "hash" 256) $ whnf fHash bs256+            , bench (benchName "incr" 256) $ whnf fIncr bs256+            ]+        , bgroup "hash-4Kb"+            [ bench (benchName "hash" 4096) $ whnf fHash bs4096+            , bench (benchName "incr" 4096) $ whnf fIncr bs4096+            ]+        ]
+ Crypto/Hash/SHA256.hs view
@@ -0,0 +1,184 @@+-- |+-- Module      : Crypto.Hash.SHA256+-- License     : BSD-style+-- Maintainer  : Herbert Valerio Riedel <hvr@gnu.org>+-- Stability   : stable+-- Portability : unknown+--+-- A module containing <https://en.wikipedia.org/wiki/SHA-2 SHA-256> bindings+--+module Crypto.Hash.SHA256+    (++    -- * Incremental API+    --+    -- | This API is based on 4 different functions, similar to the+    -- lowlevel operations of a typical hash:+    --+    --  - 'init': create a new hash context+    --  - 'update': update non-destructively a new hash context with a strict bytestring+    --  - 'updates': same as update, except that it takes a list of strict bytestring+    --  - '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-allocates a new context each time.+    --+    -- Example:+    --+    -- > import qualified Data.ByteString+    -- > import qualified Crypto.Hash.SHA256 as SHA256+    -- >+    -- > main = print digest+    -- >   where+    -- >     digest = SHA256.finalize ctx+    -- >     ctx    = foldl SHA256.update ctx0 (map Data.ByteString.pack [ [1,2,3], [4,5,6] ])+    -- >     ctx0   = SHA256.init++      Ctx(..)+    , init     -- :: Ctx+    , update   -- :: Ctx -> ByteString -> Ctx+    , updates  -- :: Ctx -> [ByteString] -> Ctx+    , finalize -- :: Ctx -> ByteString++    -- * Single Pass API+    --+    -- | This API use the incremental API under the hood to provide+    -- the common all-in-one operations to create digests out of a+    -- 'ByteString' and lazy 'L.ByteString'.+    --+    --  - 'hash': create a digest ('init' + 'update' + 'finalize') from a strict 'ByteString'+    --  - 'hashlazy': create a digest ('init' + 'update' + 'finalize') from a lazy 'L.ByteString'+    --+    -- Example:+    --+    -- > import qualified Data.ByteString+    -- > import qualified Crypto.Hash.SHA256 as SHA256+    -- >+    -- > main = print $ SHA256.hash (Data.ByteString.pack [0..255])+    --+    -- __NOTE__: The returned digest is a binary 'ByteString'. For+    -- converting to a base16/hex encoded digest the+    -- <https://hackage.haskell.org/package/base16-bytestring base16-bytestring>+    -- package is recommended.++    , hash     -- :: ByteString -> ByteString+    , hashlazy -- :: ByteString -> ByteString+    ) where++import Prelude hiding (init)+import Foreign.Ptr+import Foreign.ForeignPtr (withForeignPtr)+import Foreign.Storable+import Foreign.Marshal.Alloc+import qualified Data.ByteString.Lazy as L+import qualified Data.ByteString as B+import Data.ByteString (ByteString)+import Data.ByteString.Unsafe (unsafeUseAsCStringLen)+import Data.ByteString.Internal (create, toForeignPtr)+import Data.Word+import System.IO.Unsafe (unsafeDupablePerformIO)++-- | perform IO for hashes that do allocation and ffi.+-- unsafeDupablePerformIO is used when possible as the+-- computation is pure and the output is directly linked+-- to the input. we also do not modify anything after it has+-- been returned to the user.+unsafeDoIO :: IO a -> a+unsafeDoIO = unsafeDupablePerformIO++-- | SHA-256 Context+newtype Ctx = Ctx ByteString++{-# INLINE digestSize #-}+digestSize :: Int+digestSize = 32++{-# INLINE sizeCtx #-}+sizeCtx :: Int+sizeCtx = 192++{-# RULES "digestSize" B.length (finalize init) = digestSize #-}+{-# RULES "hash" forall b. finalize (update init b) = hash b #-}+{-# RULES "hash.list1" forall b. finalize (updates init [b]) = hash b #-}+{-# RULES "hashmany" forall b. finalize (foldl update init b) = hashlazy (L.fromChunks b) #-}+{-# RULES "hashlazy" forall b. finalize (foldl update init $ L.toChunks b) = hashlazy b #-}++{-# INLINE withByteStringPtr #-}+withByteStringPtr :: ByteString -> (Ptr Word8 -> IO a) -> IO a+withByteStringPtr b f =+    withForeignPtr fptr $ \ptr -> f (ptr `plusPtr` off)+    where (fptr, off, _) = toForeignPtr b++{-# INLINE memcopy64 #-}+memcopy64 :: Ptr Word64 -> Ptr Word64 -> IO ()+memcopy64 dst src = mapM_ peekAndPoke [0..(24-1)]+    where peekAndPoke i = peekElemOff src i >>= pokeElemOff dst i++withCtxCopy :: Ctx -> (Ptr Ctx -> IO ()) -> IO Ctx+withCtxCopy (Ctx ctxB) f = Ctx `fmap` createCtx+    where createCtx = create sizeCtx $ \dstPtr ->+                      withByteStringPtr ctxB $ \srcPtr -> do+                          memcopy64 (castPtr dstPtr) (castPtr srcPtr)+                          f (castPtr dstPtr)++withCtxThrow :: Ctx -> (Ptr Ctx -> IO a) -> IO a+withCtxThrow (Ctx ctxB) f =+    allocaBytes sizeCtx $ \dstPtr ->+    withByteStringPtr ctxB $ \srcPtr -> do+        memcopy64 (castPtr dstPtr) (castPtr srcPtr)+        f (castPtr dstPtr)++withCtxNew :: (Ptr Ctx -> IO ()) -> IO Ctx+withCtxNew f = Ctx `fmap` create sizeCtx (f . castPtr)++withCtxNewThrow :: (Ptr Ctx -> IO a) -> IO a+withCtxNewThrow f = allocaBytes sizeCtx (f . castPtr)++foreign import ccall unsafe "sha256.h hs_cryptohash_sha256_init"+    c_sha256_init :: Ptr Ctx -> IO ()++foreign import ccall unsafe "sha256.h hs_cryptohash_sha256_update"+    c_sha256_update :: Ptr Ctx -> Ptr Word8 -> Word32 -> IO ()++foreign import ccall unsafe "sha256.h hs_cryptohash_sha256_finalize"+    c_sha256_finalize :: Ptr Ctx -> Ptr Word8 -> IO ()++updateInternalIO :: Ptr Ctx -> ByteString -> IO ()+updateInternalIO ptr d =+    unsafeUseAsCStringLen d (\(cs, len) -> c_sha256_update ptr (castPtr cs) (fromIntegral len))++finalizeInternalIO :: Ptr Ctx -> IO ByteString+finalizeInternalIO ptr = create digestSize (c_sha256_finalize ptr)++{-# NOINLINE init #-}+-- | init a context+init :: Ctx+init = unsafeDoIO $ withCtxNew $ c_sha256_init++{-# NOINLINE update #-}+-- | update a context with a bytestring+update :: Ctx -> ByteString -> Ctx+update ctx d = unsafeDoIO $ withCtxCopy ctx $ \ptr -> updateInternalIO ptr d++{-# NOINLINE updates #-}+-- | updates a context with multiples bytestring+updates :: Ctx -> [ByteString] -> Ctx+updates ctx d = unsafeDoIO $ withCtxCopy ctx $ \ptr -> mapM_ (updateInternalIO ptr) d++{-# NOINLINE finalize #-}+-- | finalize the context into a digest bytestring+finalize :: Ctx -> ByteString+finalize ctx = unsafeDoIO $ withCtxThrow ctx finalizeInternalIO++{-# NOINLINE hash #-}+-- | hash a strict bytestring into a digest bytestring+hash :: ByteString -> ByteString+hash d = unsafeDoIO $ withCtxNewThrow $ \ptr -> do+    c_sha256_init ptr >> updateInternalIO ptr d >> finalizeInternalIO ptr++{-# NOINLINE hashlazy #-}+-- | hash a lazy bytestring into a digest bytestring+hashlazy :: L.ByteString -> ByteString+hashlazy l = unsafeDoIO $ withCtxNewThrow $ \ptr -> do+    c_sha256_init ptr >> mapM_ (updateInternalIO ptr) (L.toChunks l) >> finalizeInternalIO ptr
+ LICENSE view
@@ -0,0 +1,28 @@+Copyright (c) 2010-2014 Vincent Hanquez <vincent@snarc.org>+              2016      Herbert Valerio Riedel <hvr@gnu.org>++All rights reserved.++Redistribution and use in source and binary forms, with or without+modification, are permitted provided that the following conditions+are met:+1. Redistributions of source code must retain the above copyright+   notice, this list of conditions and the following disclaimer.+2. Redistributions in binary form must reproduce the above copyright+   notice, this list of conditions and the following disclaimer in the+   documentation and/or other materials provided with the distribution.+3. Neither the name of the author nor the names of his contributors+   may be used to endorse or promote products derived from this software+   without specific prior written permission.++THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE+ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS+OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)+HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT+LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY+OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF+SUCH DAMAGE.
+ Setup.hs view
@@ -0,0 +1,2 @@+import Distribution.Simple+main = defaultMain
+ Tests/KAT.hs view
@@ -0,0 +1,92 @@+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE ViewPatterns #-}+import Data.Char+import Data.Bits+import Data.Word+import Data.ByteString (ByteString)+import Data.Foldable (foldl')+import Data.Monoid (mconcat)+import qualified Data.ByteString as B+import qualified Data.ByteString.Char8 as BC+import qualified Crypto.Hash.SHA256 as SHA256++import Test.Tasty+import Test.Tasty.QuickCheck+import Test.Tasty.HUnit++v0,v1,v2 :: ByteString+v0 = ""+v1 = "The quick brown fox jumps over the lazy dog"+v2 = "The quick brown fox jumps over the lazy cog"+vectors = [ v0, v1, v2 ]++instance Arbitrary ByteString where+    arbitrary = B.pack `fmap` arbitrary++data HashFct = HashFct+    { fctHash   :: (B.ByteString -> B.ByteString)+    , fctInc    :: ([B.ByteString] -> B.ByteString) }++hashinc i u f = f . foldl u i++sha256Hash = HashFct { fctHash = SHA256.hash, fctInc = hashinc SHA256.init SHA256.update SHA256.finalize }+++results :: [ (String, HashFct, [String]) ]+results = [+    ("SHA256", sha256Hash, [+        "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",+        "d7a8fbb307d7809469ca9abcb0082e4f8d5651e46d3cdb762d02d0bf37c9e592",+        "e4c4d8f3bf76b692de791a173e05321150f7a345b46484fe427f6acc7ecc81be" ])+    ]++hexalise s = concatMap (\c -> [ hex $ c `div` 16, hex $ c `mod` 16 ]) s+        where hex i+                | i >= 0 && i <= 9   = fromIntegral (ord '0') + i+                | i >= 10 && i <= 15 = fromIntegral (ord 'a') + i - 10+                | otherwise          = 0++hexaliseB :: B.ByteString -> B.ByteString+hexaliseB = B.pack . hexalise . B.unpack++splitB :: Int -> ByteString -> [ByteString]+splitB l b =+    if B.length b > l+        then+            let (b1, b2) = B.splitAt l b in+            b1 : splitB l b2+        else+            [ b ]++showHash :: B.ByteString -> String+showHash = map (toEnum.fromEnum) . hexalise . B.unpack++runhash hash v = showHash $ (fctHash hash) $ v+runhashinc hash v = showHash $ (fctInc hash) $ v++makeTestAlg (name, hash, results) = testGroup name $ concatMap maketest (zip3 [0..] vectors results)+    where+        runtest :: ByteString -> String+        runtest v = runhash hash v++        runtestinc :: Int -> ByteString -> String+        runtestinc i v = runhashinc hash $ splitB i v++        maketest (i, v, r) =+            [ testCase (show i ++ " one-pass") (r @=? runtest v)+            , testCase (show i ++ " inc 1") (r @=? runtestinc 1 v)+            , testCase (show i ++ " inc 2") (r @=? runtestinc 2 v)+            , testCase (show i ++ " inc 3") (r @=? runtestinc 3 v)+            , testCase (show i ++ " inc 4") (r @=? runtestinc 4 v)+            , testCase (show i ++ " inc 5") (r @=? runtestinc 5 v)+            , testCase (show i ++ " inc 9") (r @=? runtestinc 9 v)+            , testCase (show i ++ " inc 16") (r @=? runtestinc 16 v)+            ]++katTests :: [TestTree]+katTests = map makeTestAlg results+++main = defaultMain $ testGroup "cryptohash"+    [ testGroup "KATs" katTests+    ]
+ cbits/bitfn.h view
@@ -0,0 +1,240 @@+/*+ * Copyright (C) 2006-2009 Vincent Hanquez <vincent@snarc.org>+ *+ * Redistribution and use in source and binary forms, with or without+ * modification, are permitted provided that the following conditions+ * are met:+ * 1. Redistributions of source code must retain the above copyright+ *    notice, this list of conditions and the following disclaimer.+ * 2. Redistributions in binary form must reproduce the above copyright+ *    notice, this list of conditions and the following disclaimer in the+ *    documentation and/or other materials provided with the distribution.+ *+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.+ */++#ifndef BITFN_H+#define BITFN_H+#include <stdint.h>++#ifndef NO_INLINE_ASM+/**********************************************************/+# if (defined(__i386__))+#  define ARCH_HAS_SWAP32+static inline uint32_t bitfn_swap32(uint32_t a)+{+	asm ("bswap %0" : "=r" (a) : "0" (a));+	return a;+}+/**********************************************************/+# elif (defined(__arm__))+#  define ARCH_HAS_SWAP32+static inline uint32_t bitfn_swap32(uint32_t a)+{+	uint32_t tmp = a;+	asm volatile ("eor %1, %0, %0, ror #16\n"+	              "bic %1, %1, #0xff0000\n"+	              "mov %0, %0, ror #8\n"+	              "eor %0, %0, %1, lsr #8\n"+	             : "=r" (a), "=r" (tmp) : "0" (a), "1" (tmp));+	return a;+}+/**********************************************************/+# elif defined(__x86_64__)+#  define ARCH_HAS_SWAP32+#  define ARCH_HAS_SWAP64+static inline uint32_t bitfn_swap32(uint32_t a)+{+	asm ("bswap %0" : "=r" (a) : "0" (a));+	return a;+}++static inline uint64_t bitfn_swap64(uint64_t a)+{+	asm ("bswap %0" : "=r" (a) : "0" (a));+	return a;+}++# endif+#endif /* NO_INLINE_ASM */+/**********************************************************/++#ifndef ARCH_HAS_ROL32+static inline uint32_t rol32(uint32_t word, uint32_t shift)+{+	return (word << shift) | (word >> (32 - shift));+}+#endif++#ifndef ARCH_HAS_ROR32+static inline uint32_t ror32(uint32_t word, uint32_t shift)+{+	return (word >> shift) | (word << (32 - shift));+}+#endif++#ifndef ARCH_HAS_ROL64+static inline uint64_t rol64(uint64_t word, uint32_t shift)+{+	return (word << shift) | (word >> (64 - shift));+}+#endif++#ifndef ARCH_HAS_ROR64+static inline uint64_t ror64(uint64_t word, uint32_t shift)+{+	return (word >> shift) | (word << (64 - shift));+}+#endif++#ifndef ARCH_HAS_SWAP32+static inline uint32_t bitfn_swap32(uint32_t a)+{+	return (a << 24) | ((a & 0xff00) << 8) | ((a >> 8) & 0xff00) | (a >> 24);+}+#endif++#ifndef ARCH_HAS_ARRAY_SWAP32+static inline void array_swap32(uint32_t *d, uint32_t *s, uint32_t nb)+{+	while (nb--)+		*d++ = bitfn_swap32(*s++);+}+#endif++#ifndef ARCH_HAS_SWAP64+static inline uint64_t bitfn_swap64(uint64_t a)+{+	return ((uint64_t) bitfn_swap32((uint32_t) (a >> 32))) |+	       (((uint64_t) bitfn_swap32((uint32_t) a)) << 32);+}+#endif++#ifndef ARCH_HAS_ARRAY_SWAP64+static inline void array_swap64(uint64_t *d, uint64_t *s, uint32_t nb)+{+	while (nb--)+		*d++ = bitfn_swap64(*s++);+}+#endif++#ifndef ARCH_HAS_MEMORY_ZERO+static inline void memory_zero(void *ptr, uint32_t len)+{+	uint32_t *ptr32 = ptr;+	uint8_t *ptr8;+	int i;++	for (i = 0; i < len / 4; i++)+		*ptr32++ = 0;+	if (len % 4) {+		ptr8 = (uint8_t *) ptr32;+		for (i = len % 4; i >= 0; i--)+			ptr8[i] = 0;+	}+}+#endif++#ifndef ARCH_HAS_ARRAY_COPY32+static inline void array_copy32(uint32_t *d, uint32_t *s, uint32_t nb)+{+	while (nb--) *d++ = *s++;+}+#endif++#ifndef ARCH_HAS_ARRAY_COPY64+static inline void array_copy64(uint64_t *d, uint64_t *s, uint32_t nb)+{+	while (nb--) *d++ = *s++;+}+#endif++#ifdef __MINGW32__+  # define LITTLE_ENDIAN 1234+  # define BYTE_ORDER    LITTLE_ENDIAN+#elif defined(__FreeBSD__) || defined(__DragonFly__) || defined(__NetBSD__)+  # include <sys/endian.h>+#elif defined(__OpenBSD__) || defined(__SVR4)+  # include <sys/types.h>+#elif defined(__APPLE__)+  # 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+#elif defined( _AIX )+  # include <sys/machine.h>+#else+  # include <endian.h>+#endif+/* big endian to cpu */+#if LITTLE_ENDIAN == BYTE_ORDER++# define be32_to_cpu(a) bitfn_swap32(a)+# define cpu_to_be32(a) bitfn_swap32(a)+# define le32_to_cpu(a) (a)+# define cpu_to_le32(a) (a)+# define be64_to_cpu(a) bitfn_swap64(a)+# define cpu_to_be64(a) bitfn_swap64(a)+# define le64_to_cpu(a) (a)+# define cpu_to_le64(a) (a)++# define cpu_to_le32_array(d, s, l) array_copy32(d, s, l)+# define le32_to_cpu_array(d, s, l) array_copy32(d, s, l)+# define cpu_to_be32_array(d, s, l) array_swap32(d, s, l)+# define be32_to_cpu_array(d, s, l) array_swap32(d, s, l)++# define cpu_to_le64_array(d, s, l) array_copy64(d, s, l)+# define le64_to_cpu_array(d, s, l) array_copy64(d, s, l)+# define cpu_to_be64_array(d, s, l) array_swap64(d, s, l)+# define be64_to_cpu_array(d, s, l) array_swap64(d, s, l)++# define ror32_be(a, s) rol32(a, s)+# define rol32_be(a, s) ror32(a, s)++# define ARCH_IS_LITTLE_ENDIAN++#elif BIG_ENDIAN == BYTE_ORDER++# define be32_to_cpu(a) (a)+# define cpu_to_be32(a) (a)+# define be64_to_cpu(a) (a)+# define cpu_to_be64(a) (a)+# define le64_to_cpu(a) bitfn_swap64(a)+# define cpu_to_le64(a) bitfn_swap64(a)+# define le32_to_cpu(a) bitfn_swap32(a)+# define cpu_to_le32(a) bitfn_swap32(a)++# define cpu_to_le32_array(d, s, l) array_swap32(d, s, l)+# define le32_to_cpu_array(d, s, l) array_swap32(d, s, l)+# define cpu_to_be32_array(d, s, l) array_copy32(d, s, l)+# define be32_to_cpu_array(d, s, l) array_copy32(d, s, l)++# define cpu_to_le64_array(d, s, l) array_swap64(d, s, l)+# define le64_to_cpu_array(d, s, l) array_swap64(d, s, l)+# define cpu_to_be64_array(d, s, l) array_copy64(d, s, l)+# define be64_to_cpu_array(d, s, l) array_copy64(d, s, l)++# define ror32_be(a, s) ror32(a, s)+# define rol32_be(a, s) rol32(a, s)++# define ARCH_IS_BIG_ENDIAN++#else+# error "endian not supported"+#endif++#endif /* !BITFN_H */
+ cbits/sha256.c view
@@ -0,0 +1,153 @@+/*+ * Copyright (C) 2006-2009 Vincent Hanquez <vincent@snarc.org>+ *               2016      Herbert Valerio Riedel <hvr@gnu.org>+ *+ * Redistribution and use in source and binary forms, with or without+ * modification, are permitted provided that the following conditions+ * are met:+ * 1. Redistributions of source code must retain the above copyright+ *    notice, this list of conditions and the following disclaimer.+ * 2. Redistributions in binary form must reproduce the above copyright+ *    notice, this list of conditions and the following disclaimer in the+ *    documentation and/or other materials provided with the distribution.+ *+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.+ */++#include <string.h>+#include "sha256.h"+#include "bitfn.h"++void+hs_cryptohash_sha256_init (struct sha256_ctx *ctx)+{+	memset(ctx, 0, sizeof(*ctx));++	ctx->h[0] = 0x6a09e667;+	ctx->h[1] = 0xbb67ae85;+	ctx->h[2] = 0x3c6ef372;+	ctx->h[3] = 0xa54ff53a;+	ctx->h[4] = 0x510e527f;+	ctx->h[5] = 0x9b05688c;+	ctx->h[6] = 0x1f83d9ab;+	ctx->h[7] = 0x5be0cd19;+}++/* 232 times the cube root of the first 64 primes 2..311 */+static const uint32_t k[] = {+	0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1,+	0x923f82a4, 0xab1c5ed5, 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,+	0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, 0xe49b69c1, 0xefbe4786,+	0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,+	0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147,+	0x06ca6351, 0x14292967, 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,+	0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, 0xa2bfe8a1, 0xa81a664b,+	0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,+	0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a,+	0x5b9cca4f, 0x682e6ff3, 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,+	0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2+};++#define e0(x)       (ror32(x, 2) ^ ror32(x,13) ^ ror32(x,22))+#define e1(x)       (ror32(x, 6) ^ ror32(x,11) ^ ror32(x,25))+#define s0(x)       (ror32(x, 7) ^ ror32(x,18) ^ (x >> 3))+#define s1(x)       (ror32(x,17) ^ ror32(x,19) ^ (x >> 10))++static void+sha256_do_chunk(struct sha256_ctx *ctx, uint32_t buf[])+{+	uint32_t a, b, c, d, e, f, g, h, t1, t2;+	int i;+	uint32_t w[64];++	cpu_to_be32_array(w, buf, 16);+	for (i = 16; i < 64; i++)+		w[i] = s1(w[i - 2]) + w[i - 7] + s0(w[i - 15]) + w[i - 16];++	a = ctx->h[0]; b = ctx->h[1]; c = ctx->h[2]; d = ctx->h[3];+	e = ctx->h[4]; f = ctx->h[5]; g = ctx->h[6]; h = ctx->h[7];++#define R(a, b, c, d, e, f, g, h, k, w)			\+	t1 = h + e1(e) + (g ^ (e & (f ^ g))) + k + w; 	\+	t2 = e0(a) + ((a & b) | (c & (a | b)));		\+	d += t1;					\+	h = t1 + t2;++	for (i = 0; i < 64; i += 8) {+		R(a, b, c, d, e, f, g, h, k[i + 0], w[i + 0]);+		R(h, a, b, c, d, e, f, g, k[i + 1], w[i + 1]);+		R(g, h, a, b, c, d, e, f, k[i + 2], w[i + 2]);+		R(f, g, h, a, b, c, d, e, k[i + 3], w[i + 3]);+		R(e, f, g, h, a, b, c, d, k[i + 4], w[i + 4]);+		R(d, e, f, g, h, a, b, c, k[i + 5], w[i + 5]);+		R(c, d, e, f, g, h, a, b, k[i + 6], w[i + 6]);+		R(b, c, d, e, f, g, h, a, k[i + 7], w[i + 7]);+	}++#undef R++	ctx->h[0] += a; ctx->h[1] += b; ctx->h[2] += c; ctx->h[3] += d;+	ctx->h[4] += e; ctx->h[5] += f; ctx->h[6] += g; ctx->h[7] += h;+}++void+hs_cryptohash_sha256_update (struct sha256_ctx *ctx, const uint8_t *data, uint32_t len)+{+	uint32_t index, to_fill;++	/* check for partial buffer */+	index = (uint32_t) (ctx->sz & 0x3f);+	to_fill = 64 - index;++	ctx->sz += len;++	/* process partial buffer if there's enough data to make a block */+	if (index && len >= to_fill) {+		memcpy(ctx->buf + index, data, to_fill);+		sha256_do_chunk(ctx, (uint32_t *) ctx->buf);+		len -= to_fill;+		data += to_fill;+		index = 0;+	}++	/* process as much 64-block as possible */+	for (; len >= 64; len -= 64, data += 64)+		sha256_do_chunk(ctx, (uint32_t *) data);++	/* append data into buf */+	if (len)+		memcpy(ctx->buf + index, data, len);+}++void+hs_cryptohash_sha256_finalize (struct sha256_ctx *ctx, uint8_t *out)+{+	static uint8_t padding[64] = { 0x80, };+	uint64_t bits;+	uint32_t i, index, padlen;+	uint32_t *p = (uint32_t *) out;++	/* cpu -> big endian */+	bits = cpu_to_be64(ctx->sz << 3);++	/* pad out to 56 */+	index = (uint32_t) (ctx->sz & 0x3f);+	padlen = (index < 56) ? (56 - index) : ((64 + 56) - index);+	hs_cryptohash_sha256_update(ctx, padding, padlen);++	/* append length */+	hs_cryptohash_sha256_update(ctx, (uint8_t *) &bits, sizeof(bits));++	/* store to digest */+	for (i = 0; i < 8; i++)+		p[i] = cpu_to_be32(ctx->h[i]);+}
+ cbits/sha256.h view
@@ -0,0 +1,45 @@+/*+ * Copyright (C) 2006-2009 Vincent Hanquez <vincent@snarc.org>+ *               2016      Herbert Valerio Riedel <hvr@gnu.org>+ *+ * Redistribution and use in source and binary forms, with or without+ * modification, are permitted provided that the following conditions+ * are met:+ * 1. Redistributions of source code must retain the above copyright+ *    notice, this list of conditions and the following disclaimer.+ * 2. Redistributions in binary form must reproduce the above copyright+ *    notice, this list of conditions and the following disclaimer in the+ *    documentation and/or other materials provided with the distribution.+ *+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.+ */++#ifndef CRYPTOHASH_SHA256_H+#define CRYPTOHASH_SHA256_H++#include <stdint.h>++struct sha256_ctx+{+	uint64_t sz;+	uint8_t  buf[128];+	uint32_t h[8];+};++#define SHA256_DIGEST_SIZE	32+#define SHA256_CTX_SIZE		sizeof(struct sha256_ctx)++void hs_cryptohash_sha256_init (struct sha256_ctx *ctx);+void hs_cryptohash_sha256_update (struct sha256_ctx *ctx, const uint8_t *data, uint32_t len);+void hs_cryptohash_sha256_finalize (struct sha256_ctx *ctx, uint8_t *out);++#endif
+ cryptohash-sha256.cabal view
@@ -0,0 +1,82 @@+name:                cryptohash-sha256+version:             0.11.7.1+description:+    A practical incremental and one-pass, pure API to the+    <https://en.wikipedia.org/wiki/SHA-2 SHA-256 hash algorithm>+    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.+    .+    NOTE: This package has been forked off @cryptohash-0.11.7@ because the @cryptohash@ has been+    deprecated and so this package continues to satisfy the need for a lightweight package+    providing the SHA256 hash algorithm without any dependencies on packages other than+    @base@ and @bytestring@.+    .+    Consequently, this package can be used as a drop-in replacement for @cryptohash@'s+    "Crypto.Hash.SHA256" module, though with a clearly smaller footprint.++license:             BSD3+license-file:        LICENSE+copyright:           Vincent Hanquez, Herbert Valerio Riedel+maintainer:          Herbert Valerio Riedel <hvr@gnu.org>+homepage:            https://github.com/hvr/cryptohash-sha256+bug-reports:         https://github.com/hvr/cryptohash-sha256/issues+synopsis:            Fast, pure and practical SHA-256 implementation+category:            Data, Cryptography+build-type:          Simple+cabal-version:       >=1.10+tested-with:         GHC == 7.4.2+                   , GHC == 7.6.3+                   , GHC == 7.8.4+                   , GHC == 7.10.3+                   , GHC == 8.0.1++extra-source-files:  cbits/bitfn.h+                     cbits/sha256.h++source-repository head+  type:     git+  location: https://github.com/hvr/cryptohash-sha256.git++library+  default-language:  Haskell2010+  build-depends:     base             >= 4.5   && < 4.10+                   , bytestring       >= 0.9.2 && < 0.11++  exposed-modules:   Crypto.Hash.SHA256+  ghc-options:       -Wall -fno-cse -O2+  cc-options:        -O3+  c-sources:         cbits/sha256.c+  include-dirs:      cbits++test-suite test-kat+  default-language:  Haskell2010+  type:              exitcode-stdio-1.0+  hs-source-dirs:    Tests+  main-is:           KAT.hs+  build-depends:     cryptohash-sha256+                   , base+                   , bytestring+                   , tasty            == 0.11.*+                   , tasty-quickcheck == 0.8.*+                   , tasty-hunit      == 0.9.*++benchmark bench-hashes+  default-language:  Haskell2010+  type:              exitcode-stdio-1.0+  main-is:           Bench.hs+  hs-source-dirs:    Bench+  build-depends:     cryptohash-sha256+                   , base+                   , bytestring+                   , criterion        == 1.1.*++benchmark bench-api+  default-language:  Haskell2010+  type:              exitcode-stdio-1.0+  main-is:           BenchAPI.hs+  hs-source-dirs:    Bench+  build-depends:     cryptohash-sha256+                   , base+                   , bytestring+                   , criterion        == 1.1.*