siphash (empty) → 1.0.0
raw patch · 6 files changed
+217/−0 lines, 6 filesdep +QuickCheckdep +basedep +bytestringsetup-changed
Dependencies added: QuickCheck, base, bytestring, cereal, siphash, test-framework, test-framework-quickcheck2
Files
- Crypto/MAC/SipHash.hs +86/−0
- LICENSE +27/−0
- README.md +31/−0
- Setup.hs +2/−0
- Tests/Tests.hs +37/−0
- siphash.cabal +34/−0
+ Crypto/MAC/SipHash.hs view
@@ -0,0 +1,86 @@+-- |+-- Module : Crypto.MAC.SipHash+-- License : BSD-style+-- Maintainer : Vincent Hanquez <vincent@snarc.org>+-- Stability : experimental+-- Portability : good+--+-- provide the SipHash algorithm.+-- reference: http://131002.net/siphash/siphash.pdf+--+module Crypto.MAC.SipHash+ ( SipKey(..)+ , SipHash(..)+ , hashWith+ , hash+ ) where++import Data.Word+import Data.Bits+import Data.List (foldl')+import Data.Serialize.Get+import Data.ByteString (ByteString)+import qualified Data.ByteString as B+import Control.Monad (foldM,replicateM)++-- | SigHash Key+data SipKey = SipKey {-# UNPACK #-} !Word64 {-# UNPACK #-} !Word64++-- | Siphash tag value+newtype SipHash = SipHash Word64+ deriving (Show,Eq)++data InternalState = InternalState {-# UNPACK #-} !Word64 {-# UNPACK #-} !Word64 {-# UNPACK #-} !Word64 {-# UNPACK #-} !Word64++-- | same as @hash, except also specifies the number of sipround iterations for compression and digest.+hashWith :: Int -> Int -> SipKey -> ByteString -> SipHash+hashWith c d key b = either error (finish d) $ runGet runHash b+ where len = B.length b+ (nb,last) = len `divMod` 8++ runHash = foldM (const . getBlock) (initSip key)[0..(nb-1)] >>= lastBlock+ getBlock st = process c st `fmap` getWord64le+ lastBlock st = do+ let lengthBlock = fromIntegral (len `mod` 256) `shiftL` 56+ z <- (fst . foldl shiftAndAdd (0,0)) `fmap` replicateM last getWord8+ return $ process c st (lengthBlock .|. z)++ shiftAndAdd :: (Word64,Int) -> Word8 -> (Word64,Int)+ shiftAndAdd (acc,pos) v = (acc .|. ((fromIntegral v) `shiftL` pos), pos+8)++-- | produce a siphash with a key and a bytestring.+hash :: SipKey -> ByteString -> SipHash+hash = hashWith 2 4++initSip (SipKey k0 k1) = InternalState (k0 `xor` 0x736f6d6570736575)+ (k1 `xor` 0x646f72616e646f6d)+ (k0 `xor` 0x6c7967656e657261)+ (k1 `xor` 0x7465646279746573)++doRound (InternalState v0 v1 v2 v3) = do+ let v0' = v0 + v1+ v2' = v2 + v3+ v1' = v1 `rotateL` 13+ v3' = v3 `rotateL` 16+ v1'' = v1' `xor` v0'+ v3'' = v3' `xor` v2'+ v0'' = v0' `rotateL` 32+ v2'' = v2' + v1''+ v0''' = v0'' + v3''+ v1''' = v1'' `rotateL` 17+ v3''' = v3'' `rotateL` 21+ v1'''' = v1''' `xor` v2''+ v3'''' = v3''' `xor` v0'''+ v2''' = v2'' `rotateL` 32+ in InternalState v0''' v1'''' v2''' v3''''++runRounds n st = foldl' (const . doRound) st [0..(n-1)]++process c istate m = newState+ where newState = postInject $ runRounds c $ preInject $ istate+ preInject (InternalState v0 v1 v2 v3) = InternalState v0 v1 v2 (v3 `xor` m)+ postInject (InternalState v0 v1 v2 v3) = InternalState (v0 `xor` m) v1 v2 v3++finish d istate = getDigest $ runRounds d $ preInject istate+ where getDigest (InternalState v0 v1 v2 v3) = SipHash (v0 `xor` v1 `xor` v2 `xor` v3)+ preInject (InternalState v0 v1 v2 v3) = InternalState v0 v1 (v2 `xor` 0xff) v3
+ LICENSE view
@@ -0,0 +1,27 @@+Copyright (c) 2012 Vincent Hanquez <vincent@snarc.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.
+ README.md view
@@ -0,0 +1,31 @@+Haskell Siphash+===============++Simple module to compute the [SipHash](http://131002.net/siphash/siphash.pdf)+algorithm.++Install+-------++ cabal install sighash++Usage+-----++sighash-2-4:++ import Crypto.MAC.SigHash (hash)+ import qualified Data.ByteString.Char8 as B+ + k0 = 0xaaaaaaaaaaaaaaaa+ k1 = 0xbbbbbbbbbbbbbbbb+ tag = hash (SigKey k0 k1) (B.pack "my text to hash")++sighash-c-d:++ import Crypto.MAC.SigHash (hash)+ import qualified Data.ByteString.Char8 as B+ + k0 = 0xaaaaaaaaaaaaaaaa+ k1 = 0xbbbbbbbbbbbbbbbb+ tag = hashWith nbCompressionRounds nbDigestRounds (SigKey k0 k1) (B.pack "my text to hash")
+ Setup.hs view
@@ -0,0 +1,2 @@+import Distribution.Simple+main = defaultMain
+ Tests/Tests.hs view
@@ -0,0 +1,37 @@+{-# LANGUAGE ViewPatterns #-}+{-# LANGUAGE OverloadedStrings #-}+module Main where++import Control.Applicative+import Control.Monad++import Test.Framework (Test, defaultMain, testGroup)+import Test.Framework.Providers.QuickCheck2 (testProperty)++import Test.QuickCheck+import Test.QuickCheck.Test+import Test.Framework.Providers.QuickCheck2 (testProperty)++import qualified Data.ByteString as B+import qualified Data.ByteString.Char8 as B+import Crypto.MAC.SipHash++assertEq expected got+ | expected == got = True+ | otherwise = error ("expected: " ++ show expected ++ " got: " ++ show got)++vectors =+ [ ( SipKey 0x0706050403020100 0x0f0e0d0c0b0a0908+ , "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e"+ , SipHash 0xa129ca6149be45e5+ )+ ]++katTests v = map (testProperty "kat" . makeTest) v+ where makeTest (key,msg,tag) = assertEq tag $ hash key msg++tests =+ [ testGroup "KAT" $ katTests vectors+ ]++main = defaultMain tests
+ siphash.cabal view
@@ -0,0 +1,34 @@+Name: siphash+Version: 1.0.0+Description:+ Haskell implementation of siphash. [http://131002.net/siphash/siphash.pdf]+License: BSD3+License-file: LICENSE+Copyright: Vincent Hanquez <vincent@snarc.org>+Author: Vincent Hanquez <vincent@snarc.org>+Maintainer: Vincent Hanquez <vincent@snarc.org>+Synopsis: siphash: a fast short input PRF+Category: Data, Cryptography+Build-Type: Simple+Cabal-Version: >=1.8+Homepage: http://github.com/vincenthz/hs-siphash+data-files: README.md++Library+ Build-Depends: base >= 4 && < 6, bytestring, cereal+ Exposed-modules: Crypto.MAC.SipHash++Test-Suite test-siphash+ type: exitcode-stdio-1.0+ hs-source-dirs: Tests+ Main-Is: Tests.hs+ Build-depends: base >= 4 && < 5+ , siphash+ , bytestring+ , QuickCheck >= 2+ , test-framework >= 0.3.3 && < 0.7+ , test-framework-quickcheck2 >= 0.2.9 && < 0.3++source-repository head+ type: git+ location: git://github.com/vincenthz/hs-siphash