hwsl2 (empty) → 0.1.0.0
raw patch · 6 files changed
+266/−0 lines, 6 filesdep +basedep +bytestringsetup-changed
Dependencies added: base, bytestring
Files
- LICENSE +22/−0
- README.md +2/−0
- Setup.hs +2/−0
- hwsl2.cabal +86/−0
- src/Data/Hash/SL2.hs +110/−0
- src/tillich-zemor.c +44/−0
+ LICENSE view
@@ -0,0 +1,22 @@+The MIT License (MIT)++Copyright (c) 2015 Sam Rijs++Permission is hereby granted, free of charge, to any person obtaining a copy+of this software and associated documentation files (the "Software"), to deal+in the Software without restriction, including without limitation the rights+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell+copies of the Software, and to permit persons to whom the Software is+furnished to do so, subject to the following conditions:++The above copyright notice and this permission notice shall be included in all+copies or substantial portions of the Software.++THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE+SOFTWARE.+
+ README.md view
@@ -0,0 +1,2 @@+coholos+=======
+ Setup.hs view
@@ -0,0 +1,2 @@+import Distribution.Simple+main = defaultMain
+ hwsl2.cabal view
@@ -0,0 +1,86 @@+-- Initial hwsl2.cabal generated by cabal init. For further documentation,+-- see http://haskell.org/cabal/users-guide/++-- The name of the package.+name: hwsl2++-- The package version. See the Haskell package versioning policy (PVP) +-- for standards guiding when and how versions should be incremented.+-- http://www.haskell.org/haskellwiki/Package_versioning_policy+-- PVP summary: +-+------- breaking API changes+-- | | +----- non-breaking API additions+-- | | | +--- code changes with no API change+version: 0.1.0.0++-- A short (one-line) description of the package.+synopsis: Hashing with SL2++-- A longer description of the package.+description:+ An algebraic hash function, inspired by the paper "Hashing with SL2" by Tillich and Zemor.+ .+ The hash function is based on matrix multiplication in the special linear group+ of degree 2, over a Galois field of order 2^127, with all computations modulo+ the polynomial x^127 + x^63 + 1.+ .+ This construction gives some nice properties, which traditional "bit-scambling"+ hash functions don't possess, including it being composable. It holds:+ .+ > hash (m1 <> m2) == hash m1 <> hash m2+ .+ All operations in this package are implemented in a very efficient manner using SSE instructions.++-- URL for the project homepage or repository.+homepage: https://github.com/srijs/hwsl2++-- The license under which the package is released.+license: MIT++-- The file containing the license text.+license-file: LICENSE++-- The package author(s).+author: Sam Rijs++-- An email address to which users can send suggestions, bug reports, and +-- patches.+maintainer: srijs@airpost.net++-- A copyright notice.+-- copyright: ++category: Data++build-type: Simple++-- Extra files to be distributed with the package, such as examples or a +-- README.+extra-source-files: README.md++-- Constraint on the version of Cabal needed to build this package.+cabal-version: >=1.10+++library+ -- Modules exported by the library.+ exposed-modules: Data.Hash.SL2+ + -- Modules included in this library but not exported.+ -- other-modules: + + -- LANGUAGE extensions used by modules in this package.+ other-extensions: ForeignFunctionInterface, EmptyDataDecls+ + -- Other library packages from which modules are imported.+ build-depends: base >=4.7 && <4.8, bytestring >=0.10 && <0.11+ + -- Directories containing source files.+ hs-source-dirs: src++ -- Options for foreign source files.+ c-sources: src/tillich-zemor.c+ cc-options: -msse2 -msse4.1 -mpclmul+ + -- Base language which the package is written in.+ default-language: Haskell2010+
+ src/Data/Hash/SL2.hs view
@@ -0,0 +1,110 @@+{-# LANGUAGE ForeignFunctionInterface, EmptyDataDecls #-}++-- |+-- Module : Data.Hash.SL2+-- License : MIT+-- Maintainer : Sam Rijs <srijs@airpost.net>+--+-- An algebraic hash function, inspired by the paper "Hashing with SL2" by+-- Tillich and Zemor.+--+-- The hash function is based on matrix multiplication in the special linear group+-- of degree 2, over a Galois field of order 2^127, with all computations modulo+-- the polynomial x^127 + x^63 + 1.+--+-- This construction gives some nice properties, which traditional "bit-scambling"+-- hash functions don't possess, including it being composable. It holds:+--+-- prop> hash (m1 <> m2) == hash m1 <> hash m2+--+-- All operations in this package are implemented in a very efficient manner using SSE instructions.+--++module Data.Hash.SL2 (Hash, hash, (<+), (+>), parse) where++import Prelude hiding (concat)++import Foreign+import Foreign.Ptr+import Foreign.C.Types+import Foreign.C.String+import Foreign.Marshal.Array+import Foreign.Marshal.Utils+import Foreign.ForeignPtr+import System.IO.Unsafe++import Data.ByteString (ByteString)+import Data.ByteString.Unsafe++import Data.Monoid+import Data.Functor++foreign import ccall "tillich-zemor.h tz_hash_eq"+ tzHashEq :: Ptr () -> Ptr () -> IO CInt++foreign import ccall "tillich-zemor.h tz_hash_unit"+ tzHashUnit :: Ptr () -> IO ()++foreign import ccall "tillich-zemor.h tz_hash_append"+ tzHashAppend :: Ptr () -> Ptr CChar -> CSize -> IO ()++foreign import ccall "tillich-zemor.h tz_hash_prepend"+ tzHashPrepend :: Ptr () -> Ptr CChar -> CSize -> IO ()++foreign import ccall "tillich-zemor.h tz_hash_concat"+ tzHashConcat :: Ptr () -> Ptr () -> Ptr () -> IO ()++foreign import ccall "tillich-zemor.h tz_hash_serialize"+ tzHashSerialize :: Ptr () -> Ptr CChar -> IO ()++foreign import ccall "tillich-zemor.h tz_hash_unserialize"+ tzHashUnserialize :: Ptr () -> Ptr CChar -> IO ()++-- | Opaque representation of a 512 bit hash.+newtype Hash = H (ForeignPtr ())++tzHashSize = 64+tzHashLen = 86++withHashPtr :: Hash -> (Ptr () -> IO a) -> IO a+withHashPtr (H fp) = withForeignPtr fp++withHashPtr2 :: Hash -> Hash -> (Ptr () -> Ptr () -> IO a) -> IO a+withHashPtr2 a b f = withHashPtr a (withHashPtr b . f)++withHashPtrNew :: (Ptr () -> IO a) -> IO (Hash, a)+withHashPtrNew f = mallocForeignPtrBytes tzHashSize >>= \fp -> (\r -> (H fp, r)) <$> withForeignPtr fp f++withHashPtrCopy :: Hash -> (Ptr () -> IO a) -> IO (Hash, a)+withHashPtrCopy h f = withHashPtr h $ \hp -> withHashPtrNew $ \hp' -> copyBytes hp' hp tzHashSize >> f hp'++instance Show Hash where+ show h = unsafePerformIO $ allocaBytes tzHashLen $ \p -> withHashPtr h (flip tzHashSerialize p) >> peekCStringLen (p, tzHashLen)++instance Eq Hash where+ a == b = toBool $ unsafePerformIO $ withHashPtr2 a b tzHashEq++instance Monoid Hash where+ mempty = fst $ unsafePerformIO $ withHashPtrNew tzHashUnit+ mappend a b = fst $ unsafePerformIO $ withHashPtrNew (withHashPtr2 a b . tzHashConcat)++-- | /O(n)/ Calculate the hash of the 'ByteString'. Alias for @('mempty' '<+')@.+hash :: ByteString -> Hash+hash = (<+) mempty++-- | /O(n)/ Append the hash of the 'ByteString' to the existing 'Hash'.+-- A significantly faster equivalent of @(flip ('<>') . 'hash')@.+(<+) :: Hash -> ByteString -> Hash+(<+) h s = fst $ unsafePerformIO $ unsafeUseAsCStringLen s $ \(s', len) ->+ withHashPtrCopy h $ \hp -> tzHashAppend hp s' $ fromIntegral len++-- | /O(n)/ Prepend the hash of the 'ByteString' to the existing 'Hash'.+-- A significantly faster equivalent of @(('<>') . 'hash')@.+(+>) :: ByteString -> Hash -> Hash+(+>) s h = fst $ unsafePerformIO $ unsafeUseAsCStringLen s $ \(s', len) ->+ withHashPtrCopy h $ \hp -> tzHashPrepend hp s' $ fromIntegral len++-- | /O(1)/ Parse the representation generated by 'show'.+parse :: String -> Maybe Hash+parse s = (\(h, r) -> h <$ r) $ unsafePerformIO $ withHashPtrNew $ \hp -> withCAStringLen s $ \(s', len) ->+ if len == tzHashLen then Just <$> tzHashUnserialize hp s' else return Nothing
+ src/tillich-zemor.c view
@@ -0,0 +1,44 @@+#include "tillich-zemor.h"+#include "sl2-inl.h"++struct tz_hash_struct {+ sl2_t sl2;+};++int tz_hash_eq(tz_hash_t a, tz_hash_t b) {+ return sl2_eq(a->sl2, b->sl2);+}++void tz_hash_copy(tz_hash_t dst, tz_hash_t src) {+ sl2_copy(dst->sl2, src->sl2);+}++void tz_hash_unit(tz_hash_t h) {+ sl2_unit(h->sl2);+}++void tz_hash_append(tz_hash_t h, unsigned char *buf, size_t n) {+ size_t i;+ for (i = 0; i < n; i++) {+ sl2_mul_bits_right(h->sl2, buf[i]);+ }+}++void tz_hash_prepend(tz_hash_t h, unsigned char *buf, size_t n) {+ size_t i;+ for (i = n; i > 0; i--) {+ sl2_mul_bits_left(h->sl2, buf[i - 1]);+ }+}++void tz_hash_concat(tz_hash_t c, tz_hash_t a, tz_hash_t b) {+ sl2_mul(c->sl2, a->sl2, b->sl2);+}++void tz_hash_serialize(tz_hash_t h, unsigned char buf[86]) {+ sl2_serialize(h->sl2, buf);+}++void tz_hash_unserialize(tz_hash_t h, unsigned char buf[86]) {+ sl2_unserialize(h->sl2, buf);+}