hashes 0.1.0.1 → 0.2.0.0
raw patch · 29 files changed
+2874/−471 lines, 29 filesdep +cryptonitedep +sydtestPVP ok
version bump matches the API change (PVP)
Dependencies added: cryptonite, sydtest
API changes (from Hackage documentation)
- Data.Hash.FNV1: fnv1_ :: Addr# -> Int -> Word -> IO Word
- Data.Hash.FNV1: fnv1a_ :: Addr# -> Int -> Word -> IO Word
- Data.Hash.Utils: hashByteArray :: (Ptr Word8 -> Int -> IO b) -> ByteArray# -> b
- Data.Hash.Utils: hashByteArrayIO :: (Ptr Word8 -> Int -> IO b) -> ByteArray# -> IO b
- Data.Hash.Utils: hashByteArrayIO_ :: (Ptr Word8 -> Int -> b -> IO b) -> ByteArray# -> b -> IO b
- Data.Hash.Utils: hashByteArray_ :: (Ptr Word8 -> Int -> b -> IO b) -> ByteArray# -> b -> b
- Data.Hash.Utils: hashByteString :: (Ptr Word8 -> Int -> IO b) -> ByteString -> b
- Data.Hash.Utils: hashByteStringIO :: (Ptr Word8 -> Int -> IO b) -> ByteString -> IO b
- Data.Hash.Utils: hashByteStringIO_ :: (Ptr Word8 -> Int -> b -> IO b) -> ByteString -> b -> IO b
- Data.Hash.Utils: hashByteString_ :: (Ptr Word8 -> Int -> b -> IO b) -> ByteString -> b -> b
- Data.Hash.Utils: hashPtr :: (Ptr Word8 -> Int -> IO b) -> Ptr Word8 -> Int -> b
- Data.Hash.Utils: hashPtr_ :: (Ptr Word8 -> Int -> b -> IO b) -> Ptr Word8 -> Int -> b -> b
- Data.Hash.Utils: hashStorable :: Storable a => (Ptr Word8 -> Int -> IO b) -> a -> b
- Data.Hash.Utils: hashStorableIO :: Storable a => (Ptr Word8 -> Int -> IO b) -> a -> IO b
- Data.Hash.Utils: hashStorableIO_ :: Storable a => (Ptr Word8 -> Int -> b -> IO b) -> a -> b -> IO b
- Data.Hash.Utils: hashStorable_ :: Storable a => (Ptr Word8 -> Int -> b -> IO b) -> a -> b -> b
+ Data.Hash.Blake2: Blake2b512 :: ShortByteString -> Blake2b512
+ Data.Hash.Blake2: Blake2s256 :: ShortByteString -> Blake2s256
+ Data.Hash.Blake2: newtype Blake2b512
+ Data.Hash.Blake2: newtype Blake2s256
+ Data.Hash.Class.Mutable: class IncrementalHash a => Hash a
+ Data.Hash.Class.Mutable: class IncrementalHash a where {
+ Data.Hash.Class.Mutable: finalize :: IncrementalHash a => Context a -> IO a
+ Data.Hash.Class.Mutable: hashByteArray :: forall a. Hash a => ByteArray# -> IO a
+ Data.Hash.Class.Mutable: hashByteString :: forall a. Hash a => ByteString -> a
+ Data.Hash.Class.Mutable: hashByteStringLazy :: forall a. Hash a => ByteString -> a
+ Data.Hash.Class.Mutable: hashPtr :: forall a. Hash a => Ptr Word8 -> Int -> IO a
+ Data.Hash.Class.Mutable: hashShortByteString :: forall a. Hash a => ShortByteString -> IO a
+ Data.Hash.Class.Mutable: hashStorable :: forall a b. Hash a => Storable b => b -> IO a
+ Data.Hash.Class.Mutable: initialize :: Hash a => IO (Context a)
+ Data.Hash.Class.Mutable: type family Context a :: Type;
+ Data.Hash.Class.Mutable: update :: IncrementalHash a => Context a -> Ptr Word8 -> Int -> IO ()
+ Data.Hash.Class.Mutable: updateByteArray :: forall a. IncrementalHash a => Context a -> ByteArray# -> IO ()
+ Data.Hash.Class.Mutable: updateByteString :: forall a. IncrementalHash a => Context a -> ByteString -> IO ()
+ Data.Hash.Class.Mutable: updateByteStringLazy :: forall a. IncrementalHash a => Context a -> ByteString -> IO ()
+ Data.Hash.Class.Mutable: updateShortByteString :: forall a. IncrementalHash a => Context a -> ShortByteString -> IO ()
+ Data.Hash.Class.Mutable: updateStorable :: forall a b. IncrementalHash a => Storable b => Context a -> b -> IO ()
+ Data.Hash.Class.Mutable: }
+ Data.Hash.Class.Mutable.Internal: class IncrementalHash a where {
+ Data.Hash.Class.Mutable.Internal: finalize :: IncrementalHash a => Context a -> IO a
+ Data.Hash.Class.Mutable.Internal: type family Context a :: Type;
+ Data.Hash.Class.Mutable.Internal: update :: IncrementalHash a => Context a -> Ptr Word8 -> Int -> IO ()
+ Data.Hash.Class.Mutable.Internal: updateByteArray :: forall a. IncrementalHash a => Context a -> ByteArray# -> IO ()
+ Data.Hash.Class.Mutable.Internal: updateByteString :: forall a. IncrementalHash a => Context a -> ByteString -> IO ()
+ Data.Hash.Class.Mutable.Internal: updateByteStringLazy :: forall a. IncrementalHash a => Context a -> ByteString -> IO ()
+ Data.Hash.Class.Mutable.Internal: updateShortByteString :: forall a. IncrementalHash a => Context a -> ShortByteString -> IO ()
+ Data.Hash.Class.Mutable.Internal: updateStorable :: forall a b. IncrementalHash a => Storable b => Context a -> b -> IO ()
+ Data.Hash.Class.Mutable.Internal: }
+ Data.Hash.Class.Mutable.Salted: class IncrementalHash a => Hash a where {
+ Data.Hash.Class.Mutable.Salted: hashByteArray :: forall a. Hash a => Salt a -> ByteArray# -> IO a
+ Data.Hash.Class.Mutable.Salted: hashByteString :: forall a. Hash a => Salt a -> ByteString -> a
+ Data.Hash.Class.Mutable.Salted: hashByteStringLazy :: forall a. Hash a => Salt a -> ByteString -> a
+ Data.Hash.Class.Mutable.Salted: hashPtr :: forall a. Hash a => Salt a -> Ptr Word8 -> Int -> IO a
+ Data.Hash.Class.Mutable.Salted: hashShortByteString :: forall a. Hash a => Salt a -> ShortByteString -> IO a
+ Data.Hash.Class.Mutable.Salted: hashStorable :: forall a b. Hash a => Storable b => Salt a -> b -> IO a
+ Data.Hash.Class.Mutable.Salted: initialize :: Hash a => Salt a -> IO (Context a)
+ Data.Hash.Class.Mutable.Salted: type family Salt a :: Type;
+ Data.Hash.Class.Mutable.Salted: updateByteArray :: forall a. IncrementalHash a => Context a -> ByteArray# -> IO ()
+ Data.Hash.Class.Mutable.Salted: updateByteString :: forall a. IncrementalHash a => Context a -> ByteString -> IO ()
+ Data.Hash.Class.Mutable.Salted: updateByteStringLazy :: forall a. IncrementalHash a => Context a -> ByteString -> IO ()
+ Data.Hash.Class.Mutable.Salted: updateShortByteString :: forall a. IncrementalHash a => Context a -> ShortByteString -> IO ()
+ Data.Hash.Class.Mutable.Salted: updateStorable :: forall a b. IncrementalHash a => Storable b => Context a -> b -> IO ()
+ Data.Hash.Class.Mutable.Salted: }
+ Data.Hash.Class.Pure: class IncrementalHash a => Hash a
+ Data.Hash.Class.Pure: class IncrementalHash a where {
+ Data.Hash.Class.Pure: finalize :: IncrementalHash a => Context a -> a
+ Data.Hash.Class.Pure: hashByteArray :: forall a. Hash a => ByteArray# -> a
+ Data.Hash.Class.Pure: hashByteString :: forall a. Hash a => ByteString -> a
+ Data.Hash.Class.Pure: hashByteStringLazy :: forall a. Hash a => ByteString -> a
+ Data.Hash.Class.Pure: hashPtr :: forall a. Hash a => Ptr Word8 -> Int -> IO a
+ Data.Hash.Class.Pure: hashShortByteString :: forall a. Hash a => ShortByteString -> a
+ Data.Hash.Class.Pure: hashStorable :: forall a b. Hash a => Storable b => b -> a
+ Data.Hash.Class.Pure: initialize :: Hash a => Context a
+ Data.Hash.Class.Pure: initializeWithSalt :: forall a s. Hash a => Storable s => s -> Context a
+ Data.Hash.Class.Pure: type family Context a :: Type;
+ Data.Hash.Class.Pure: update :: IncrementalHash a => Context a -> Ptr Word8 -> Int -> IO (Context a)
+ Data.Hash.Class.Pure: updateByteArray :: forall a. IncrementalHash a => Context a -> ByteArray# -> Context a
+ Data.Hash.Class.Pure: updateByteString :: forall a. IncrementalHash a => Context a -> ByteString -> Context a
+ Data.Hash.Class.Pure: updateByteStringLazy :: forall a. IncrementalHash a => Context a -> ByteString -> Context a
+ Data.Hash.Class.Pure: updateShortByteString :: forall a. IncrementalHash a => Context a -> ShortByteString -> Context a
+ Data.Hash.Class.Pure: updateStorable :: forall a b. IncrementalHash a => Storable b => Context a -> b -> Context a
+ Data.Hash.Class.Pure: }
+ Data.Hash.Class.Pure.Internal: class IncrementalHash a where {
+ Data.Hash.Class.Pure.Internal: finalize :: IncrementalHash a => Context a -> a
+ Data.Hash.Class.Pure.Internal: type family Context a :: Type;
+ Data.Hash.Class.Pure.Internal: update :: IncrementalHash a => Context a -> Ptr Word8 -> Int -> IO (Context a)
+ Data.Hash.Class.Pure.Internal: updateByteArray :: forall a. IncrementalHash a => Context a -> ByteArray# -> Context a
+ Data.Hash.Class.Pure.Internal: updateByteString :: forall a. IncrementalHash a => Context a -> ByteString -> Context a
+ Data.Hash.Class.Pure.Internal: updateByteStringLazy :: forall a. IncrementalHash a => Context a -> ByteString -> Context a
+ Data.Hash.Class.Pure.Internal: updateShortByteString :: forall a. IncrementalHash a => Context a -> ShortByteString -> Context a
+ Data.Hash.Class.Pure.Internal: updateStorable :: forall a b. IncrementalHash a => Storable b => Context a -> b -> Context a
+ Data.Hash.Class.Pure.Internal: }
+ Data.Hash.Class.Pure.Salted: class IncrementalHash a => Hash a where {
+ Data.Hash.Class.Pure.Salted: class IncrementalHash a where {
+ Data.Hash.Class.Pure.Salted: finalize :: IncrementalHash a => Context a -> a
+ Data.Hash.Class.Pure.Salted: hashByteArray :: forall a. Hash a => Salt a -> ByteArray# -> a
+ Data.Hash.Class.Pure.Salted: hashByteString :: forall a. Hash a => Salt a -> ByteString -> a
+ Data.Hash.Class.Pure.Salted: hashByteStringLazy :: forall a. Hash a => Salt a -> ByteString -> a
+ Data.Hash.Class.Pure.Salted: hashPtr :: forall a. Hash a => Salt a -> Ptr Word8 -> Int -> IO a
+ Data.Hash.Class.Pure.Salted: hashShortByteString :: forall a. Hash a => Salt a -> ShortByteString -> a
+ Data.Hash.Class.Pure.Salted: hashStorable :: forall a b. Hash a => Storable b => Salt a -> b -> a
+ Data.Hash.Class.Pure.Salted: initialize :: Hash a => Salt a -> Context a
+ Data.Hash.Class.Pure.Salted: type family Context a :: Type;
+ Data.Hash.Class.Pure.Salted: update :: IncrementalHash a => Context a -> Ptr Word8 -> Int -> IO (Context a)
+ Data.Hash.Class.Pure.Salted: updateByteArray :: forall a. IncrementalHash a => Context a -> ByteArray# -> Context a
+ Data.Hash.Class.Pure.Salted: updateByteString :: forall a. IncrementalHash a => Context a -> ByteString -> Context a
+ Data.Hash.Class.Pure.Salted: updateByteStringLazy :: forall a. IncrementalHash a => Context a -> ByteString -> Context a
+ Data.Hash.Class.Pure.Salted: updateShortByteString :: forall a. IncrementalHash a => Context a -> ShortByteString -> Context a
+ Data.Hash.Class.Pure.Salted: updateStorable :: forall a b. IncrementalHash a => Storable b => Context a -> b -> Context a
+ Data.Hash.Class.Pure.Salted: }
+ Data.Hash.FNV1: Fnv132Hash :: Word32 -> Fnv132Hash
+ Data.Hash.FNV1: Fnv164Hash :: Word64 -> Fnv164Hash
+ Data.Hash.FNV1: Fnv1Hash :: Word -> Fnv1Hash
+ Data.Hash.FNV1: Fnv1a32Hash :: Word32 -> Fnv1a32Hash
+ Data.Hash.FNV1: Fnv1a64Hash :: Word64 -> Fnv1a64Hash
+ Data.Hash.FNV1: Fnv1aHash :: Word -> Fnv1aHash
+ Data.Hash.FNV1: data Fnv132Context
+ Data.Hash.FNV1: data Fnv164Context
+ Data.Hash.FNV1: data Fnv1Context
+ Data.Hash.FNV1: data Fnv1a32Context
+ Data.Hash.FNV1: data Fnv1a64Context
+ Data.Hash.FNV1: data Fnv1aContext
+ Data.Hash.FNV1: fnv132 :: Ptr Word8 -> Int -> IO Fnv132Hash
+ Data.Hash.FNV1: fnv132Finalize :: Fnv132Context -> Fnv132Hash
+ Data.Hash.FNV1: fnv132Initialize :: Fnv132Context
+ Data.Hash.FNV1: fnv132Update :: Fnv132Context -> Ptr Word8 -> Int -> IO Fnv132Context
+ Data.Hash.FNV1: fnv164 :: Ptr Word8 -> Int -> IO Fnv164Hash
+ Data.Hash.FNV1: fnv164Finalize :: Fnv164Context -> Fnv164Hash
+ Data.Hash.FNV1: fnv164Initialize :: Fnv164Context
+ Data.Hash.FNV1: fnv164Update :: Fnv164Context -> Ptr Word8 -> Int -> IO Fnv164Context
+ Data.Hash.FNV1: fnv1Finalize :: Fnv1Context -> Fnv1Hash
+ Data.Hash.FNV1: fnv1Initialize :: Fnv1Context
+ Data.Hash.FNV1: fnv1Update :: Fnv1Context -> Ptr Word8 -> Int -> IO Fnv1Context
+ Data.Hash.FNV1: fnv1_host :: Ptr Word8 -> Int -> IO Word
+ Data.Hash.FNV1: fnv1_host_ :: Ptr Word8 -> Int -> Word -> IO Word
+ Data.Hash.FNV1: fnv1a32 :: Ptr Word8 -> Int -> IO Fnv1a32Hash
+ Data.Hash.FNV1: fnv1a32Finalize :: Fnv1a32Context -> Fnv1a32Hash
+ Data.Hash.FNV1: fnv1a32Initialize :: Fnv1a32Context
+ Data.Hash.FNV1: fnv1a32Update :: Fnv1a32Context -> Ptr Word8 -> Int -> IO Fnv1a32Context
+ Data.Hash.FNV1: fnv1a64 :: Ptr Word8 -> Int -> IO Fnv1a64Hash
+ Data.Hash.FNV1: fnv1a64Finalize :: Fnv1a64Context -> Fnv1a64Hash
+ Data.Hash.FNV1: fnv1a64Initialize :: Fnv1a64Context
+ Data.Hash.FNV1: fnv1a64Update :: Fnv1a64Context -> Ptr Word8 -> Int -> IO Fnv1a64Context
+ Data.Hash.FNV1: fnv1aFinalize :: Fnv1aContext -> Fnv1aHash
+ Data.Hash.FNV1: fnv1aInitialize :: Fnv1aContext
+ Data.Hash.FNV1: fnv1aUpdate :: Fnv1aContext -> Ptr Word8 -> Int -> IO Fnv1aContext
+ Data.Hash.FNV1: fnv1a_host :: Ptr Word8 -> Int -> IO Word
+ Data.Hash.FNV1: fnv1a_host_ :: Ptr Word8 -> Int -> Word -> IO Word
+ Data.Hash.FNV1: instance Data.Hash.Class.Pure.Hash Data.Hash.FNV1.Fnv132Hash
+ Data.Hash.FNV1: instance Data.Hash.Class.Pure.Hash Data.Hash.FNV1.Fnv164Hash
+ Data.Hash.FNV1: instance Data.Hash.Class.Pure.Hash Data.Hash.FNV1.Fnv1Hash
+ Data.Hash.FNV1: instance Data.Hash.Class.Pure.Hash Data.Hash.FNV1.Fnv1a32Hash
+ Data.Hash.FNV1: instance Data.Hash.Class.Pure.Hash Data.Hash.FNV1.Fnv1a64Hash
+ Data.Hash.FNV1: instance Data.Hash.Class.Pure.Hash Data.Hash.FNV1.Fnv1aHash
+ Data.Hash.FNV1: instance Data.Hash.Class.Pure.Internal.IncrementalHash Data.Hash.FNV1.Fnv132Hash
+ Data.Hash.FNV1: instance Data.Hash.Class.Pure.Internal.IncrementalHash Data.Hash.FNV1.Fnv164Hash
+ Data.Hash.FNV1: instance Data.Hash.Class.Pure.Internal.IncrementalHash Data.Hash.FNV1.Fnv1Hash
+ Data.Hash.FNV1: instance Data.Hash.Class.Pure.Internal.IncrementalHash Data.Hash.FNV1.Fnv1a32Hash
+ Data.Hash.FNV1: instance Data.Hash.Class.Pure.Internal.IncrementalHash Data.Hash.FNV1.Fnv1a64Hash
+ Data.Hash.FNV1: instance Data.Hash.Class.Pure.Internal.IncrementalHash Data.Hash.FNV1.Fnv1aHash
+ Data.Hash.FNV1: instance GHC.Classes.Eq Data.Hash.FNV1.Fnv132Hash
+ Data.Hash.FNV1: instance GHC.Classes.Eq Data.Hash.FNV1.Fnv164Hash
+ Data.Hash.FNV1: instance GHC.Classes.Eq Data.Hash.FNV1.Fnv1Hash
+ Data.Hash.FNV1: instance GHC.Classes.Eq Data.Hash.FNV1.Fnv1a32Hash
+ Data.Hash.FNV1: instance GHC.Classes.Eq Data.Hash.FNV1.Fnv1a64Hash
+ Data.Hash.FNV1: instance GHC.Classes.Eq Data.Hash.FNV1.Fnv1aHash
+ Data.Hash.FNV1: instance GHC.Classes.Ord Data.Hash.FNV1.Fnv132Hash
+ Data.Hash.FNV1: instance GHC.Classes.Ord Data.Hash.FNV1.Fnv164Hash
+ Data.Hash.FNV1: instance GHC.Classes.Ord Data.Hash.FNV1.Fnv1Hash
+ Data.Hash.FNV1: instance GHC.Classes.Ord Data.Hash.FNV1.Fnv1a32Hash
+ Data.Hash.FNV1: instance GHC.Classes.Ord Data.Hash.FNV1.Fnv1a64Hash
+ Data.Hash.FNV1: instance GHC.Classes.Ord Data.Hash.FNV1.Fnv1aHash
+ Data.Hash.FNV1: instance GHC.Show.Show Data.Hash.FNV1.Fnv132Hash
+ Data.Hash.FNV1: instance GHC.Show.Show Data.Hash.FNV1.Fnv164Hash
+ Data.Hash.FNV1: instance GHC.Show.Show Data.Hash.FNV1.Fnv1Hash
+ Data.Hash.FNV1: instance GHC.Show.Show Data.Hash.FNV1.Fnv1a32Hash
+ Data.Hash.FNV1: instance GHC.Show.Show Data.Hash.FNV1.Fnv1a64Hash
+ Data.Hash.FNV1: instance GHC.Show.Show Data.Hash.FNV1.Fnv1aHash
+ Data.Hash.FNV1: newtype Fnv132Hash
+ Data.Hash.FNV1: newtype Fnv164Hash
+ Data.Hash.FNV1: newtype Fnv1Hash
+ Data.Hash.FNV1: newtype Fnv1a32Hash
+ Data.Hash.FNV1: newtype Fnv1a64Hash
+ Data.Hash.FNV1: newtype Fnv1aHash
+ Data.Hash.FNV1.Salted: Fnv132Hash :: Word32 -> Fnv132Hash
+ Data.Hash.FNV1.Salted: Fnv164Hash :: Word64 -> Fnv164Hash
+ Data.Hash.FNV1.Salted: Fnv1Hash :: Word -> Fnv1Hash
+ Data.Hash.FNV1.Salted: Fnv1a32Hash :: Word32 -> Fnv1a32Hash
+ Data.Hash.FNV1.Salted: Fnv1a64Hash :: Word64 -> Fnv1a64Hash
+ Data.Hash.FNV1.Salted: Fnv1aHash :: Word -> Fnv1aHash
+ Data.Hash.FNV1.Salted: data Fnv132Context
+ Data.Hash.FNV1.Salted: data Fnv164Context
+ Data.Hash.FNV1.Salted: data Fnv1Context
+ Data.Hash.FNV1.Salted: data Fnv1a32Context
+ Data.Hash.FNV1.Salted: data Fnv1a64Context
+ Data.Hash.FNV1.Salted: data Fnv1aContext
+ Data.Hash.FNV1.Salted: instance Data.Hash.Class.Pure.Salted.Hash Data.Hash.FNV1.Fnv132Hash
+ Data.Hash.FNV1.Salted: instance Data.Hash.Class.Pure.Salted.Hash Data.Hash.FNV1.Fnv164Hash
+ Data.Hash.FNV1.Salted: instance Data.Hash.Class.Pure.Salted.Hash Data.Hash.FNV1.Fnv1Hash
+ Data.Hash.FNV1.Salted: instance Data.Hash.Class.Pure.Salted.Hash Data.Hash.FNV1.Fnv1a32Hash
+ Data.Hash.FNV1.Salted: instance Data.Hash.Class.Pure.Salted.Hash Data.Hash.FNV1.Fnv1a64Hash
+ Data.Hash.FNV1.Salted: instance Data.Hash.Class.Pure.Salted.Hash Data.Hash.FNV1.Fnv1aHash
+ Data.Hash.FNV1.Salted: newtype Fnv132Hash
+ Data.Hash.FNV1.Salted: newtype Fnv164Hash
+ Data.Hash.FNV1.Salted: newtype Fnv1Hash
+ Data.Hash.FNV1.Salted: newtype Fnv1a32Hash
+ Data.Hash.FNV1.Salted: newtype Fnv1a64Hash
+ Data.Hash.FNV1.Salted: newtype Fnv1aHash
+ Data.Hash.Internal.OpenSSL: Algorithm :: Ptr Void -> Algorithm
+ Data.Hash.Internal.OpenSSL: Blake2b512 :: ShortByteString -> Blake2b512
+ Data.Hash.Internal.OpenSSL: Blake2s256 :: ShortByteString -> Blake2s256
+ Data.Hash.Internal.OpenSSL: Ctx :: ForeignPtr Void -> Ctx a
+ Data.Hash.Internal.OpenSSL: Digest :: ShortByteString -> Digest a
+ Data.Hash.Internal.OpenSSL: Keccak256 :: ShortByteString -> Keccak256
+ Data.Hash.Internal.OpenSSL: OpenSslException :: String -> OpenSslException
+ Data.Hash.Internal.OpenSSL: Sha2_224 :: ShortByteString -> Sha2_224
+ Data.Hash.Internal.OpenSSL: Sha2_256 :: ShortByteString -> Sha2_256
+ Data.Hash.Internal.OpenSSL: Sha2_384 :: ShortByteString -> Sha2_384
+ Data.Hash.Internal.OpenSSL: Sha2_512 :: ShortByteString -> Sha2_512
+ Data.Hash.Internal.OpenSSL: Sha2_512_224 :: ShortByteString -> Sha2_512_224
+ Data.Hash.Internal.OpenSSL: Sha2_512_256 :: ShortByteString -> Sha2_512_256
+ Data.Hash.Internal.OpenSSL: Sha3_224 :: ShortByteString -> Sha3_224
+ Data.Hash.Internal.OpenSSL: Sha3_256 :: ShortByteString -> Sha3_256
+ Data.Hash.Internal.OpenSSL: Sha3_384 :: ShortByteString -> Sha3_384
+ Data.Hash.Internal.OpenSSL: Sha3_512 :: ShortByteString -> Sha3_512
+ Data.Hash.Internal.OpenSSL: Shake128 :: ShortByteString -> Shake128
+ Data.Hash.Internal.OpenSSL: Shake256 :: ShortByteString -> Shake256
+ Data.Hash.Internal.OpenSSL: algorithm :: OpenSslDigest a => Algorithm
+ Data.Hash.Internal.OpenSSL: class OpenSslDigest a
+ Data.Hash.Internal.OpenSSL: finalCtx :: Ctx a -> IO (Digest a)
+ Data.Hash.Internal.OpenSSL: initCtx :: Algorithm -> IO (Ctx a)
+ Data.Hash.Internal.OpenSSL: instance Data.Hash.Class.Mutable.Hash Data.Hash.Internal.OpenSSL.Blake2b512
+ Data.Hash.Internal.OpenSSL: instance Data.Hash.Class.Mutable.Hash Data.Hash.Internal.OpenSSL.Blake2s256
+ Data.Hash.Internal.OpenSSL: instance Data.Hash.Class.Mutable.Hash Data.Hash.Internal.OpenSSL.Keccak256
+ Data.Hash.Internal.OpenSSL: instance Data.Hash.Class.Mutable.Hash Data.Hash.Internal.OpenSSL.Sha2_224
+ Data.Hash.Internal.OpenSSL: instance Data.Hash.Class.Mutable.Hash Data.Hash.Internal.OpenSSL.Sha2_256
+ Data.Hash.Internal.OpenSSL: instance Data.Hash.Class.Mutable.Hash Data.Hash.Internal.OpenSSL.Sha2_384
+ Data.Hash.Internal.OpenSSL: instance Data.Hash.Class.Mutable.Hash Data.Hash.Internal.OpenSSL.Sha2_512
+ Data.Hash.Internal.OpenSSL: instance Data.Hash.Class.Mutable.Hash Data.Hash.Internal.OpenSSL.Sha2_512_224
+ Data.Hash.Internal.OpenSSL: instance Data.Hash.Class.Mutable.Hash Data.Hash.Internal.OpenSSL.Sha2_512_256
+ Data.Hash.Internal.OpenSSL: instance Data.Hash.Class.Mutable.Hash Data.Hash.Internal.OpenSSL.Sha3_224
+ Data.Hash.Internal.OpenSSL: instance Data.Hash.Class.Mutable.Hash Data.Hash.Internal.OpenSSL.Sha3_256
+ Data.Hash.Internal.OpenSSL: instance Data.Hash.Class.Mutable.Hash Data.Hash.Internal.OpenSSL.Sha3_384
+ Data.Hash.Internal.OpenSSL: instance Data.Hash.Class.Mutable.Hash Data.Hash.Internal.OpenSSL.Sha3_512
+ Data.Hash.Internal.OpenSSL: instance Data.Hash.Class.Mutable.Hash Data.Hash.Internal.OpenSSL.Shake128
+ Data.Hash.Internal.OpenSSL: instance Data.Hash.Class.Mutable.Hash Data.Hash.Internal.OpenSSL.Shake256
+ Data.Hash.Internal.OpenSSL: instance Data.Hash.Class.Mutable.Internal.IncrementalHash Data.Hash.Internal.OpenSSL.Blake2b512
+ Data.Hash.Internal.OpenSSL: instance Data.Hash.Class.Mutable.Internal.IncrementalHash Data.Hash.Internal.OpenSSL.Blake2s256
+ Data.Hash.Internal.OpenSSL: instance Data.Hash.Class.Mutable.Internal.IncrementalHash Data.Hash.Internal.OpenSSL.Keccak256
+ Data.Hash.Internal.OpenSSL: instance Data.Hash.Class.Mutable.Internal.IncrementalHash Data.Hash.Internal.OpenSSL.Sha2_224
+ Data.Hash.Internal.OpenSSL: instance Data.Hash.Class.Mutable.Internal.IncrementalHash Data.Hash.Internal.OpenSSL.Sha2_256
+ Data.Hash.Internal.OpenSSL: instance Data.Hash.Class.Mutable.Internal.IncrementalHash Data.Hash.Internal.OpenSSL.Sha2_384
+ Data.Hash.Internal.OpenSSL: instance Data.Hash.Class.Mutable.Internal.IncrementalHash Data.Hash.Internal.OpenSSL.Sha2_512
+ Data.Hash.Internal.OpenSSL: instance Data.Hash.Class.Mutable.Internal.IncrementalHash Data.Hash.Internal.OpenSSL.Sha2_512_224
+ Data.Hash.Internal.OpenSSL: instance Data.Hash.Class.Mutable.Internal.IncrementalHash Data.Hash.Internal.OpenSSL.Sha2_512_256
+ Data.Hash.Internal.OpenSSL: instance Data.Hash.Class.Mutable.Internal.IncrementalHash Data.Hash.Internal.OpenSSL.Sha3_224
+ Data.Hash.Internal.OpenSSL: instance Data.Hash.Class.Mutable.Internal.IncrementalHash Data.Hash.Internal.OpenSSL.Sha3_256
+ Data.Hash.Internal.OpenSSL: instance Data.Hash.Class.Mutable.Internal.IncrementalHash Data.Hash.Internal.OpenSSL.Sha3_384
+ Data.Hash.Internal.OpenSSL: instance Data.Hash.Class.Mutable.Internal.IncrementalHash Data.Hash.Internal.OpenSSL.Sha3_512
+ Data.Hash.Internal.OpenSSL: instance Data.Hash.Class.Mutable.Internal.IncrementalHash Data.Hash.Internal.OpenSSL.Shake128
+ Data.Hash.Internal.OpenSSL: instance Data.Hash.Class.Mutable.Internal.IncrementalHash Data.Hash.Internal.OpenSSL.Shake256
+ Data.Hash.Internal.OpenSSL: instance Data.Hash.Internal.OpenSSL.OpenSslDigest Data.Hash.Internal.OpenSSL.Blake2b512
+ Data.Hash.Internal.OpenSSL: instance Data.Hash.Internal.OpenSSL.OpenSslDigest Data.Hash.Internal.OpenSSL.Blake2s256
+ Data.Hash.Internal.OpenSSL: instance Data.Hash.Internal.OpenSSL.OpenSslDigest Data.Hash.Internal.OpenSSL.Sha2_224
+ Data.Hash.Internal.OpenSSL: instance Data.Hash.Internal.OpenSSL.OpenSslDigest Data.Hash.Internal.OpenSSL.Sha2_256
+ Data.Hash.Internal.OpenSSL: instance Data.Hash.Internal.OpenSSL.OpenSslDigest Data.Hash.Internal.OpenSSL.Sha2_384
+ Data.Hash.Internal.OpenSSL: instance Data.Hash.Internal.OpenSSL.OpenSslDigest Data.Hash.Internal.OpenSSL.Sha2_512
+ Data.Hash.Internal.OpenSSL: instance Data.Hash.Internal.OpenSSL.OpenSslDigest Data.Hash.Internal.OpenSSL.Sha2_512_224
+ Data.Hash.Internal.OpenSSL: instance Data.Hash.Internal.OpenSSL.OpenSslDigest Data.Hash.Internal.OpenSSL.Sha2_512_256
+ Data.Hash.Internal.OpenSSL: instance Data.Hash.Internal.OpenSSL.OpenSslDigest Data.Hash.Internal.OpenSSL.Sha3_224
+ Data.Hash.Internal.OpenSSL: instance Data.Hash.Internal.OpenSSL.OpenSslDigest Data.Hash.Internal.OpenSSL.Sha3_256
+ Data.Hash.Internal.OpenSSL: instance Data.Hash.Internal.OpenSSL.OpenSslDigest Data.Hash.Internal.OpenSSL.Sha3_384
+ Data.Hash.Internal.OpenSSL: instance Data.Hash.Internal.OpenSSL.OpenSslDigest Data.Hash.Internal.OpenSSL.Sha3_512
+ Data.Hash.Internal.OpenSSL: instance Data.Hash.Internal.OpenSSL.OpenSslDigest Data.Hash.Internal.OpenSSL.Shake128
+ Data.Hash.Internal.OpenSSL: instance Data.Hash.Internal.OpenSSL.OpenSslDigest Data.Hash.Internal.OpenSSL.Shake256
+ Data.Hash.Internal.OpenSSL: instance Data.Hash.Internal.OpenSSL.OpenSslDigest a => Data.Hash.Class.Mutable.Hash (Data.Hash.Internal.OpenSSL.Digest a)
+ Data.Hash.Internal.OpenSSL: instance Data.Hash.Internal.OpenSSL.OpenSslDigest a => Data.Hash.Class.Mutable.Internal.IncrementalHash (Data.Hash.Internal.OpenSSL.Digest a)
+ Data.Hash.Internal.OpenSSL: instance GHC.Classes.Eq (Data.Hash.Internal.OpenSSL.Digest a)
+ Data.Hash.Internal.OpenSSL: instance GHC.Classes.Eq Data.Hash.Internal.OpenSSL.Blake2b512
+ Data.Hash.Internal.OpenSSL: instance GHC.Classes.Eq Data.Hash.Internal.OpenSSL.Blake2s256
+ Data.Hash.Internal.OpenSSL: instance GHC.Classes.Eq Data.Hash.Internal.OpenSSL.Keccak256
+ Data.Hash.Internal.OpenSSL: instance GHC.Classes.Eq Data.Hash.Internal.OpenSSL.Sha2_224
+ Data.Hash.Internal.OpenSSL: instance GHC.Classes.Eq Data.Hash.Internal.OpenSSL.Sha2_256
+ Data.Hash.Internal.OpenSSL: instance GHC.Classes.Eq Data.Hash.Internal.OpenSSL.Sha2_384
+ Data.Hash.Internal.OpenSSL: instance GHC.Classes.Eq Data.Hash.Internal.OpenSSL.Sha2_512
+ Data.Hash.Internal.OpenSSL: instance GHC.Classes.Eq Data.Hash.Internal.OpenSSL.Sha2_512_224
+ Data.Hash.Internal.OpenSSL: instance GHC.Classes.Eq Data.Hash.Internal.OpenSSL.Sha2_512_256
+ Data.Hash.Internal.OpenSSL: instance GHC.Classes.Eq Data.Hash.Internal.OpenSSL.Sha3_224
+ Data.Hash.Internal.OpenSSL: instance GHC.Classes.Eq Data.Hash.Internal.OpenSSL.Sha3_256
+ Data.Hash.Internal.OpenSSL: instance GHC.Classes.Eq Data.Hash.Internal.OpenSSL.Sha3_384
+ Data.Hash.Internal.OpenSSL: instance GHC.Classes.Eq Data.Hash.Internal.OpenSSL.Sha3_512
+ Data.Hash.Internal.OpenSSL: instance GHC.Classes.Eq Data.Hash.Internal.OpenSSL.Shake128
+ Data.Hash.Internal.OpenSSL: instance GHC.Classes.Eq Data.Hash.Internal.OpenSSL.Shake256
+ Data.Hash.Internal.OpenSSL: instance GHC.Classes.Ord (Data.Hash.Internal.OpenSSL.Digest a)
+ Data.Hash.Internal.OpenSSL: instance GHC.Classes.Ord Data.Hash.Internal.OpenSSL.Blake2b512
+ Data.Hash.Internal.OpenSSL: instance GHC.Classes.Ord Data.Hash.Internal.OpenSSL.Blake2s256
+ Data.Hash.Internal.OpenSSL: instance GHC.Classes.Ord Data.Hash.Internal.OpenSSL.Keccak256
+ Data.Hash.Internal.OpenSSL: instance GHC.Classes.Ord Data.Hash.Internal.OpenSSL.Sha2_224
+ Data.Hash.Internal.OpenSSL: instance GHC.Classes.Ord Data.Hash.Internal.OpenSSL.Sha2_256
+ Data.Hash.Internal.OpenSSL: instance GHC.Classes.Ord Data.Hash.Internal.OpenSSL.Sha2_384
+ Data.Hash.Internal.OpenSSL: instance GHC.Classes.Ord Data.Hash.Internal.OpenSSL.Sha2_512
+ Data.Hash.Internal.OpenSSL: instance GHC.Classes.Ord Data.Hash.Internal.OpenSSL.Sha2_512_224
+ Data.Hash.Internal.OpenSSL: instance GHC.Classes.Ord Data.Hash.Internal.OpenSSL.Sha2_512_256
+ Data.Hash.Internal.OpenSSL: instance GHC.Classes.Ord Data.Hash.Internal.OpenSSL.Sha3_224
+ Data.Hash.Internal.OpenSSL: instance GHC.Classes.Ord Data.Hash.Internal.OpenSSL.Sha3_256
+ Data.Hash.Internal.OpenSSL: instance GHC.Classes.Ord Data.Hash.Internal.OpenSSL.Sha3_384
+ Data.Hash.Internal.OpenSSL: instance GHC.Classes.Ord Data.Hash.Internal.OpenSSL.Sha3_512
+ Data.Hash.Internal.OpenSSL: instance GHC.Classes.Ord Data.Hash.Internal.OpenSSL.Shake128
+ Data.Hash.Internal.OpenSSL: instance GHC.Classes.Ord Data.Hash.Internal.OpenSSL.Shake256
+ Data.Hash.Internal.OpenSSL: instance GHC.Exception.Type.Exception Data.Hash.Internal.OpenSSL.OpenSslException
+ Data.Hash.Internal.OpenSSL: instance GHC.Show.Show (Data.Hash.Internal.OpenSSL.Digest a)
+ Data.Hash.Internal.OpenSSL: instance GHC.Show.Show Data.Hash.Internal.OpenSSL.Blake2b512
+ Data.Hash.Internal.OpenSSL: instance GHC.Show.Show Data.Hash.Internal.OpenSSL.Blake2s256
+ Data.Hash.Internal.OpenSSL: instance GHC.Show.Show Data.Hash.Internal.OpenSSL.Keccak256
+ Data.Hash.Internal.OpenSSL: instance GHC.Show.Show Data.Hash.Internal.OpenSSL.OpenSslException
+ Data.Hash.Internal.OpenSSL: instance GHC.Show.Show Data.Hash.Internal.OpenSSL.Sha2_224
+ Data.Hash.Internal.OpenSSL: instance GHC.Show.Show Data.Hash.Internal.OpenSSL.Sha2_256
+ Data.Hash.Internal.OpenSSL: instance GHC.Show.Show Data.Hash.Internal.OpenSSL.Sha2_384
+ Data.Hash.Internal.OpenSSL: instance GHC.Show.Show Data.Hash.Internal.OpenSSL.Sha2_512
+ Data.Hash.Internal.OpenSSL: instance GHC.Show.Show Data.Hash.Internal.OpenSSL.Sha2_512_224
+ Data.Hash.Internal.OpenSSL: instance GHC.Show.Show Data.Hash.Internal.OpenSSL.Sha2_512_256
+ Data.Hash.Internal.OpenSSL: instance GHC.Show.Show Data.Hash.Internal.OpenSSL.Sha3_224
+ Data.Hash.Internal.OpenSSL: instance GHC.Show.Show Data.Hash.Internal.OpenSSL.Sha3_256
+ Data.Hash.Internal.OpenSSL: instance GHC.Show.Show Data.Hash.Internal.OpenSSL.Sha3_384
+ Data.Hash.Internal.OpenSSL: instance GHC.Show.Show Data.Hash.Internal.OpenSSL.Sha3_512
+ Data.Hash.Internal.OpenSSL: instance GHC.Show.Show Data.Hash.Internal.OpenSSL.Shake128
+ Data.Hash.Internal.OpenSSL: instance GHC.Show.Show Data.Hash.Internal.OpenSSL.Shake256
+ Data.Hash.Internal.OpenSSL: newCtx :: IO (Ctx a)
+ Data.Hash.Internal.OpenSSL: newtype Algorithm
+ Data.Hash.Internal.OpenSSL: newtype Blake2b512
+ Data.Hash.Internal.OpenSSL: newtype Blake2s256
+ Data.Hash.Internal.OpenSSL: newtype Ctx a
+ Data.Hash.Internal.OpenSSL: newtype Digest a
+ Data.Hash.Internal.OpenSSL: newtype Keccak256
+ Data.Hash.Internal.OpenSSL: newtype OpenSslException
+ Data.Hash.Internal.OpenSSL: newtype Sha2_224
+ Data.Hash.Internal.OpenSSL: newtype Sha2_256
+ Data.Hash.Internal.OpenSSL: newtype Sha2_384
+ Data.Hash.Internal.OpenSSL: newtype Sha2_512
+ Data.Hash.Internal.OpenSSL: newtype Sha2_512_224
+ Data.Hash.Internal.OpenSSL: newtype Sha2_512_256
+ Data.Hash.Internal.OpenSSL: newtype Sha3_224
+ Data.Hash.Internal.OpenSSL: newtype Sha3_256
+ Data.Hash.Internal.OpenSSL: newtype Sha3_384
+ Data.Hash.Internal.OpenSSL: newtype Sha3_512
+ Data.Hash.Internal.OpenSSL: newtype Shake128
+ Data.Hash.Internal.OpenSSL: newtype Shake256
+ Data.Hash.Internal.OpenSSL: updateCtx :: Ctx a -> Ptr Word8 -> Int -> IO ()
+ Data.Hash.Internal.Utils: B16ShortByteString :: ShortByteString -> B16ShortByteString
+ Data.Hash.Internal.Utils: instance GHC.Show.Show Data.Hash.Internal.Utils.B16ShortByteString
+ Data.Hash.Internal.Utils: newtype B16ShortByteString
+ Data.Hash.Keccak: Keccak256 :: ShortByteString -> Keccak256
+ Data.Hash.Keccak: newtype Keccak256
+ Data.Hash.SHA2: Sha2_224 :: ShortByteString -> Sha2_224
+ Data.Hash.SHA2: Sha2_256 :: ShortByteString -> Sha2_256
+ Data.Hash.SHA2: Sha2_384 :: ShortByteString -> Sha2_384
+ Data.Hash.SHA2: Sha2_512 :: ShortByteString -> Sha2_512
+ Data.Hash.SHA2: Sha2_512_224 :: ShortByteString -> Sha2_512_224
+ Data.Hash.SHA2: Sha2_512_256 :: ShortByteString -> Sha2_512_256
+ Data.Hash.SHA2: newtype Sha2_224
+ Data.Hash.SHA2: newtype Sha2_256
+ Data.Hash.SHA2: newtype Sha2_384
+ Data.Hash.SHA2: newtype Sha2_512
+ Data.Hash.SHA2: newtype Sha2_512_224
+ Data.Hash.SHA2: newtype Sha2_512_256
+ Data.Hash.SHA3: Sha3_224 :: ShortByteString -> Sha3_224
+ Data.Hash.SHA3: Sha3_256 :: ShortByteString -> Sha3_256
+ Data.Hash.SHA3: Sha3_384 :: ShortByteString -> Sha3_384
+ Data.Hash.SHA3: Sha3_512 :: ShortByteString -> Sha3_512
+ Data.Hash.SHA3: Shake128 :: ShortByteString -> Shake128
+ Data.Hash.SHA3: Shake256 :: ShortByteString -> Shake256
+ Data.Hash.SHA3: newtype Sha3_224
+ Data.Hash.SHA3: newtype Sha3_256
+ Data.Hash.SHA3: newtype Sha3_384
+ Data.Hash.SHA3: newtype Sha3_512
+ Data.Hash.SHA3: newtype Shake128
+ Data.Hash.SHA3: newtype Shake256
+ Data.Hash.SipHash: SipHash :: Word64 -> SipHash (c :: Nat) (d :: Nat)
+ Data.Hash.SipHash: SipHashKey :: {-# UNPACK #-} !Word64 -> {-# UNPACK #-} !Word64 -> SipHashKey
+ Data.Hash.SipHash: data SipHashContext (c :: Nat) (d :: Nat)
+ Data.Hash.SipHash: data SipHashKey
+ Data.Hash.SipHash: instance ((GHC.TypeNats.CmpNat n 8 Data.Type.Equality.== 'GHC.Types.GT) GHC.Types.~ 'GHC.Types.True, Data.Hash.SipHash.SipHashRounds (n GHC.TypeNats.- 8) t) => Data.Hash.SipHash.SipHashRounds n 'GHC.Types.True
+ Data.Hash.SipHash: instance (Data.Hash.SipHash.SipHashParam c, Data.Hash.SipHash.SipHashParam d) => Data.Hash.Class.Pure.Internal.IncrementalHash (Data.Hash.SipHash.SipHash c d)
+ Data.Hash.SipHash: instance (Data.Hash.SipHash.SipHashParam c, Data.Hash.SipHash.SipHashParam d) => Data.Hash.Class.Pure.Salted.Hash (Data.Hash.SipHash.SipHash c d)
+ Data.Hash.SipHash: instance Data.Hash.SipHash.SipHashRounds 1 'GHC.Types.False
+ Data.Hash.SipHash: instance Data.Hash.SipHash.SipHashRounds 2 'GHC.Types.False
+ Data.Hash.SipHash: instance Data.Hash.SipHash.SipHashRounds 3 'GHC.Types.False
+ Data.Hash.SipHash: instance Data.Hash.SipHash.SipHashRounds 4 'GHC.Types.False
+ Data.Hash.SipHash: instance Data.Hash.SipHash.SipHashRounds 5 'GHC.Types.False
+ Data.Hash.SipHash: instance Data.Hash.SipHash.SipHashRounds 6 'GHC.Types.False
+ Data.Hash.SipHash: instance Data.Hash.SipHash.SipHashRounds 7 'GHC.Types.False
+ Data.Hash.SipHash: instance Data.Hash.SipHash.SipHashRounds 8 'GHC.Types.False
+ Data.Hash.SipHash: instance Data.Hash.SipHash.SipHashRounds n (Data.Hash.SipHash.SlowRounds n) => Data.Hash.SipHash.SipHashParam n
+ Data.Hash.SipHash: instance GHC.Classes.Eq (Data.Hash.SipHash.SipHash c d)
+ Data.Hash.SipHash: instance GHC.Classes.Eq Data.Hash.SipHash.SipHashKey
+ Data.Hash.SipHash: instance GHC.Classes.Ord (Data.Hash.SipHash.SipHash c d)
+ Data.Hash.SipHash: instance GHC.Classes.Ord Data.Hash.SipHash.SipHashKey
+ Data.Hash.SipHash: instance GHC.Show.Show (Data.Hash.SipHash.SipHash c d)
+ Data.Hash.SipHash: instance GHC.Show.Show Data.Hash.SipHash.SipHashKey
+ Data.Hash.SipHash: newtype SipHash (c :: Nat) (d :: Nat)
+ Data.Hash.SipHash: sipHashFinalize :: forall (c :: Nat) (d :: Nat). SipHashParam c => SipHashParam d => SipHashContext c d -> SipHash c d
+ Data.Hash.SipHash: sipHashInitialize :: SipHashKey -> SipHashContext c d
+ Data.Hash.SipHash: sipHashUpdate :: forall (c :: Nat) (d :: Nat). SipHashParam c => SipHashContext c d -> Ptr Word8 -> Int -> IO (SipHashContext c d)
- Data.Hash.FNV1: fnv1 :: Addr# -> Int -> IO Word
+ Data.Hash.FNV1: fnv1 :: Ptr Word8 -> Int -> IO Fnv1Hash
- Data.Hash.FNV1: fnv1a :: Addr# -> Int -> IO Word
+ Data.Hash.FNV1: fnv1a :: Ptr Word8 -> Int -> IO Fnv1aHash
- Data.Hash.SipHash: sipHash :: Word64 -> Word64 -> Ptr Word8 -> Int -> IO Word64
+ Data.Hash.SipHash: sipHash :: SipHashKey -> Ptr Word8 -> Int -> IO (SipHash 2 4)
- Data.Hash.SipHash: sipHash13 :: Word64 -> Word64 -> Ptr Word8 -> Int -> IO Word64
+ Data.Hash.SipHash: sipHash13 :: SipHashKey -> Ptr Word8 -> Int -> IO (SipHash 1 3)
- Data.Hash.SipHash: sipHash24 :: Word64 -> Word64 -> Ptr Word8 -> Int -> IO Word64
+ Data.Hash.SipHash: sipHash24 :: SipHashKey -> Ptr Word8 -> Int -> IO (SipHash 2 4)
- Data.Hash.SipHash: sipHash48 :: Word64 -> Word64 -> Ptr Word8 -> Int -> IO Word64
+ Data.Hash.SipHash: sipHash48 :: SipHashKey -> Ptr Word8 -> Int -> IO (SipHash 4 8)
- Data.Hash.SipHash: sipHashCD :: Int -> Int -> Word64 -> Word64 -> Ptr Word8 -> Int -> IO Word64
+ Data.Hash.SipHash: sipHashCD :: forall c d. SipHashParam c => SipHashParam d => SipHashKey -> Ptr Word8 -> Int -> IO (SipHash c d)
Files
- CHANGELOG.md +14/−0
- README.md +38/−5
- bench/Main.hs +266/−31
- cbits/keccak-example.c +49/−0
- cbits/keccak.c +145/−0
- cbits/keccak.h +30/−0
- hashes.cabal +83/−10
- src/Data/Hash/Blake2.hs +31/−0
- src/Data/Hash/Class/Mutable.hs +99/−0
- src/Data/Hash/Class/Mutable/Internal.hs +106/−0
- src/Data/Hash/Class/Mutable/Salted.hs +101/−0
- src/Data/Hash/Class/Pure.hs +94/−0
- src/Data/Hash/Class/Pure/Internal.hs +103/−0
- src/Data/Hash/Class/Pure/Salted.hs +83/−0
- src/Data/Hash/FNV1.hs +318/−32
- src/Data/Hash/FNV1/Salted.hs +90/−0
- src/Data/Hash/Internal/OpenSSL.hs +455/−0
- src/Data/Hash/Internal/Utils.hs +27/−0
- src/Data/Hash/Keccak.hs +39/−0
- src/Data/Hash/SHA2.hs +30/−0
- src/Data/Hash/SHA3.hs +30/−0
- src/Data/Hash/SipHash.hs +239/−124
- src/Data/Hash/Utils.hs +0/−144
- test/Cryptonite.hs +166/−0
- test/Main.hs +20/−6
- test/Test/Data/Hash/Class/Pure.hs +115/−0
- test/Test/Data/Hash/FNV1.hs +89/−32
- test/Test/Data/Hash/SipHash.hs +14/−9
- test/Test/Data/Hash/Utils.hs +0/−78
CHANGELOG.md view
@@ -1,5 +1,19 @@ # Revision history for the hashes package +## 0.2.0.0 -- 2021-10-20++Breaking changes:++* Add Class based interfaces for hash functions with pure and mutable+ contexts.+* Support incremental hashing.+* Provide type classes for hash functions with salt / key.+* Add utility functions for hashing `ByteString`s.++Other changes:++* Provide cryptographic hash functions from OpenSSL.+ ## 0.1.0.1 -- 2021-09-30 * Support building with GHC-9.2.0-rc1
README.md view
@@ -1,8 +1,41 @@-Haskell implementation of various non-cryptographic hash functions.+Haskell implementation of various hash functions. -The current version includes+## Available Hash functions -* SipHash-* FNV1 (64 bit and 32 bit)-* FNV1a (64 bit and 32 bit)+### Native Haskell Implementations++* SipHash+ * SipHash-2-4+ * SipHash-1-3+ * SipHash-4-8+ * SipHash-c-d (c rounds per block and d finalization rounds)+* FNV1 (64 bit, 32 bit, and host word size)+* FNV1a (64 bit, 32 bit, and host word size)++## Linked from OpenSSL++The following hash functions are available with the package is build with+`-f+with-openssl`, which is the default.++A version of OpenSSL of at least version 1.1 must be available on the system at+a location for Cabal/GHC can find it.++* SHA2+ * SHA2-224+ * SHA2-256+ * SHA2-384+ * SHA2-512+ * SHA2-512_224 (SHA512 truncated to 224 bits)+ * SHA2-512_256 (SHA512 truncated to 256 bits)+* SHA3+ * SHA3_224+ * SHA3_256+ * SHA3_384+ * SHA3_512+ * SHAKE-128+ * SHAKE-256+* BLAKE2+ * BLAKE2s256+ * BLAKE2b512+* KECCAK-256 (cf. comment in [Data.Hash.Keccak](https://github.com/larskuhtz/hs-hashes/blob/main/src/Data/Hash/Keccak.hs))
bench/Main.hs view
@@ -1,5 +1,8 @@+{-# LANGUAGE CPP #-}+{-# LANGUAGE DataKinds #-} {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TypeApplications #-} -- | -- Module: Main@@ -12,56 +15,129 @@ ( main ) where +import Control.Monad+ import Criterion import Criterion.Main +#if defined(BENCHMARK_CRYPTONITE) import qualified Data.ByteArray as BA import qualified Data.ByteArray.Hash as BA+import qualified Crypto.Hash as C+#endif import qualified Data.ByteString as B+import qualified Data.ByteString.Unsafe as B+import qualified Data.ByteString.Short as BS import Data.Word import GHC.Ptr -import Test.QuickCheck+import System.IO.Unsafe -- internal modules -import qualified Data.Hash.SipHash as H-import qualified Data.Hash.FNV1 as H+import qualified Data.Hash.SipHash as SH+import qualified Data.Hash.FNV1 as FH +#if defined(WITH_OPENSSL)+import qualified Data.Hash.SHA3 as SHA3+import qualified Data.Hash.SHA2 as SHA2+import qualified Data.Hash.Blake2 as BLAKE2+import qualified Data.Hash.Keccak as K+#endif+ -- -------------------------------------------------------------------------- -- -- Main main :: IO () main = do- putStrLn "prop_sip"- quickCheck prop_sip- putStrLn "prop_fnv1a"- quickCheck prop_fnv1a- putStrLn "prop_fnv1aPrimitive"- quickCheck prop_fnv1aPrimitive defaultMain- [ bgroup "sipHash"- [ sipBench "memory" (memorySipHash 17 17)- , sipBench "internal" (H.hashByteString $ H.sipHash24 17 17)- ]- , bgroup "fnv1aHash"- [ fnv1aBench "memory" memoryFnv1a- , fnv1aBench "internal" (H.hashByteString H.fnv1a_64)- , fnv1aBench "primitive" primitiveFnv1a- ]+ [ bgroup "sipHash" $ []+ <> [sipBench "internal" (internalSipHash 17 17)]+#if defined(BENCHMARK_CRYPTONITE)+ <> [sipBench "memory" (memorySipHash 17 17)]+#endif++ , bgroup "fnv1aHash" $ []+ <> [fnv1aBench "internal" internalFnv1a]+ <> [fnv1aBench "primitive" primitiveFnv1a]+#if defined(BENCHMARK_CRYPTONITE)+ <> [fnv1aBench "memory" memoryFnv1a]+#endif++ , bgroup "Sha2_256" $ []+#if defined(WITH_OPENSSL)+ <> [sha2_256Bench "openssl" sha2_256Ssl]+#endif+#if defined(BENCHMARK_CRYPTONITE)+ <> [sha2_256Bench "cryptonite" cryptoniteSha2_256]+#endif++ , bgroup "Sha2_512" $ []+#if defined(WITH_OPENSSL)+ <> [sha2_512Bench "openssl" sha2_512Ssl]+#endif+#if defined(BENCHMARK_CRYPTONITE)+ <> [sha2_512Bench "cryptonite" cryptoniteSha2_512]+#endif++ , bgroup "Sha3_256" $ []+#if defined(WITH_OPENSSL)+ <> [sha3_256Bench "openssl" sha3_256Ssl]+#endif+#if defined(BENCHMARK_CRYPTONITE)+ <> [sha3_256Bench "cryptonite" cryptoniteSha3_256]+#endif++ , bgroup "Sha3_512" $ []+#if defined(WITH_OPENSSL)+ <> [sha3_512Bench "openssl" sha3_512Ssl]+#endif+#if defined(BENCHMARK_CRYPTONITE)+ <> [sha3_512Bench "cryptonite" cryptoniteSha3_512]+#endif++ , bgroup "keccak256" $ []+#if defined(WITH_OPENSSL)+ <> [keccakBench "openssl" keccak256Ssl]+#endif+#if defined(BENCHMARK_CRYPTONITE)+ <> [keccakBench "cryptonite" cryptoniteKeccak256]+#endif++ , bgroup "blake2s256" $ []+#if defined(WITH_OPENSSL)+ <> [blake2s256Bench "openssl" blake2s256Ssl]+#endif+#if defined(BENCHMARK_CRYPTONITE)+ <> [blake2s256Bench "cryptonite" cryptoniteBlake2s256]+#endif++ , bgroup "blake2b512" $ []+#if defined(WITH_OPENSSL)+ <> [ blake2b512Bench "openssl" blake2b512Ssl ]+#endif+#if defined(BENCHMARK_CRYPTONITE)+ <> [ blake2b512Bench "cryptonite" cryptoniteBlake2b512 ]+#endif ] -- -------------------------------------------------------------------------- -- -- SipHash +#if defined(BENCHMARK_CRYPTONITE) memorySipHash :: BA.ByteArrayAccess p => Word64 -> Word64 -> p -> Word64-memorySipHash w0 w1 x = let BA.SipHash r = BA.sipHash (BA.SipKey w0 w1) x in r+memorySipHash w0 w1 x = r+ where+ BA.SipHash r = BA.sipHash (BA.SipKey w0 w1) x {-# INLINE memorySipHash #-}+#endif -prop_sip :: Word64 -> Word64 -> [Word8] -> Property-prop_sip w0 w1 b =- memorySipHash w0 w1 (B.pack b) === H.hashByteString (H.sipHash24 w0 w1) (B.pack b)+internalSipHash :: Word64 -> Word64 -> B.ByteString -> Word64+internalSipHash w0 w1 x = r+ where+ SH.SipHash r = SH.hashByteString @(SH.SipHash 2 4) (SH.SipHashKey w0 w1) x+{-# INLINE internalSipHash #-} sipBench :: String -> (B.ByteString -> Word64) -> Benchmark sipBench l f = bgroup l $ go <$> benchStrings@@ -76,23 +152,182 @@ -- -------------------------------------------------------------------------- -- -- Fvn1Hash +#if defined(BENCHMARK_CRYPTONITE) memoryFnv1a :: B.ByteString -> Word64-memoryFnv1a b = let BA.FnvHash64 h = BA.fnv1a_64Hash b in h+memoryFnv1a b = h+ where+ BA.FnvHash64 h = BA.fnv1a_64Hash b {-# INLINE memoryFnv1a #-}+#endif +internalFnv1a :: B.ByteString -> Word64+internalFnv1a b = r+ where+ FH.Fnv1a64Hash r = FH.hashByteString @FH.Fnv1a64Hash b+{-# INLINE internalFnv1a #-}+ primitiveFnv1a :: B.ByteString -> Word64-primitiveFnv1a = H.hashByteString $ \(Ptr addr) n ->- fromIntegral <$> H.fnv1a addr n+primitiveFnv1a b = unsafeDupablePerformIO $+ B.unsafeUseAsCStringLen b $ \(addr, n) ->+ fromIntegral <$!> FH.fnv1a_host (castPtr addr) n {-# INLINE primitiveFnv1a #-} -prop_fnv1a :: [Word8] -> Property-prop_fnv1a b = memoryFnv1a (B.pack b) === H.hashByteString H.fnv1a_64 (B.pack b)--prop_fnv1aPrimitive :: [Word8] -> Property-prop_fnv1aPrimitive b = primitiveFnv1a (B.pack b) === H.hashByteString H.fnv1a_64 (B.pack b)- fnv1aBench :: String -> (B.ByteString -> Word64) -> Benchmark fnv1aBench l f = bgroup l $ go <$> benchStrings+ where+ go i = bench (show (B.length i)) $ whnf f i++-- -------------------------------------------------------------------------- --+-- SHA3 256++#if defined(WITH_OPENSSL)+sha3_256Ssl :: B.ByteString -> BS.ShortByteString+sha3_256Ssl b = r+ where+ SHA3.Sha3_256 r = SHA3.hashByteString @SHA3.Sha3_256 b+{-# INLINE sha3_256Ssl #-}+#endif++#if defined(BENCHMARK_CRYPTONITE)+cryptoniteSha3_256 :: B.ByteString -> BS.ShortByteString+cryptoniteSha3_256 b = BS.toShort $ BA.convert $! C.hash @_ @C.SHA3_256 b+{-# INLINE cryptoniteSha3_256 #-}+#endif++sha3_256Bench :: String -> (B.ByteString -> BS.ShortByteString) -> Benchmark+sha3_256Bench l f = bgroup l $ go <$> benchStrings+ where+ go i = bench (show (B.length i)) $ whnf f i++-- -------------------------------------------------------------------------- --+-- SHA3 512++#if defined(WITH_OPENSSL)+sha3_512Ssl :: B.ByteString -> BS.ShortByteString+sha3_512Ssl b = r+ where+ SHA3.Sha3_512 r = SHA3.hashByteString @SHA3.Sha3_512 b+{-# INLINE sha3_512Ssl #-}+#endif++#if defined(BENCHMARK_CRYPTONITE)+cryptoniteSha3_512 :: B.ByteString -> BS.ShortByteString+cryptoniteSha3_512 b = BS.toShort $ BA.convert $! C.hash @_ @C.SHA3_512 b+{-# INLINE cryptoniteSha3_512 #-}+#endif++sha3_512Bench :: String -> (B.ByteString -> BS.ShortByteString) -> Benchmark+sha3_512Bench l f = bgroup l $ go <$> benchStrings+ where+ go i = bench (show (B.length i)) $ whnf f i++-- -------------------------------------------------------------------------- --+-- SHA2_256++#if defined(WITH_OPENSSL)+sha2_256Ssl :: B.ByteString -> BS.ShortByteString+sha2_256Ssl b = r+ where+ SHA2.Sha2_256 r = SHA3.hashByteString @SHA2.Sha2_256 b+{-# INLINE sha2_256Ssl #-}+#endif++#if defined(BENCHMARK_CRYPTONITE)+cryptoniteSha2_256 :: B.ByteString -> BS.ShortByteString+cryptoniteSha2_256 b = BS.toShort $ BA.convert $! C.hash @_ @C.SHA256 b+{-# INLINE cryptoniteSha2_256 #-}+#endif++sha2_256Bench :: String -> (B.ByteString -> BS.ShortByteString) -> Benchmark+sha2_256Bench l f = bgroup l $ go <$> benchStrings+ where+ go i = bench (show (B.length i)) $ whnf f i++-- -------------------------------------------------------------------------- --+-- SHA2_512++#if defined(WITH_OPENSSL)+sha2_512Ssl :: B.ByteString -> BS.ShortByteString+sha2_512Ssl b = r+ where+ SHA2.Sha2_512 r = SHA3.hashByteString @SHA2.Sha2_512 b+{-# INLINE sha2_512Ssl #-}+#endif++#if defined(BENCHMARK_CRYPTONITE)+cryptoniteSha2_512 :: B.ByteString -> BS.ShortByteString+cryptoniteSha2_512 b = BS.toShort $ BA.convert $! C.hash @_ @C.SHA512 b+{-# INLINE cryptoniteSha2_512 #-}+#endif++sha2_512Bench :: String -> (B.ByteString -> BS.ShortByteString) -> Benchmark+sha2_512Bench l f = bgroup l $ go <$> benchStrings+ where+ go i = bench (show (B.length i)) $ whnf f i++-- -------------------------------------------------------------------------- --+-- BLAKE2B512++#if defined(WITH_OPENSSL)+blake2b512Ssl :: B.ByteString -> BS.ShortByteString+blake2b512Ssl b = r+ where+ BLAKE2.Blake2b512 r = BLAKE2.hashByteString @BLAKE2.Blake2b512 b+{-# INLINE blake2b512Ssl #-}+#endif++#if defined(BENCHMARK_CRYPTONITE)+cryptoniteBlake2b512 :: B.ByteString -> BS.ShortByteString+cryptoniteBlake2b512 b = BS.toShort $ BA.convert $! C.hash @_ @C.Blake2b_512 b+{-# INLINE cryptoniteBlake2b512 #-}+#endif++blake2b512Bench :: String -> (B.ByteString -> BS.ShortByteString) -> Benchmark+blake2b512Bench l f = bgroup l $ go <$> benchStrings+ where+ go i = bench (show (B.length i)) $ whnf f i++-- -------------------------------------------------------------------------- --+-- BLAKE2S256++#if defined(WITH_OPENSSL)+blake2s256Ssl :: B.ByteString -> BS.ShortByteString+blake2s256Ssl b = r+ where+ BLAKE2.Blake2s256 r = BLAKE2.hashByteString @BLAKE2.Blake2s256 b+{-# INLINE blake2s256Ssl #-}+#endif++#if defined(BENCHMARK_CRYPTONITE)+cryptoniteBlake2s256 :: B.ByteString -> BS.ShortByteString+cryptoniteBlake2s256 b = BS.toShort $ BA.convert $! C.hash @_ @C.Blake2s_256 b+{-# INLINE cryptoniteBlake2s256 #-}+#endif++blake2s256Bench :: String -> (B.ByteString -> BS.ShortByteString) -> Benchmark+blake2s256Bench l f = bgroup l $ go <$> benchStrings+ where+ go i = bench (show (B.length i)) $ whnf f i++-- -------------------------------------------------------------------------- --+-- Keccak 256++#if defined(WITH_OPENSSL)+keccak256Ssl :: B.ByteString -> BS.ShortByteString+keccak256Ssl b = r+ where+ K.Keccak256 r = K.hashByteString @K.Keccak256 b+{-# INLINE keccak256Ssl #-}+#endif++#if defined(BENCHMARK_CRYPTONITE)+cryptoniteKeccak256 :: B.ByteString -> BS.ShortByteString+cryptoniteKeccak256 b = BS.toShort $ BA.convert $! C.hash @_ @C.Keccak_256 b+{-# INLINE cryptoniteKeccak256 #-}+#endif++keccakBench :: String -> (B.ByteString -> BS.ShortByteString) -> Benchmark+keccakBench l f = bgroup l $ go <$> benchStrings where go i = bench (show (B.length i)) $ whnf f i
+ cbits/keccak-example.c view
@@ -0,0 +1,49 @@+#include <string.h>+#include "keccak.h"++/* *************************************************************************** */+/* Generic Tools */++#define CHECKED(f) \+ if (! (f)) { \+ ok = 0; goto finally; \+ }++/* *************************************************************************** */+/* Digests */++typedef unsigned char MD_VALUE[32];+typedef char MD_VALUE_HEX[32*2+1];++void digestToHex(char *result, const unsigned char *md_value) {+ int i;+ for (i = 0; i < 32; i++) {+ sprintf(&result[2*i], "%02x", (uint8_t) (md_value[i]));+ }+}++const char *msg = "testing";+const char *expected = "5f16f4c7f149ac4f9510d9cf8cf384038ad348b3bcdc01915f95de12df9d1b02";++/* *************************************************************************** */+/* Main */++int main()+{+ int ok = 1;+ MD_VALUE md_value;+ MD_VALUE_HEX result;+ KECCAK256_CTX *ctx = NULL;++ CHECKED(ctx = keccak256_newctx());+ CHECKED(keccak256_init(ctx));+ CHECKED(keccak256_update(ctx, msg, strlen(msg)));+ CHECKED(keccak256_final(ctx, md_value));+ digestToHex(result, md_value);+ printf("Keccak-256 digest: %s\n", result);+ printf("expected : %s\n", expected);++finally:+ if (ctx) keccak256_freectx(ctx);+ return ! ok;+}
+ cbits/keccak.c view
@@ -0,0 +1,145 @@+#include <openssl/evp.h>+#include "keccak.h"++/* *************************************************************************** */+/* OpenSSL Master */++/*+int main()+{+ int ok = 1;+ unsigned int md_len = 0;+ MD_VALUE md_value;+ MD_VALUE_HEX result;+ EVP_MD *md;+ EVP_MD_CTX *ctx;++ CHECKED(md = EVP_get_digestbyname("KECCAK-256"));+ CHECKED(ctx = EVP_MD_CTX_new());+ CHECKED(EVP_DigestInit(ctx, md));+ CHECKED(EVP_DigestUpdate(ctx, msg, strlen(msg)));+ CHECKED(EVP_DigestFinal(ctx, md_value, &md_len));++ // Print Digest+ digestToHex(result, md_value);+ printf("Keccak-256 digest: %s\n", result);+ printf("expected : %s\n", expected);++finally:+ if (ctx) keccak256_freectx(ctx);+ return ! ok;+}+*/++#if OPENSSL_VERSION_NUMBER >= 0x30000000L+/* *************************************************************************** */+/* KECCAK-256 for OpenSSL 3.0 */++typedef struct keccak1600_ctx_st KECCAK1600_CTX;+typedef KECCAK1600_CTX KECCAK256_CTX;++extern const OSSL_DISPATCH ossl_sha3_256_functions[];+extern int ossl_sha3_init(KECCAK1600_CTX *ctx, unsigned char pad, size_t bitlen);++typedef void (*VoidFunPtr) (void);++VoidFunPtr dispatch(int fn_id) {+ const OSSL_DISPATCH *fns = ossl_sha3_256_functions;+ for (; fns->function_id != 0; fns++) {+ if (fns->function_id == fn_id) {+ return fns->function;+ }+ }+ return NULL;+}++KECCAK256_CTX *keccak256_newctx()+{+ KECCAK256_CTX * ctx = ((OSSL_FUNC_digest_newctx_fn *) dispatch(OSSL_FUNC_DIGEST_NEWCTX))(NULL);++ // this has already be called once by the dispatch function. Here we update the pad character+ if (ctx) ossl_sha3_init(ctx, '\x01', 256);+ return ctx;+}++int keccak256_init(KECCAK256_CTX *ctx) {+ return ((OSSL_FUNC_digest_init_fn *) dispatch(OSSL_FUNC_DIGEST_INIT))(ctx, NULL);+}++int keccak256_update(KECCAK256_CTX *ctx, const void *p, size_t l)+{+ return ((OSSL_FUNC_digest_update_fn *) dispatch(OSSL_FUNC_DIGEST_UPDATE))(ctx, p, l);+}++int keccak256_final(KECCAK256_CTX *ctx, unsigned char *md)+{+ size_t l;+ return ((OSSL_FUNC_digest_final_fn *) dispatch(OSSL_FUNC_DIGEST_FINAL))(ctx, md, &l, 32);+}++void keccak256_freectx(KECCAK256_CTX *ctx)+{+ return ((OSSL_FUNC_digest_freectx_fn *) dispatch(OSSL_FUNC_DIGEST_FREECTX))(ctx);+}++#elif OPENSSL_VERSION_NUMBER >= 0x10100000L+/* *************************************************************************** */+/* OpenSSL 1.1 */++/* The computation of the magic offset is base on the keccak_st structure in+ * OpenSSL-1.1.+ *+ * Assuming conventional alignment, the bytes offset is+ *+ * sizeof(uint64_t) * 40 + size_of(size_t) * 3 + (1600 / 8 - 32)+ *+ * On a 64bit platform this number is 392+ */++// struct keccak_st {+// uint64_t A[5][5];+// size_t block_size; /* cached ctx->digest->block_size */+// size_t md_size; /* output length, variable in XOF */+// size_t bufsz; /* used bytes in below buffer */+// unsigned char buf[KECCAK1600_WIDTH / 8 - 32];+// unsigned char pad;+// };++typedef EVP_MD_CTX KECCAK256_CTX;++KECCAK256_CTX *keccak256_newctx()+{+ return EVP_MD_CTX_new();+}++int keccak256_init(KECCAK256_CTX *ctx) {+ int ok = 1;+ const EVP_MD *md = NULL;+ int padByteOffset = 25 * sizeof(uint64_t) + 3 * sizeof(size_t) + 1600/8 - 32;+ CHECKED(md = EVP_sha3_256());+ CHECKED(EVP_DigestInit(ctx, md));++ // MAGIC (set padding char to 0x1)+ ((uint8_t *) EVP_MD_CTX_md_data(ctx))[padByteOffset] = 0x01;+finally:+ return ok;+}++int keccak256_update(KECCAK256_CTX *ctx, const void *p, size_t l)+{+ return EVP_DigestUpdate(ctx, p, l);+}++int keccak256_final(KECCAK256_CTX *ctx, unsigned char *md)+{+ unsigned int l;+ return EVP_DigestFinal(ctx, md, &l);+}++void keccak256_freectx(KECCAK256_CTX *ctx)+{+ return EVP_MD_CTX_free(ctx);+}++#endif+
+ cbits/keccak.h view
@@ -0,0 +1,30 @@+#include <openssl/evp.h>++/* *************************************************************************** */+/* Generic Tools */++#define CHECKED(f) \+ if (! (f)) { \+ ok = 0; goto finally; \+ }++/* *************************************************************************** */+/* Keccak-256 */++#if OPENSSL_VERSION_NUMBER >= 0x31000000L++#elif OPENSSL_VERSION_NUMBER >= 0x30000000L+typedef struct keccak1600_ctx_st KECCAK1600_CTX;+typedef KECCAK1600_CTX KECCAK256_CTX;++#elif OPENSSL_VERSION_NUMBER >= 0x10100000L+typedef EVP_MD_CTX KECCAK256_CTX;++#endif++KECCAK256_CTX *keccak256_newctx();+int keccak256_init(KECCAK256_CTX *ctx);+int keccak256_update(KECCAK256_CTX *ctx, const void *p, size_t l);+int keccak256_final(KECCAK256_CTX *ctx, unsigned char *md);+void keccak256_freectx(KECCAK256_CTX *ctx);+
hashes.cabal view
@@ -1,8 +1,8 @@ cabal-version: 2.4 name: hashes-version: 0.1.0.1+version: 0.2.0.0 synopsis: Hash functions-Description: Efficient implementation of non-cryptographic hash functions+Description: Efficient implementations of hash functions homepage: https://github.com/larskuhtz/hs-hashes bug-reports: https://github.com/larskuhtz/hs-hashes/issues license: MIT@@ -18,30 +18,90 @@ extra-source-files: README.md CHANGELOG.md+ cbits/keccak.h+ cbits/keccak.c+ cbits/keccak-example.c source-repository head type: git location: https://github.com/larskuhtz/hs-hashes.git +flag with-openssl+ description:+ Include cryptograph hash functions from openssl. Requires that openssl+ is installed in the system at a location where cabal can find it.+ default: True+ manual: True++flag benchmark-cryptonite+ description: Include implementations from the cryptonite package in benchmarks+ default: False+ manual: True++flag test-cryptonite+ description: Test compatibility with implementations of hash functions in cryptonite+ default: False+ manual: True++flag openssl-use-pkg-config+ description: Use pkg-config to find OpenSSL (macOS and linux only).+ default: False+ manual: True++common openssl-common+ if flag(with-openssl)+ c-sources:+ cbits/keccak.h+ cbits/keccak.c+ cpp-options: -DWITH_OPENSSL=1+ include-dirs:+ /usr/local/opt/openssl@3/include+ /usr/local/opt/openssl/include+ /opt/local/include+ extra-lib-dirs:+ /usr/local/opt/openssl@3/lib/+ /usr/local/opt/openssl/lib/+ /opt/local/lib+ if flag(openssl-use-pkg-config)+ pkgconfig-depends: libcrypto+ else+ extra-Libraries: crypto+ library+ import: openssl-common hs-source-dirs: src default-language: Haskell2010 exposed-modules:- Data.Hash.SipHash+ Data.Hash.Class.Mutable+ Data.Hash.Class.Mutable.Internal+ Data.Hash.Class.Mutable.Salted+ Data.Hash.Class.Pure+ Data.Hash.Class.Pure.Internal+ Data.Hash.Class.Pure.Salted Data.Hash.FNV1- Data.Hash.Utils+ Data.Hash.FNV1.Salted+ Data.Hash.Internal.Utils+ Data.Hash.SipHash+ if flag(with-openssl)+ exposed-modules:+ Data.Hash.Blake2+ Data.Hash.Internal.OpenSSL+ Data.Hash.Keccak+ Data.Hash.SHA2+ Data.Hash.SHA3 ghc-options:- -Wall+ -mbmi2+ -msse4.2 build-depends: , base >=4.11 && <5 , bytestring >=0.10 test-suite tests+ import: openssl-common type: exitcode-stdio-1.0 hs-source-dirs: test default-language: Haskell2010 ghc-options:- -Wall -rtsopts -threaded -with-rtsopts=-N@@ -49,7 +109,7 @@ other-modules: Test.Data.Hash.SipHash Test.Data.Hash.FNV1- Test.Data.Hash.Utils+ Test.Data.Hash.Class.Pure build-depends: -- internal , hashes@@ -57,14 +117,23 @@ , QuickCheck >= 2.13 , base >=4.11 && <5 , bytestring >=0.10+ , sydtest >=0.4 + if flag(test-cryptonite)+ build-depends:+ , memory >=0.14+ , cryptonite >=0.29+ cpp-options: -DTEST_CRYPTONITE=1+ other-modules:+ Cryptonite+ benchmark benchmarks+ import: openssl-common type: exitcode-stdio-1.0 hs-source-dirs: bench main-is: Main.hs default-language: Haskell2010 ghc-options:- -Wall -rtsopts -threaded -with-rtsopts=-N@@ -75,9 +144,13 @@ , hashes -- external- , QuickCheck >= 2.13 , base >=4.10 && <5 , bytestring >=0.10 , criterion >= 1.5- , memory >=0.14++ if flag(benchmark-cryptonite)+ build-depends:+ , memory >=0.14+ , cryptonite >=0.29+ cpp-options: -DBENCHMARK_CRYPTONITE=1
+ src/Data/Hash/Blake2.hs view
@@ -0,0 +1,31 @@+-- |+-- Module: Data.Hash.Blake2+-- Copyright: Copyright © 2021 Lars Kuhtz <lakuhtz@gmail.com>+-- License: MIT+-- Maintainer: Lars Kuhtz <lakuhtz@gmail.com>+-- Stability: experimental+--+-- Blake2 Hash Functions+--+module Data.Hash.Blake2+(+-- * Blake2+--+-- | BLAKE2 is an improved version of BLAKE, which was submitted to the NIST SHA-3+-- algorithm competition. The BLAKE2s and BLAKE2b algorithms are described in+-- RFC 7693.+--+-- While the BLAKE2b and BLAKE2s algorithms supports a variable length digest,+-- this implementation outputs a digest of a fixed length (the maximum length+-- supported), which is 512-bits for BLAKE2b and 256-bits for BLAKE2s.++ Blake2b512(..)+, Blake2s256(..)++, module Data.Hash.Class.Mutable+) where++import Data.Hash.Class.Mutable+import Data.Hash.Internal.OpenSSL++
+ src/Data/Hash/Class/Mutable.hs view
@@ -0,0 +1,99 @@+{-# LANGUAGE AllowAmbiguousTypes #-}+{-# LANGUAGE MagicHash #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TypeApplications #-}++-- |+-- Module: Data.Hash.Class.Mutable+-- Copyright: Copyright © 2021 Lars Kuhtz <lakuhtz@gmail.com>+-- License: MIT+-- Maintainer: Lars Kuhtz <lakuhtz@gmail.com>+-- Stability: experimental+--+-- Class of Salted Pure Hashes+--+module Data.Hash.Class.Mutable+( Hash(..)+, IncrementalHash(..)++, hashPtr+, hashStorable+, hashByteString+, hashByteStringLazy+, hashShortByteString+, hashByteArray++-- * Incremental Hashing+, updateByteString+, updateByteStringLazy+, updateShortByteString+, updateStorable+, updateByteArray+) where++import qualified Data.ByteString as B+import qualified Data.ByteString.Lazy as BL+import qualified Data.ByteString.Short as BS+import Data.Word++import Foreign.Ptr+import Foreign.Storable++import GHC.Exts+import GHC.IO++-- internal modules++import Data.Hash.Class.Mutable.Internal++-- -------------------------------------------------------------------------- --+-- Class of Salted Pure Hashes++class IncrementalHash a => Hash a where+ initialize :: IO (Context a)++-- -------------------------------------------------------------------------- --+-- Hash Functions++hashPtr :: forall a . Hash a => Ptr Word8 -> Int -> IO a+hashPtr p n = do+ ctx <- initialize @a+ update @a ctx p n+ finalize ctx+{-# INLINE hashPtr #-}++hashByteString :: forall a . Hash a => B.ByteString -> a+hashByteString b = unsafeDupablePerformIO $ do+ ctx <- initialize @a+ updateByteString @a ctx b+ finalize ctx+{-# INLINE hashByteString #-}++hashByteStringLazy :: forall a . Hash a => BL.ByteString -> a+hashByteStringLazy b = unsafeDupablePerformIO $ do+ ctx <- initialize @a+ updateByteStringLazy @a ctx b+ finalize ctx+{-# INLINE hashByteStringLazy #-}++hashShortByteString :: forall a . Hash a => BS.ShortByteString -> IO a+hashShortByteString b = do+ ctx <- initialize @a+ updateShortByteString @a ctx b+ finalize ctx+{-# INLINE hashShortByteString #-}++hashStorable :: forall a b . Hash a => Storable b => b -> IO a+hashStorable b = do+ ctx <- initialize @a+ updateStorable @a ctx b+ finalize ctx+{-# INLINE hashStorable #-}++hashByteArray :: forall a . Hash a => ByteArray# -> IO a+hashByteArray b = do+ ctx <- initialize @a+ updateByteArray @a ctx b+ finalize ctx+{-# INLINE hashByteArray #-}+
+ src/Data/Hash/Class/Mutable/Internal.hs view
@@ -0,0 +1,106 @@+{-# LANGUAGE AllowAmbiguousTypes #-}+{-# LANGUAGE BangPatterns #-}+{-# LANGUAGE MagicHash #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TypeApplications #-}+{-# LANGUAGE TypeFamilies #-}++-- |+-- Module: Data.Hash.Class.Mutable.Internal+-- Copyright: Copyright © 2021 Lars Kuhtz <lakuhtz@gmail.com>+-- License: MIT+-- Maintainer: Lars Kuhtz <lakuhtz@gmail.com>+-- Stability: experimental+--+-- Incremental Mutable Hashes+--+module Data.Hash.Class.Mutable.Internal+( IncrementalHash(..)+, updateByteString+, updateByteStringLazy+, updateShortByteString+, updateStorable+, updateByteArray+) where++import qualified Data.ByteString as B+import qualified Data.ByteString.Lazy as BL+import qualified Data.ByteString.Short as BS+import qualified Data.ByteString.Unsafe as B+import Data.Kind+import Data.Word++import Foreign.Marshal.Alloc+import Foreign.Marshal.Utils+import Foreign.Ptr+import Foreign.Storable++import GHC.Exts+import GHC.IO++-- -------------------------------------------------------------------------- --+-- Incremental Mutable Hashes++class IncrementalHash a where+ type Context a :: Type+ update :: Context a -> Ptr Word8 -> Int -> IO ()+ finalize :: Context a -> IO a++updateByteString+ :: forall a+ . IncrementalHash a+ => Context a+ -> B.ByteString+ -> IO ()+updateByteString ctx b = B.unsafeUseAsCStringLen b $ \(!p, !l) ->+ update @a ctx (castPtr p) l+{-# INLINE updateByteString #-}++updateByteStringLazy+ :: forall a+ . IncrementalHash a+ => Context a+ -> BL.ByteString+ -> IO ()+updateByteStringLazy ctx = mapM_ (updateByteString @a ctx) . BL.toChunks+{-# INLINE updateByteStringLazy #-}++updateShortByteString+ :: forall a+ . IncrementalHash a+ => Context a+ -> BS.ShortByteString+ -> IO ()+updateShortByteString ctx b = BS.useAsCStringLen b $ \(!p, !l) ->+ update @a ctx (castPtr p) l+{-# INLINE updateShortByteString #-}++updateStorable+ :: forall a b+ . IncrementalHash a+ => Storable b+ => Context a+ -> b+ -> IO ()+updateStorable ctx b = with b $ \p -> update @a ctx (castPtr p) (sizeOf b)+{-# INLINE updateStorable #-}++updateByteArray+ :: forall a+ . IncrementalHash a+ => Context a+ -> ByteArray#+ -> IO ()+updateByteArray ctx a# = case isByteArrayPinned# a# of+ -- Pinned ByteArray+ 1# -> update @a ctx (Ptr (byteArrayContents# a#)) (I# size#)++ -- Unpinned ByteArray, copy content to newly allocated pinned ByteArray+ _ -> allocaBytes (I# size#) $ \ptr@(Ptr addr#) -> IO $ \s0 ->+ case copyByteArrayToAddr# a# 0# addr# size# s0 of+ s1 -> case update @a ctx ptr (I# size#) of+ IO run -> run s1+ where+ size# = sizeofByteArray# a#+{-# INLINE updateByteArray #-}+
+ src/Data/Hash/Class/Mutable/Salted.hs view
@@ -0,0 +1,101 @@+{-# LANGUAGE AllowAmbiguousTypes #-}+{-# LANGUAGE MagicHash #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TypeApplications #-}+{-# LANGUAGE TypeFamilies #-}++-- |+-- Module: Data.Hash.Class.Mutable.Salted+-- Copyright: Copyright © 2021 Lars Kuhtz <lakuhtz@gmail.com>+-- License: MIT+-- Maintainer: Lars Kuhtz <lakuhtz@gmail.com>+-- Stability: experimental+--+-- Class of Salted Mutable Hashes+--+module Data.Hash.Class.Mutable.Salted+( Hash(..)++, hashPtr+, hashStorable+, hashByteString+, hashByteStringLazy+, hashShortByteString+, hashByteArray++-- * Incremental Hashing+, updateByteString+, updateByteStringLazy+, updateShortByteString+, updateStorable+, updateByteArray+) where++import qualified Data.ByteString as B+import qualified Data.ByteString.Lazy as BL+import qualified Data.ByteString.Short as BS+import Data.Kind+import Data.Word++import Foreign.Ptr+import Foreign.Storable++import GHC.Exts+import GHC.IO++-- internal modules++import Data.Hash.Class.Mutable.Internal++-- -------------------------------------------------------------------------- --+-- Class of Salted Mutable Hashes++class IncrementalHash a => Hash a where+ type Salt a :: Type+ initialize :: Salt a -> IO (Context a)++-- -------------------------------------------------------------------------- --+-- Hash Functions++hashPtr :: forall a . Hash a => Salt a -> Ptr Word8 -> Int -> IO a+hashPtr k p n = do+ ctx <- initialize @a k+ update @a ctx p n+ finalize ctx+{-# INLINE hashPtr #-}++hashByteString :: forall a . Hash a => Salt a -> B.ByteString -> a+hashByteString k b = unsafeDupablePerformIO $ do+ ctx <- initialize @a k+ updateByteString @a ctx b+ finalize ctx+{-# INLINE hashByteString #-}++hashByteStringLazy :: forall a . Hash a => Salt a -> BL.ByteString -> a+hashByteStringLazy k b = unsafeDupablePerformIO $ do+ ctx <- initialize @a k+ updateByteStringLazy @a ctx b+ finalize ctx+{-# INLINE hashByteStringLazy #-}++hashShortByteString :: forall a . Hash a => Salt a -> BS.ShortByteString -> IO a+hashShortByteString k b = do+ ctx <- initialize @a k+ updateShortByteString @a ctx b+ finalize ctx+{-# INLINE hashShortByteString #-}++hashStorable :: forall a b . Hash a => Storable b => Salt a -> b -> IO a+hashStorable k b = do+ ctx <- initialize @a k+ updateStorable @a ctx b+ finalize ctx+{-# INLINE hashStorable #-}++hashByteArray :: forall a . Hash a => Salt a -> ByteArray# -> IO a+hashByteArray k b = do+ ctx <- initialize @a k+ updateByteArray @a ctx b+ finalize ctx+{-# INLINE hashByteArray #-}+
+ src/Data/Hash/Class/Pure.hs view
@@ -0,0 +1,94 @@+{-# LANGUAGE AllowAmbiguousTypes #-}+{-# LANGUAGE MagicHash #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TypeApplications #-}++-- |+-- Module: Data.Hash.Class.Pure+-- Copyright: Copyright © 2021 Lars Kuhtz <lakuhtz@gmail.com>+-- License: MIT+-- Maintainer: Lars Kuhtz <lakuhtz@gmail.com>+-- Stability: experimental+--+-- Hashes with pure context+--+module Data.Hash.Class.Pure+( Hash(..)+, IncrementalHash(..)++, hashPtr+, hashStorable+, hashByteString+, hashByteStringLazy+, hashShortByteString+, hashByteArray++-- * Incremental Hashing+, updateByteString+, updateByteStringLazy+, updateShortByteString+, updateStorable+, updateByteArray++-- * Utilities+, initializeWithSalt+) where++import Control.Monad++import qualified Data.ByteString as B+import qualified Data.ByteString.Lazy as BL+import qualified Data.ByteString.Short as BS+import Data.Word++import Foreign.Ptr+import Foreign.Storable++import GHC.Exts++-- internal modules++import Data.Hash.Class.Pure.Internal++-- -------------------------------------------------------------------------- --+-- Class of Pure Hashes++class IncrementalHash a => Hash a where+ initialize :: Context a++-- -------------------------------------------------------------------------- --+-- hash Functions++hashPtr :: forall a. Hash a => Ptr Word8 -> Int -> IO a+hashPtr p n = finalize <$!> update @a (initialize @a) p n+{-# INLINE hashPtr #-}++hashByteString :: forall a . Hash a => B.ByteString -> a+hashByteString b = finalize $! updateByteString @a (initialize @a) b+{-# INLINE hashByteString #-}++hashByteStringLazy :: forall a . Hash a => BL.ByteString -> a+hashByteStringLazy b = finalize $! updateByteStringLazy @a (initialize @a) b+{-# INLINE hashByteStringLazy #-}++hashShortByteString :: forall a . Hash a => BS.ShortByteString -> a+hashShortByteString b = finalize $! updateShortByteString @a (initialize @a) b+{-# INLINE hashShortByteString #-}++hashStorable :: forall a b . Hash a => Storable b => b -> a+hashStorable b = finalize $! updateStorable @a (initialize @a) b+{-# INLINE hashStorable #-}++hashByteArray :: forall a . Hash a => ByteArray# -> a+hashByteArray b = finalize $! updateByteArray @a (initialize @a) b+{-# INLINE hashByteArray #-}++-- -------------------------------------------------------------------------- --+-- Utilities++-- | Utility function to initialize a hash with a salt+--+initializeWithSalt :: forall a s . Hash a => Storable s => s -> Context a+initializeWithSalt = updateStorable @a $ initialize @a+{-# INLINE initializeWithSalt #-}+
+ src/Data/Hash/Class/Pure/Internal.hs view
@@ -0,0 +1,103 @@+{-# LANGUAGE AllowAmbiguousTypes #-}+{-# LANGUAGE BangPatterns #-}+{-# LANGUAGE MagicHash #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TypeApplications #-}+{-# LANGUAGE TypeFamilies #-}++-- |+-- Module: Data.Hash.Class.Pure.Internal+-- Copyright: Copyright © 2021 Lars Kuhtz <lakuhtz@gmail.com>+-- License: MIT+-- Maintainer: Lars Kuhtz <lakuhtz@gmail.com>+-- Stability: experimental+--+-- Incremental Pure Hashes+--+module Data.Hash.Class.Pure.Internal+( IncrementalHash(..)+, updateByteString+, updateByteStringLazy+, updateShortByteString+, updateStorable+, updateByteArray+) where++import qualified Data.ByteString as B+import qualified Data.ByteString.Lazy as BL+import qualified Data.ByteString.Short as BS+import qualified Data.ByteString.Unsafe as B+import Data.Kind+import Data.Word++import Foreign.Marshal.Alloc+import Foreign.Marshal.Utils+import Foreign.Ptr+import Foreign.Storable++import GHC.Exts+import GHC.IO++-- -------------------------------------------------------------------------- --+-- Incremental Pure Hashes++class IncrementalHash a where+ type Context a :: Type+ update :: Context a -> Ptr Word8 -> Int -> IO (Context a)+ finalize :: Context a -> a++updateByteString :: forall a . IncrementalHash a => Context a -> B.ByteString -> Context a+updateByteString !ctx !b = unsafeDupablePerformIO $!+ B.unsafeUseAsCStringLen b $ \(!p, !l) -> update @a ctx (castPtr p) l+{-# INLINE updateByteString #-}++updateByteStringLazy+ :: forall a+ . IncrementalHash a+ => Context a+ -> BL.ByteString+ -> Context a+updateByteStringLazy = BL.foldlChunks (updateByteString @a)+{-# INLINE updateByteStringLazy #-}++updateShortByteString+ :: forall a+ . IncrementalHash a+ => Context a+ -> BS.ShortByteString+ -> Context a+updateShortByteString !ctx b = unsafeDupablePerformIO $!+ BS.useAsCStringLen b $ \(!p, !l) -> update @a ctx (castPtr p) l+{-# INLINE updateShortByteString #-}++updateStorable+ :: forall a b+ . IncrementalHash a+ => Storable b+ => Context a+ -> b+ -> Context a+updateStorable !ctx b = unsafeDupablePerformIO $!+ with b $ \p -> update @a ctx (castPtr p) (sizeOf b)+{-# INLINE updateStorable #-}++updateByteArray+ :: forall a+ . IncrementalHash a+ => Context a+ -> ByteArray#+ -> Context a+updateByteArray ctx a# = unsafeDupablePerformIO $!+ case isByteArrayPinned# a# of+ -- Pinned ByteArray+ 1# -> update @a ctx (Ptr (byteArrayContents# a#)) (I# size#)++ -- Unpinned ByteArray, copy content to newly allocated pinned ByteArray+ _ -> allocaBytes (I# size#) $ \ptr@(Ptr addr#) -> IO $ \s0 ->+ case copyByteArrayToAddr# a# 0# addr# size# s0 of+ s1 -> case update @a ctx ptr (I# size#) of+ IO run -> run s1+ where+ size# = sizeofByteArray# a#+{-# INLINE updateByteArray #-}+
+ src/Data/Hash/Class/Pure/Salted.hs view
@@ -0,0 +1,83 @@+{-# LANGUAGE AllowAmbiguousTypes #-}+{-# LANGUAGE MagicHash #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TypeApplications #-}+{-# LANGUAGE TypeFamilies #-}++-- |+-- Module: Data.Hash.Class.Pure.Salted+-- Copyright: Copyright © 2021 Lars Kuhtz <lakuhtz@gmail.com>+-- License: MIT+-- Maintainer: Lars Kuhtz <lakuhtz@gmail.com>+-- Stability: experimental+--+module Data.Hash.Class.Pure.Salted+( Hash(..)+, IncrementalHash(..)++, hashPtr+, hashStorable+, hashByteString+, hashByteStringLazy+, hashShortByteString+, hashByteArray++-- * Incremental Hashing+, updateByteString+, updateByteStringLazy+, updateShortByteString+, updateStorable+, updateByteArray+) where++import Control.Monad++import qualified Data.ByteString as B+import qualified Data.ByteString.Lazy as BL+import qualified Data.ByteString.Short as BS+import Data.Kind+import Data.Word++import Foreign.Ptr+import Foreign.Storable++import GHC.Exts++-- internal modules++import Data.Hash.Class.Pure.Internal++-- -------------------------------------------------------------------------- --+-- Class of Pure Salted Hashes++class IncrementalHash a => Hash a where+ type Salt a :: Type+ initialize :: Salt a -> Context a++-- -------------------------------------------------------------------------- --+-- hash Functions++hashPtr :: forall a. Hash a => Salt a -> Ptr Word8 -> Int -> IO a+hashPtr k p n = finalize <$!> update @a (initialize @a k) p n+{-# INLINE hashPtr #-}++hashByteString :: forall a . Hash a => Salt a -> B.ByteString -> a+hashByteString k b = finalize $! updateByteString @a (initialize @a k) b+{-# INLINE hashByteString #-}++hashByteStringLazy :: forall a . Hash a => Salt a -> BL.ByteString -> a+hashByteStringLazy k b = finalize $! updateByteStringLazy @a (initialize @a k) b+{-# INLINE hashByteStringLazy #-}++hashShortByteString :: forall a . Hash a => Salt a -> BS.ShortByteString -> a+hashShortByteString k b = finalize $! updateShortByteString @a (initialize @a k) b+{-# INLINE hashShortByteString #-}++hashStorable :: forall a b . Hash a => Storable b => Salt a -> b -> a+hashStorable k b = finalize $! updateStorable @a (initialize @a k) b+{-# INLINE hashStorable #-}++hashByteArray :: forall a . Hash a => Salt a -> ByteArray# -> a+hashByteArray k b = finalize $! updateByteArray @a (initialize @a k) b+{-# INLINE hashByteArray #-}+
src/Data/Hash/FNV1.hs view
@@ -2,6 +2,7 @@ {-# LANGUAGE CPP #-} {-# LANGUAGE MagicHash #-} {-# LANGUAGE TypeApplications #-}+{-# LANGUAGE TypeFamilies #-} {-# LANGUAGE UnboxedTuples #-} -- |@@ -16,34 +17,84 @@ -- module Data.Hash.FNV1 (--- * IO API (64 bit)+-- * Fnv1 64 bit+ Fnv164Hash(..)+, Fnv164Context+, fnv164Initialize+, fnv164Update+, fnv164Finalize+, fnv164 - fnv1_64++-- * Fnv1a 64 bit+, Fnv1a64Hash(..)+, Fnv1a64Context+, fnv1a64Initialize+, fnv1a64Update+, fnv1a64Finalize+, fnv1a64++-- * Fnv1 32 bit+, Fnv132Hash(..)+, Fnv132Context+, fnv132Initialize+, fnv132Update+, fnv132Finalize+, fnv132++-- * Fnv1a 32 bit+, Fnv1a32Hash(..)+, Fnv1a32Context+, fnv1a32Initialize+, fnv1a32Update+, fnv1a32Finalize+, fnv1a32++-- * Fnv1 Host Wordsize+, Fnv1Hash(..)+, Fnv1Context+, fnv1Initialize+, fnv1Update+, fnv1Finalize+, fnv1++-- * Fnv1a Host Wordsize+, Fnv1aHash(..)+, Fnv1aContext+, fnv1aInitialize+, fnv1aUpdate+, fnv1aFinalize+, fnv1a++-- * Utils+, module Data.Hash.Class.Pure++-- * Low-Level+-- ** 64 bit++, fnv1_64 , fnv1_64_ , fnv1a_64 , fnv1a_64_ --- * 32 bit versions+-- ** 32 bit , fnv1_32 , fnv1_32_ , fnv1a_32 , fnv1a_32_ --- * Primitive (host word size)-, fnv1-, fnv1_+-- ** Host word size+, fnv1_host+, fnv1_host_ , fnv1Primitive , fnv1Primitive_ -, fnv1a-, fnv1a_+, fnv1a_host+, fnv1a_host_ , fnv1aPrimitive , fnv1aPrimitive_ --- * Utils-, module Data.Hash.Utils---- * Constants+-- ** Internal Constants , fnvPrime , fnvPrime32 , fnvPrime64@@ -54,6 +105,8 @@ ) where +import Control.Monad+ import Data.Bits import Data.Word @@ -61,27 +114,256 @@ import Foreign.Storable import GHC.Exts- import GHC.IO -- internal modules -import Data.Hash.Utils+import Data.Hash.Class.Pure -- -------------------------------------------------------------------------- --+-- Fnv1 64 bit++newtype Fnv164Context = Fnv164Context Word64++newtype Fnv164Hash = Fnv164Hash Word64+ deriving (Show, Eq, Ord)++fnv164Initialize :: Fnv164Context+fnv164Initialize = Fnv164Context fnvOffsetBasis64+{-# INLINE fnv164Initialize #-}++fnv164Update :: Fnv164Context -> Ptr Word8 -> Int -> IO Fnv164Context+fnv164Update (Fnv164Context !ctx) !ptr !n =+ Fnv164Context <$!> fnv1_64_ ptr n ctx+{-# INLINE fnv164Update #-}++fnv164Finalize :: Fnv164Context -> Fnv164Hash+fnv164Finalize (Fnv164Context !ctx) = Fnv164Hash ctx+{-# INLINE fnv164Finalize #-}++fnv164 :: Ptr Word8 -> Int -> IO Fnv164Hash+fnv164 !ptr !n = fnv164Finalize <$!> fnv164Update fnv164Initialize ptr n+{-# INLINE fnv164 #-}++instance IncrementalHash Fnv164Hash where+ type Context Fnv164Hash = Fnv164Context+ update = fnv164Update+ finalize = fnv164Finalize++ {-# INLINE update #-}+ {-# INLINE finalize #-}++instance Hash Fnv164Hash where+ initialize = fnv164Initialize+ {-# INLINE initialize #-}++-- -------------------------------------------------------------------------- --+-- Fnv1a 64 bit++newtype Fnv1a64Context = Fnv1a64Context Word64++newtype Fnv1a64Hash = Fnv1a64Hash Word64+ deriving (Show, Eq, Ord)++fnv1a64Initialize :: Fnv1a64Context+fnv1a64Initialize = Fnv1a64Context fnvOffsetBasis64+{-# INLINE fnv1a64Initialize #-}++fnv1a64Update :: Fnv1a64Context -> Ptr Word8 -> Int -> IO Fnv1a64Context+fnv1a64Update (Fnv1a64Context !ctx) !ptr !n =+ Fnv1a64Context <$!> fnv1a_64_ ptr n ctx+{-# INLINE fnv1a64Update #-}++fnv1a64Finalize :: Fnv1a64Context -> Fnv1a64Hash+fnv1a64Finalize (Fnv1a64Context !ctx) = Fnv1a64Hash ctx+{-# INLINE fnv1a64Finalize #-}++fnv1a64 :: Ptr Word8 -> Int -> IO Fnv1a64Hash+fnv1a64 !ptr !n = fnv1a64Finalize <$!> fnv1a64Update fnv1a64Initialize ptr n+{-# INLINE fnv1a64 #-}++instance IncrementalHash Fnv1a64Hash where+ type Context Fnv1a64Hash = Fnv1a64Context+ update = fnv1a64Update+ finalize = fnv1a64Finalize++ {-# INLINE update #-}+ {-# INLINE finalize #-}++instance Hash Fnv1a64Hash where+ initialize = fnv1a64Initialize+ {-# INLINE initialize #-}++-- -------------------------------------------------------------------------- --+-- Fnv1 32 bit++newtype Fnv132Context = Fnv132Context Word32++newtype Fnv132Hash = Fnv132Hash Word32+ deriving (Show, Eq, Ord)++fnv132Initialize :: Fnv132Context+fnv132Initialize = Fnv132Context fnvOffsetBasis32+{-# INLINE fnv132Initialize #-}++fnv132Update :: Fnv132Context -> Ptr Word8 -> Int -> IO Fnv132Context+fnv132Update (Fnv132Context !ctx) !ptr !n =+ Fnv132Context <$!> fnv1_32_ ptr n ctx+{-# INLINE fnv132Update #-}++fnv132Finalize :: Fnv132Context -> Fnv132Hash+fnv132Finalize (Fnv132Context !ctx) = Fnv132Hash ctx+{-# INLINE fnv132Finalize #-}++fnv132 :: Ptr Word8 -> Int -> IO Fnv132Hash+fnv132 !ptr !n = fnv132Finalize <$!> fnv132Update fnv132Initialize ptr n+{-# INLINE fnv132 #-}++instance IncrementalHash Fnv132Hash where+ type Context Fnv132Hash = Fnv132Context+ update = fnv132Update+ finalize = fnv132Finalize++ {-# INLINE update #-}+ {-# INLINE finalize #-}++instance Hash Fnv132Hash where+ initialize = fnv132Initialize+ {-# INLINE initialize #-}++-- -------------------------------------------------------------------------- --+-- Fnv1a 32 bit++newtype Fnv1a32Context = Fnv1a32Context Word32++newtype Fnv1a32Hash = Fnv1a32Hash Word32+ deriving (Show, Eq, Ord)++fnv1a32Initialize :: Fnv1a32Context+fnv1a32Initialize = Fnv1a32Context fnvOffsetBasis32+{-# INLINE fnv1a32Initialize #-}++fnv1a32Update :: Fnv1a32Context -> Ptr Word8 -> Int -> IO Fnv1a32Context+fnv1a32Update (Fnv1a32Context !ctx) !ptr !n =+ Fnv1a32Context <$!> fnv1a_32_ ptr n ctx+{-# INLINE fnv1a32Update #-}++fnv1a32Finalize :: Fnv1a32Context -> Fnv1a32Hash+fnv1a32Finalize (Fnv1a32Context !ctx) = Fnv1a32Hash ctx+{-# INLINE fnv1a32Finalize #-}++fnv1a32 :: Ptr Word8 -> Int -> IO Fnv1a32Hash+fnv1a32 !ptr !n = fnv1a32Finalize <$!> fnv1a32Update fnv1a32Initialize ptr n+{-# INLINE fnv1a32 #-}++instance IncrementalHash Fnv1a32Hash where+ type Context Fnv1a32Hash = Fnv1a32Context+ update = fnv1a32Update+ finalize = fnv1a32Finalize++ {-# INLINE update #-}+ {-# INLINE finalize #-}++instance Hash Fnv1a32Hash where+ initialize = fnv1a32Initialize+ {-# INLINE initialize #-}++-- -------------------------------------------------------------------------- --+-- Fnv1 Host Wordsize++newtype Fnv1Context = Fnv1Context Word++newtype Fnv1Hash = Fnv1Hash Word+ deriving (Show, Eq, Ord)++fnv1Initialize :: Fnv1Context+fnv1Initialize = Fnv1Context fnvOffsetBasis+{-# INLINE fnv1Initialize #-}++fnv1Update :: Fnv1Context -> Ptr Word8 -> Int -> IO Fnv1Context+fnv1Update (Fnv1Context !ctx) !ptr !n =+ Fnv1Context <$!> fnv1_host_ ptr n ctx+{-# INLINE fnv1Update #-}++fnv1Finalize :: Fnv1Context -> Fnv1Hash+fnv1Finalize (Fnv1Context !ctx) = Fnv1Hash ctx+{-# INLINE fnv1Finalize #-}++fnv1 :: Ptr Word8 -> Int -> IO Fnv1Hash+fnv1 !ptr !n = fnv1Finalize <$!> fnv1Update fnv1Initialize ptr n+{-# INLINE fnv1 #-}++instance IncrementalHash Fnv1Hash where+ type Context Fnv1Hash = Fnv1Context+ update = fnv1Update+ finalize = fnv1Finalize++ {-# INLINE update #-}+ {-# INLINE finalize #-}++instance Hash Fnv1Hash where+ initialize = fnv1Initialize+ {-# INLINE initialize #-}++-- -------------------------------------------------------------------------- --+-- Fnv1a Host Wordsize++newtype Fnv1aContext = Fnv1aContext Word++newtype Fnv1aHash = Fnv1aHash Word+ deriving (Show, Eq, Ord)++fnv1aInitialize :: Fnv1aContext+fnv1aInitialize = Fnv1aContext fnvOffsetBasis+{-# INLINE fnv1aInitialize #-}++fnv1aUpdate :: Fnv1aContext -> Ptr Word8 -> Int -> IO Fnv1aContext+fnv1aUpdate (Fnv1aContext !ctx) !ptr !n =+ Fnv1aContext <$!> fnv1a_host_ ptr n ctx+{-# INLINE fnv1aUpdate #-}++fnv1aFinalize :: Fnv1aContext -> Fnv1aHash+fnv1aFinalize (Fnv1aContext !ctx) = Fnv1aHash ctx+{-# INLINE fnv1aFinalize #-}++fnv1a :: Ptr Word8 -> Int -> IO Fnv1aHash+fnv1a !ptr !n = fnv1aFinalize <$!> fnv1aUpdate fnv1aInitialize ptr n+{-# INLINE fnv1a #-}++instance IncrementalHash Fnv1aHash where+ type Context Fnv1aHash = Fnv1aContext+ update = fnv1aUpdate+ finalize = fnv1aFinalize++ {-# INLINE update #-}+ {-# INLINE finalize #-}++instance Hash Fnv1aHash where+ initialize = fnv1aInitialize+ {-# INLINE initialize #-}++-- -------------------------------------------------------------------------- --+-- Low Level+-- -------------------------------------------------------------------------- --++-- -------------------------------------------------------------------------- -- -- Constants fnvPrime32 :: Word32 fnvPrime32 = 0x01000193+{-# INLINE fnvPrime32 #-} fnvPrime64 :: Word64 fnvPrime64 = 0x100000001b3+{-# INLINE fnvPrime64 #-} fnvOffsetBasis32 :: Word32 fnvOffsetBasis32 = 0x811c9dc5+{-# INLINE fnvOffsetBasis32 #-} fnvOffsetBasis64 :: Word64 fnvOffsetBasis64 = 0xcbf29ce484222325+{-# INLINE fnvOffsetBasis64 #-} fnvPrime :: Word #if defined(x86_64_HOST_ARCH)@@ -91,6 +373,7 @@ #else fnvPrime = error "fnvPrime: unsupported hardware platform" #endif+{-# INLINE fnvPrime #-} fnvOffsetBasis :: Word #if defined(x86_64_HOST_ARCH)@@ -100,6 +383,7 @@ #else fnvOffsetBasis = error "fnvOffsetBasis: unsupported hardware platform" #endif+{-# INLINE fnvOffsetBasis #-} -- -------------------------------------------------------------------------- -- -- FNV1 64 bit@@ -169,19 +453,19 @@ {-# INLINE fnv1a_32_ #-} -- -------------------------------------------------------------------------- ----- Primitive (host architecture words)+-- Host architecture words -- FNV1 -fnv1 :: Addr# -> Int -> IO Word-fnv1 addr (I# n) = IO $ \s -> case fnv1Primitive addr n s of+fnv1_host :: Ptr Word8 -> Int -> IO Word+fnv1_host (Ptr addr) (I# n) = IO $ \s -> case fnv1Primitive addr n s of (# s1, w #) -> (# s1, W# w #)-{-# INlINE fnv1 #-}+{-# INlINE fnv1_host #-} -fnv1_ :: Addr# -> Int -> Word -> IO Word-fnv1_ addr (I# n) (W# a) = IO $ \s -> case fnv1Primitive_ addr n a s of+fnv1_host_ :: Ptr Word8 -> Int -> Word -> IO Word+fnv1_host_ (Ptr addr) (I# n) (W# a) = IO $ \s -> case fnv1Primitive_ addr n a s of (# s1, w #) -> (# s1, W# w #)-{-# INlINE fnv1_ #-}+{-# INlINE fnv1_host_ #-} fnv1Primitive :: Addr# -> Int# -> State# tok -> (# State# tok, Word# #) fnv1Primitive !addr !n !tok = fnv1Primitive_ addr n o tok@@ -204,17 +488,18 @@ !(W# p) = fnvPrime {-# INLINE fnv1Primitive_ #-} --- FNV1a+-- -------------------------------------------------------------------------- --+-- Host Wordsize FNV1a -fnv1a :: Addr# -> Int -> IO Word-fnv1a addr (I# n) = IO $ \s -> case fnv1aPrimitive addr n s of+fnv1a_host :: Ptr Word8 -> Int -> IO Word+fnv1a_host (Ptr addr) (I# n) = IO $ \s -> case fnv1aPrimitive addr n s of (# s1, w #) -> (# s1, W# w #)-{-# INlINE fnv1a #-}+{-# INlINE fnv1a_host #-} -fnv1a_ :: Addr# -> Int -> Word -> IO Word-fnv1a_ addr (I# n) (W# a) = IO $ \s -> case fnv1aPrimitive_ addr n a s of+fnv1a_host_ :: Ptr Word8 -> Int -> Word -> IO Word+fnv1a_host_ (Ptr addr) (I# n) (W# a) = IO $ \s -> case fnv1aPrimitive_ addr n a s of (# s1, w #) -> (# s1, W# w #)-{-# INlINE fnv1a_ #-}+{-# INlINE fnv1a_host_ #-} fnv1aPrimitive :: Addr# -> Int# -> State# tok -> (# State# tok, Word# #) fnv1aPrimitive !addr !n !tok = fnv1aPrimitive_ addr n o tok@@ -229,10 +514,10 @@ loop !acc !i !s = case i ==# n of 1# -> (# s, acc #) _ -> case readWord8OffAddr# addr i s of- (# s1, w #) -> loop- (p `timesWord#` (acc `xor#` word8ToWord# w))- (i +# 1#)- s1+ (# s1, w #) ->+ let !acc' = p `timesWord#` (acc `xor#` word8ToWord# w)+ !n' = i +# 1#+ in loop acc' n' s1 !(W# p) = fnvPrime {-# INLINE fnv1aPrimitive_ #-}@@ -246,4 +531,5 @@ -- word8ToWord# :: Word# -> Word# word8ToWord# a = a+{-# INLINE word8ToWord# #-} #endif
+ src/Data/Hash/FNV1/Salted.hs view
@@ -0,0 +1,90 @@+{-# LANGUAGE LambdaCase #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TypeApplications #-}+{-# LANGUAGE TypeFamilies #-}++{-# OPTIONS_GHC -fno-warn-orphans #-}++-- |+-- Module: Data.Hash.FNV1.Salted+-- Copyright: Copyright © 2021 Lars Kuhtz <lakuhtz@gmail.com>+-- License: MIT+-- Maintainer: Lars Kuhtz <lakuhtz@gmail.com>+-- Stability: experimental+--+-- Salted variants for FNV1 Hashes+--+module Data.Hash.FNV1.Salted+(+-- * Fnv1 64 bit+ FH.Fnv164Hash(..)+, FH.Fnv164Context+++-- * Fnv1a 64 bit+, FH.Fnv1a64Hash(..)+, FH.Fnv1a64Context++-- * Fnv1 32 bit+, FH.Fnv132Hash(..)+, FH.Fnv132Context++-- * Fnv1a 32 bit+, FH.Fnv1a32Hash(..)+, FH.Fnv1a32Context++-- * Fnv1 Host Wordsize+, FH.Fnv1Hash(..)+, FH.Fnv1Context++-- * Fnv1a Host Wordsize+, FH.Fnv1aHash(..)+, FH.Fnv1aContext++-- * Utils+, module Data.Hash.Class.Pure.Salted++) where++import Data.Word++-- internal modules++import qualified Data.Hash.FNV1 as FH+import qualified Data.Hash.Class.Pure as PH+import Data.Hash.Class.Pure.Salted++-- -------------------------------------------------------------------------- --+-- Orphans++instance Hash FH.Fnv164Hash where+ type Salt FH.Fnv164Hash = Word64+ initialize = PH.initializeWithSalt @FH.Fnv164Hash+ {-# INLINE initialize #-}++instance Hash FH.Fnv1a64Hash where+ type Salt FH.Fnv1a64Hash = Word64+ initialize = PH.initializeWithSalt @FH.Fnv1a64Hash+ {-# INLINE initialize #-}++instance Hash FH.Fnv132Hash where+ type Salt FH.Fnv132Hash = Word32+ initialize = PH.initializeWithSalt @FH.Fnv132Hash+ {-# INLINE initialize #-}++instance Hash FH.Fnv1a32Hash where+ type Salt FH.Fnv1a32Hash = Word32+ initialize = PH.initializeWithSalt @FH.Fnv1a32Hash+ {-# INLINE initialize #-}++instance Hash FH.Fnv1Hash where+ type Salt FH.Fnv1Hash = Word+ initialize = PH.initializeWithSalt @FH.Fnv1Hash+ {-# INLINE initialize #-}++instance Hash FH.Fnv1aHash where+ type Salt FH.Fnv1aHash = Word+ initialize = PH.initializeWithSalt @FH.Fnv1aHash+ {-# INLINE initialize #-}+
+ src/Data/Hash/Internal/OpenSSL.hs view
@@ -0,0 +1,455 @@+{-# LANGUAGE AllowAmbiguousTypes #-}+{-# LANGUAGE CPP #-}+{-# LANGUAGE DerivingStrategies #-}+{-# LANGUAGE DerivingVia #-}+{-# LANGUAGE LambdaCase #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TypeApplications #-}+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE UndecidableInstances #-}++#include <openssl/opensslv.h>++-- |+-- Module: Data.Hash.Internal.OpenSSL+-- Copyright: Copyright © 2021 Lars Kuhtz <lakuhtz@gmail.com>+-- License: MIT+-- Maintainer: Lars Kuhtz <lakuhtz@gmail.com>+-- Stability: experimental+--+-- Bindings for OpenSSL EVP Message Digest Routines+--+module Data.Hash.Internal.OpenSSL+(++-- * EVP digest routines++ Algorithm(..)+, Ctx(..)+, Digest(..)+, newCtx+, initCtx+, updateCtx+, finalCtx++-- * Algorithms++, OpenSslDigest(..)+, OpenSslException(..)++-- ** SHA2+--+-- $sha2++, Sha2_224(..)+, Sha2_256(..)+, Sha2_384(..)+, Sha2_512(..)+, Sha2_512_224(..)+, Sha2_512_256(..)++-- ** SHA3+--+-- $sha3++, Sha3_224(..)+, Sha3_256(..)+, Sha3_384(..)+, Sha3_512(..)+, Shake128(..)+, Shake256(..)++-- ** Keccak+--+-- $keccak++, Keccak256(..)++-- ** Blake2+--+-- $blake2++, Blake2b512(..)+, Blake2s256(..)+) where++import Control.Exception+import Control.Monad++import qualified Data.ByteString.Short as BS+import Data.Void+import Data.Word++import Foreign.ForeignPtr+import Foreign.Marshal+import Foreign.Ptr++import GHC.IO++-- internal modules++import Data.Hash.Class.Mutable+import Data.Hash.Internal.Utils+++#if OPENSSL_VERSION_NUMBER < 0x10100000L+#error "Unsupported OpenSSL version. Please install OpenSSL >= 1.1.0"+#endif++-- -------------------------------------------------------------------------- --+-- OpenSSL Message Digests++newtype OpenSslException = OpenSslException String+ deriving (Show)++instance Exception OpenSslException++newtype Algorithm = Algorithm (Ptr Void)+newtype Ctx a = Ctx (ForeignPtr Void)+newtype Digest a = Digest BS.ShortByteString+ deriving (Eq, Ord)+ deriving (Show) via B16ShortByteString++#if OPENSSL_VERSION_NUMBER >= 0x10100000L+foreign import ccall unsafe "openssl/evp.h EVP_MD_CTX_new"+#else+foreign import ccall unsafe "openssl/evp.h EVP_MD_CTX_create"+#endif+ c_evp_ctx_new :: IO (Ptr a)++#if OPENSSL_VERSION_NUMBER >= 0x10100000L+foreign import ccall unsafe "openssl/evp.h &EVP_MD_CTX_free"+#else+foreign import ccall unsafe "openssl/evp.h &EVP_MD_CTX_destroy"+#endif+ c_evp_ctx_free_ptr :: FunPtr (Ptr a -> IO ())++-- obsolete, superseeded by EVP_DigestInit_ex instead, but not deprecated+-- (beware in case this becomes a macro in future versions)+--+foreign import ccall unsafe "opnessl/evp.h EVP_DigestInit"+ c_evp_digest_init :: Ptr ctx -> Ptr alg -> IO Bool++foreign import ccall unsafe "opnessl/evp.h EVP_DigestUpdate"+ c_evp_digest_update :: Ptr ctx -> Ptr d -> Int -> IO Bool++foreign import ccall unsafe "opnessl/evp.h EVP_DigestFinal"+ c_evp_digest_final :: Ptr ctx -> Ptr d -> Int -> IO Bool++#if OPENSSL_VERSION_NUMBER >= 0x30000000L+foreign import ccall unsafe "openssl/evp.h EVP_MD_CTX_get0_md"+#else+foreign import ccall unsafe "openssl/evp.h EVP_MD_CTX_md"+#endif+ c_evp_ctx_get0_md :: Ptr ctx -> IO Algorithm++#if OPENSSL_VERSION_NUMBER >= 0x30000000L+foreign import ccall unsafe "openssl/evp.h EVP_MD_get_size"+#else+foreign import ccall unsafe "openssl/evp.h EVP_MD_size"+#endif+ c_evp_get_size :: Algorithm -> IO Int++newCtx :: IO (Ctx a)+newCtx = fmap Ctx $ mask_ $ do+ ptr <- c_evp_ctx_new+ when (ptr == nullPtr) $ throw $ OpenSslException "failed to initialize context"+ newForeignPtr c_evp_ctx_free_ptr ptr+{-# INLINE newCtx #-}++initCtx :: Algorithm -> IO (Ctx a)+initCtx (Algorithm alg) = do+ Ctx ctx <- newCtx+ r <- withForeignPtr ctx $ \ptr ->+ c_evp_digest_init ptr alg+ unless r $ throw $ OpenSslException "digest initialization failed"+ return $ Ctx ctx+{-# INLINE initCtx #-}++updateCtx :: Ctx a -> Ptr Word8 -> Int -> IO ()+updateCtx (Ctx ctx) d c = withForeignPtr ctx $ \ptr -> do+ r <- c_evp_digest_update ptr d c+ unless r $ throw $ OpenSslException "digest update failed"+{-# INLINE updateCtx #-}++finalCtx :: Ctx a -> IO (Digest a)+finalCtx (Ctx ctx) = withForeignPtr ctx $ \ptr -> do+ s <- c_evp_ctx_get0_md ptr >>= c_evp_get_size+ allocaBytes s $ \dptr -> do+ r <- c_evp_digest_final ptr dptr 0+ unless r $ throw $ OpenSslException "digest finalization failed"+ Digest <$> BS.packCStringLen (dptr, s)+{-# INLINE finalCtx #-}++-- -------------------------------------------------------------------------- --+-- Support for DerivingVia++class OpenSslDigest a where+ algorithm :: Algorithm++instance OpenSslDigest a => IncrementalHash (Digest a) where+ type Context (Digest a) = Ctx a+ update = updateCtx+ finalize = finalCtx+ {-# INLINE update #-}+ {-# INLINE finalize #-}++instance OpenSslDigest a => Hash (Digest a) where+ initialize = initCtx (algorithm @a)+ {-# INLINE initialize #-}++-- -------------------------------------------------------------------------- --+-- Digests+-- -------------------------------------------------------------------------- --++-- -------------------------------------------------------------------------- --+-- SHA-2++-- $sha2+--+-- SHA-2 (Secure Hash Algorithm 2) is a family of cryptographic hash functions+-- standardized in NIST FIPS 180-4, first published in 2001. These functions+-- conform to NIST FIPS 180-4.+--+-- The following hash functions from the SHA-2 family are supported in+-- openssl-3.0 (cf. https://www.openssl.org/docs/man3.0/man3/EVP_sha224.html)+--+-- EVP_sha224, EVP_sha256, EVP_sha512_224, EVP_sha512_256, EVP_sha384,+-- EVP_sha512+--++foreign import ccall unsafe "openssl/evp.h EVP_sha224"+ c_evp_sha2_224 :: Algorithm++foreign import ccall unsafe "openssl/evp.h EVP_sha256"+ c_evp_sha2_256 :: Algorithm++foreign import ccall unsafe "openssl/evp.h EVP_sha384"+ c_evp_sha2_384 :: Algorithm++foreign import ccall unsafe "openssl/evp.h EVP_sha512"+ c_evp_sha2_512 :: Algorithm++foreign import ccall unsafe "openssl/evp.h EVP_sha512_224"+ c_evp_sha2_512_224 :: Algorithm++foreign import ccall unsafe "openssl/evp.h EVP_sha512_256"+ c_evp_sha2_512_256 :: Algorithm++newtype Sha2_224 = Sha2_224 BS.ShortByteString+ deriving (Eq, Ord)+ deriving (Show) via B16ShortByteString+ deriving (IncrementalHash, Hash) via (Digest Sha2_224)+instance OpenSslDigest Sha2_224 where algorithm = c_evp_sha2_224++newtype Sha2_256 = Sha2_256 BS.ShortByteString+ deriving (Eq, Ord)+ deriving (Show) via B16ShortByteString+ deriving (IncrementalHash, Hash) via (Digest Sha2_256)+instance OpenSslDigest Sha2_256 where algorithm = c_evp_sha2_256++newtype Sha2_384 = Sha2_384 BS.ShortByteString+ deriving (Eq, Ord)+ deriving (Show) via B16ShortByteString+ deriving (IncrementalHash, Hash) via (Digest Sha2_384)+instance OpenSslDigest Sha2_384 where algorithm = c_evp_sha2_384++newtype Sha2_512 = Sha2_512 BS.ShortByteString+ deriving (Eq, Ord)+ deriving (Show) via B16ShortByteString+ deriving (IncrementalHash, Hash) via (Digest Sha2_512)+instance OpenSslDigest Sha2_512 where algorithm = c_evp_sha2_512++newtype Sha2_512_224 = Sha2_512_224 BS.ShortByteString+ deriving (Eq, Ord)+ deriving (Show) via B16ShortByteString+ deriving (IncrementalHash, Hash) via (Digest Sha2_512_224)+instance OpenSslDigest Sha2_512_224 where algorithm = c_evp_sha2_512_224++newtype Sha2_512_256 = Sha2_512_256 BS.ShortByteString+ deriving (Eq, Ord)+ deriving (Show) via B16ShortByteString+ deriving (IncrementalHash, Hash) via (Digest Sha2_512_256)+instance OpenSslDigest Sha2_512_256 where algorithm = c_evp_sha2_512_256++-- -------------------------------------------------------------------------- --+-- SHA-3++-- $sha3+--+-- SHA-3 (Secure Hash Algorithm 3) is a family of cryptographic hash functions+-- standardized in NIST FIPS 202, first published in 2015. It is based on the+-- Keccak algorithm. These functions conform to NIST FIPS 202.+--+-- The following hash functions from the SHA-3 family are supported in+-- openssl-3.0 (cf. https://www.openssl.org/docs/man3.0/man3/EVP_sha3_224.html)+--+-- EVP_sha3_224, EVP_sha3_256, EVP_sha3_384, EVP_sha3_512, EVP_shake128,+-- EVP_shake256++foreign import ccall unsafe "openssl/evp.h EVP_sha3_224"+ c_evp_sha3_224 :: Algorithm++foreign import ccall unsafe "openssl/evp.h EVP_sha3_256"+ c_evp_sha3_256 :: Algorithm++foreign import ccall unsafe "openssl/evp.h EVP_sha3_384"+ c_evp_sha3_384 :: Algorithm++foreign import ccall unsafe "openssl/evp.h EVP_sha3_512"+ c_evp_sha3_512 :: Algorithm++foreign import ccall unsafe "openssl/evp.h EVP_shake128"+ c_evp_shake128 :: Algorithm++foreign import ccall unsafe "openssl/evp.h EVP_shake256"+ c_evp_shake256 :: Algorithm++newtype Sha3_224 = Sha3_224 BS.ShortByteString+ deriving (Eq, Ord)+ deriving (Show) via B16ShortByteString+ deriving (IncrementalHash, Hash) via (Digest Sha3_224)+instance OpenSslDigest Sha3_224 where algorithm = c_evp_sha3_224++newtype Sha3_256 = Sha3_256 BS.ShortByteString+ deriving (Eq, Ord)+ deriving (Show) via B16ShortByteString+ deriving (IncrementalHash, Hash) via (Digest Sha3_256)+instance OpenSslDigest Sha3_256 where algorithm = c_evp_sha3_256++newtype Sha3_384 = Sha3_384 BS.ShortByteString+ deriving (Eq, Ord)+ deriving (Show) via B16ShortByteString+ deriving (IncrementalHash, Hash) via (Digest Sha3_384)+instance OpenSslDigest Sha3_384 where algorithm = c_evp_sha3_384++newtype Sha3_512 = Sha3_512 BS.ShortByteString+ deriving (Eq, Ord)+ deriving (Show) via B16ShortByteString+ deriving (IncrementalHash, Hash) via (Digest Sha3_512)+instance OpenSslDigest Sha3_512 where algorithm = c_evp_sha3_512++newtype Shake128 = Shake128 BS.ShortByteString+ deriving (Eq, Ord)+ deriving (Show) via B16ShortByteString+ deriving (IncrementalHash, Hash) via (Digest Shake128)+instance OpenSslDigest Shake128 where algorithm = c_evp_shake128++newtype Shake256 = Shake256 BS.ShortByteString+ deriving (Eq, Ord)+ deriving (Show) via B16ShortByteString+ deriving (IncrementalHash, Hash) via (Digest Shake256)+instance OpenSslDigest Shake256 where algorithm = c_evp_shake256++-- -------------------------------------------------------------------------- --+-- Keccak++-- $keccak+--+-- This is the latest version of Keccak-256 hash function that was submitted to+-- the SHA3 competition. It is different from the final NIST SHA3 hash.+--+-- The difference between NIST SHA3-256 and Keccak-256 is the use of a different+-- padding character for the input message. The former uses '0x06' and the+-- latter uses '0x01'.+--+-- This version of Keccak-256 is used by the Ethereum project.+--+-- This implementation of Keccak-256 uses internal OpenSSL APIs. It may break+-- with new versions of OpenSSL. It may also be broken for existing versions of+-- OpenSSL. Portability of the code is unknown.+--+-- ONLY USE THIS CODE AFTER YOU HAVE VERIFIED THAT IT WORKS WITH OUR VERSION OF+-- OPENSSL.+--+-- For details see the file cbits/keccak.c.++newtype Keccak256 = Keccak256 BS.ShortByteString+ deriving (Eq, Ord)+ deriving (Show) via B16ShortByteString++foreign import ccall unsafe "keccak.h keccak256_newctx"+ c_keccak256_newctx :: IO (Ptr ctx)++foreign import ccall unsafe "keccak.h keccak256_init"+ c_keccak256_init :: Ptr ctx -> IO Bool++foreign import ccall unsafe "keccak.h keccak256_update"+ c_keccak256_update :: Ptr ctx -> Ptr Word8 -> Int -> IO Bool++foreign import ccall unsafe "keccak.h keccak256_final"+ c_keccak256_final :: Ptr ctx -> Ptr Word8 -> IO Bool++foreign import ccall unsafe "keccak.h &keccak256_freectx"+ c_keccak256_freectx_ptr :: FunPtr (Ptr ctx -> IO ())++instance IncrementalHash Keccak256 where+ type Context Keccak256 = Ctx Keccak256+ update (Ctx ctx) ptr n = withForeignPtr ctx $ \cptr -> do+ r <- c_keccak256_update cptr ptr n+ unless r $ throw $ OpenSslException "digest update failed"+ finalize (Ctx ctx) = withForeignPtr ctx $ \cptr -> do+ allocaBytes 32 $ \dptr -> do+ r <- c_keccak256_final cptr dptr+ unless r $ throw $ OpenSslException "digest finalization failed"+ Keccak256 <$> BS.packCStringLen (castPtr dptr, 32)+ {-# INLINE update #-}+ {-# INLINE finalize #-}+++newKeccak256Ctx :: IO (Ctx Keccak256)+newKeccak256Ctx = fmap Ctx $ mask_ $ do+ ptr <- c_keccak256_newctx+ when (ptr == nullPtr) $ throw $ OpenSslException "failed to initialize context"+ newForeignPtr c_keccak256_freectx_ptr ptr+{-# INLINE newKeccak256Ctx #-}++instance Hash Keccak256 where+ initialize = do+ Ctx ctx <- newKeccak256Ctx+ r <- withForeignPtr ctx $ \ptr ->+ c_keccak256_init ptr+ unless r $ throw $ OpenSslException "digest initialization failed"+ return $ Ctx ctx+ {-# INLINE initialize #-}++-- -------------------------------------------------------------------------- --+-- Blake++-- $blake2+--+-- BLAKE2 is an improved version of BLAKE, which was submitted to the NIST SHA-3+-- algorithm competition. The BLAKE2s and BLAKE2b algorithms are described in+-- RFC 7693.+--+-- The following hash functions from the BLAKE2 family are supported in+-- openssl-3.0 (cf.+-- https://www.openssl.org/docs/man3.0/man3/EVP_blake2b512.html)+--+-- EVP_blake2b512, EVP_blake2s256+--+-- While the BLAKE2b and BLAKE2s algorithms supports a variable length digest,+-- this implementation outputs a digest of a fixed length (the maximum length+-- supported), which is 512-bits for BLAKE2b and 256-bits for BLAKE2s.+--+--++foreign import ccall unsafe "openssl/evp.h EVP_blake2b512"+ c_evp_blake2b512 :: Algorithm++foreign import ccall unsafe "openssl/evp.h EVP_blake2s256"+ c_evp_blake2s256 :: Algorithm++newtype Blake2b512 = Blake2b512 BS.ShortByteString+ deriving (Eq, Ord)+ deriving (Show) via B16ShortByteString+ deriving (IncrementalHash, Hash) via (Digest Blake2b512)+instance OpenSslDigest Blake2b512 where algorithm = c_evp_blake2b512++newtype Blake2s256 = Blake2s256 BS.ShortByteString+ deriving (Eq, Ord)+ deriving (Show) via B16ShortByteString+ deriving (IncrementalHash, Hash) via (Digest Blake2s256)+instance OpenSslDigest Blake2s256 where algorithm = c_evp_blake2s256+
+ src/Data/Hash/Internal/Utils.hs view
@@ -0,0 +1,27 @@+{-# LANGUAGE LambdaCase #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE ScopedTypeVariables #-}++-- |+-- Module: Data.Hash.Internal.Utils+-- Copyright: Copyright © 2021 Lars Kuhtz <lakuhtz@gmail.com>+-- License: MIT+-- Maintainer: Lars Kuhtz <lakuhtz@gmail.com>+-- Stability: experimental+--+module Data.Hash.Internal.Utils+( B16ShortByteString(..)+) where++import qualified Data.ByteString.Short as BS++import Text.Printf++-- -------------------------------------------------------------------------- --+-- Utils++newtype B16ShortByteString = B16ShortByteString BS.ShortByteString++instance Show B16ShortByteString where+ show (B16ShortByteString b) = concatMap (printf "%0.2x") $ BS.unpack b+
+ src/Data/Hash/Keccak.hs view
@@ -0,0 +1,39 @@+{-# LANGUAGE CPP #-}+{-# LANGUAGE TypeFamilies #-}++-- |+-- Module: Data.Hash.Keccak+-- Copyright: Copyright © 2021 Lars Kuhtz <lakuhtz@gmail.com>+-- License: MIT+-- Maintainer: Lars Kuhtz <lakuhtz@gmail.com>+-- Stability: experimental+--+-- | The code in this module uses internal OpenSSL APIs. It may break with new+-- versions of OpenSSL. It may also be broken for existing versions of OpenSSL.+-- Portability of the code is unknown.+--+-- ONLY USE THIS CODE AFTER YOU HAVE VERIFIED THAT IT WORKS WITH OUR VERSION OF+-- OPENSSL.+--+-- For details see the file cbits/keccak.c.+--+module Data.Hash.Keccak+(+-- * Keccak-256+--+-- | This is the latest version of Keccak-256 hash function that was submitted to+-- the SHA3 competition. It is different from the final NIST SHA3 hash.+--+-- The difference between NIST SHA3-256 and Keccak-256 is the use of a different+-- padding character for the input message. The former uses '0x06' and the+-- latter uses '0x01'.+--+-- This version of Keccak-256 is used by the Ethereum project.++ Keccak256(..)+, module Data.Hash.Class.Mutable+) where++import Data.Hash.Class.Mutable+import Data.Hash.Internal.OpenSSL+
+ src/Data/Hash/SHA2.hs view
@@ -0,0 +1,30 @@+-- |+-- Module: Data.Hash.SHA2+-- Copyright: Copyright © 2021 Lars Kuhtz <lakuhtz@gmail.com>+-- License: MIT+-- Maintainer: Lars Kuhtz <lakuhtz@gmail.com>+-- Stability: experimental+--+-- SHA-2 Hash Functions+--+module Data.Hash.SHA2+(+-- * SHA-2+--+-- | SHA-2 (Secure Hash Algorithm 2) is a family of cryptographic hash functions+-- standardized in NIST FIPS 180-4, first published in 2001. These functions+-- conform to NIST FIPS 180-4.++ Sha2_224(..)+, Sha2_256(..)+, Sha2_384(..)+, Sha2_512(..)+, Sha2_512_224(..)+, Sha2_512_256(..)++, module Data.Hash.Class.Mutable+) where++import Data.Hash.Class.Mutable+import Data.Hash.Internal.OpenSSL+
+ src/Data/Hash/SHA3.hs view
@@ -0,0 +1,30 @@+-- |+-- Module: Data.Hash.SHA3+-- Copyright: Copyright © 2021 Lars Kuhtz <lakuhtz@gmail.com>+-- License: MIT+-- Maintainer: Lars Kuhtz <lakuhtz@gmail.com>+-- Stability: experimental+--+-- SHA-3 Hash Functions+--+module Data.Hash.SHA3+(+-- * SHA-3+--+-- | SHA-3 (Secure Hash Algorithm 3) is a family of cryptographic hash functions+-- standardized in NIST FIPS 202, first published in 2015. It is based on the+-- Keccak algorithm. These functions conform to NIST FIPS 202.++ Sha3_224(..)+, Sha3_256(..)+, Sha3_384(..)+, Sha3_512(..)+, Shake128(..)+, Shake256(..)++, module Data.Hash.Class.Mutable+) where++import Data.Hash.Class.Mutable+import Data.Hash.Internal.OpenSSL+
src/Data/Hash/SipHash.hs view
@@ -1,7 +1,15 @@+{-# LANGUAGE AllowAmbiguousTypes #-} {-# LANGUAGE BangPatterns #-}-{-# LANGUAGE MagicHash #-}+{-# LANGUAGE DataKinds #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE KindSignatures #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE TypeApplications #-}+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE TypeOperators #-} {-# LANGUAGE UnboxedTuples #-}+{-# LANGUAGE UndecidableInstances #-} -- | -- Module: Data.Hash.SipHash@@ -11,62 +19,82 @@ -- Stability: experimental -- module Data.Hash.SipHash-( sipHash-, sipHash13+( SipHashKey(..)+, SipHash(..)+, sipHash++-- * SipHash-c-d+, sipHashCD , sipHash24+, sipHash13 , sipHash48-, sipHashCD +-- * Incremental SipHash+, SipHashContext+, sipHashInitialize+, sipHashUpdate+, sipHashFinalize+ -- * Utils-, module Data.Hash.Utils+, module Data.Hash.Class.Pure.Salted ) where import Control.Monad import Data.Bits-import Data.Function+import Data.Type.Equality import Data.Word -import Foreign.Marshal.Utils+import Foreign.Marshal+import Foreign.Ptr import Foreign.Storable -import GHC.Ptr--import Prelude hiding (drop, length, null, splitAt, take)+import GHC.TypeNats -- internal modules -import Data.Hash.Utils+import Data.Hash.Class.Pure.Salted -- -------------------------------------------------------------------------- -- -- SipHash --- | SipHash, with recommended default parameters of c=2 and c=4.+-- | SipHash, with recommended default parameters of c=2 and d=4. -- -- The first and second argument is the 128 bit key, represented as two 64 bit -- words. -- sipHash- :: Word64- -> Word64+ :: SipHashKey -> Ptr Word8 -> Int- -> IO Word64-sipHash = sipHash24+ -> IO (SipHash 2 4)+sipHash = sipHashCD {-# INLINE sipHash #-} --- | SipHash-2-4+-- | Generic SipHash with c rounds per block and d finalization rounds. -- -- The first and second argument is the 128 bit key, represented as two 64 bit -- words. ---sipHash24- :: Word64- -> Word64+sipHashCD+ :: forall c d+ . SipHashParam c+ => SipHashParam d+ => SipHashKey -> Ptr Word8 -> Int- -> IO Word64-sipHash24 = sipHashInternal rounds2 rounds4+ -> IO (SipHash c d)+sipHashCD key ptr n = sipHashFinalize+ <$> sipHashUpdate (sipHashInitialize key) ptr n+{-# INLINE sipHashCD #-}++-- | SipHash-2-4+--+-- The first and second argument is the 128 bit key, represented as two 64 bit+-- words.+--+sipHash24 :: SipHashKey -> Ptr Word8 -> Int -> IO (SipHash 2 4)+sipHash24 = sipHashCD {-# INLINE sipHash24 #-} -- | SipHash-1-3@@ -74,13 +102,8 @@ -- The first and second argument is the 128 bit key, represented as two 64 bit -- words. ---sipHash13- :: Word64- -> Word64- -> Ptr Word8- -> Int- -> IO Word64-sipHash13 = sipHashInternal rounds1 rounds3+sipHash13 :: SipHashKey -> Ptr Word8 -> Int -> IO (SipHash 1 3)+sipHash13 = sipHashCD {-# INLINE sipHash13 #-} -- | SipHash-4-8@@ -88,83 +111,142 @@ -- The first and second argument is the 128 bit key, represented as two 64 bit -- words. ---sipHash48- :: Word64- -> Word64- -> Ptr Word8- -> Int- -> IO Word64-sipHash48 = sipHashInternal rounds4 rounds8+sipHash48 :: SipHashKey -> Ptr Word8 -> Int -> IO (SipHash 4 8)+sipHash48 = sipHashCD {-# INLINE sipHash48 #-} --- | Generic SipHash with c rounds per block and d finalization rounds.+-- -------------------------------------------------------------------------- --+-- Class++instance (SipHashParam c, SipHashParam d) => IncrementalHash (SipHash c d) where+ type Context (SipHash c d) = SipHashContext c d+ update = sipHashUpdate+ finalize = sipHashFinalize++ {-# INLINE update #-}+ {-# INLINE finalize #-}++instance (SipHashParam c, SipHashParam d) => Hash (SipHash c d) where+ type Salt (SipHash c d) = SipHashKey+ initialize = sipHashInitialize+ {-# INLINE initialize #-}++-- -------------------------------------------------------------------------- --+-- Incremental Version of SipHash++-- | SipHash with @c@ compression rounds and @d@ finalization rounds. ----- The first and second argument is the 128 bit key, represented as two 64 bit--- words.+-- cf. http://cr.yp.to/siphash/siphash-20120918.pdf ---sipHashCD- :: Int- -> Int- -> Word64- -> Word64- -> Ptr Word8- -> Int- -> IO Word64-sipHashCD c d = sipHashInternal (rounds c) (rounds d)-{-# INLINE sipHashCD #-}+newtype SipHash (c :: Nat) (d :: Nat) = SipHash Word64+ deriving (Show, Eq, Ord) --- -------------------------------------------------------------------------- ----- Generic SipHash+-- | The 'Word46' constructor parameters represent the 128 bit key in little+-- endian encoding.+--+data SipHashKey = SipHashKey {-# UNPACK #-} !Word64 {-# UNPACK #-} !Word64+ deriving (Show, Eq, Ord) -data S = S+-- | Internal mutable SipHashContext.+--+-- The first four arguments are the internal state values \(v_{0..3}\) and the+-- last argument represents the pending bytes from an incomplete word of the+-- last chunk of input.+--+data SipHashContext (c :: Nat) (d :: Nat) = SipHashContext {-# UNPACK #-} !Word64 {-# UNPACK #-} !Word64 {-# UNPACK #-} !Word64 {-# UNPACK #-} !Word64+ {-# UNPACK #-} !Word64+ -- ^ the most significant byte keeps track of the total number of input+ -- bytes modulo 256. The remaining bytes are the currently pending input+ -- bytes (i.e. the last \(totalInput `mod` 8\) many bytes of the input). -type Round = Word64 -> Word64 -> Word64 -> Word64 -> (# Word64, Word64, Word64, Word64 #)+-- | Initialize a new SipHashContext+--+sipHashInitialize :: SipHashKey -> SipHashContext c d+sipHashInitialize (SipHashKey k0 k1) = SipHashContext+ (0x736f6d6570736575 `xor` k0)+ (0x646f72616e646f6d `xor` k1)+ (0x6c7967656e657261 `xor` k0)+ (0x7465646279746573 `xor` k1)+ 0x0+{-# INLINE sipHashInitialize #-} -sipHashInternal- :: Round- -> Round- -> Word64- -> Word64+-- | Incrementally add input bytes to an SipHash computation and update+-- the internal context.+--+sipHashUpdate+ :: forall (c :: Nat) (d :: Nat)+ . SipHashParam c+ => SipHashContext c d -> Ptr Word8 -> Int- -> IO Word64-sipHashInternal cRound dRound !k0 !k1 !ptr !len = do+ -> IO (SipHashContext c d)+sipHashUpdate (SipHashContext s0 s1 s2 s3 r) ptr8 len+ | 0 <- rlen `rem` 8 = loop s0 s1 s2 s3 ptr64 len64 - -- loop- (S !v0 !v1 !v2 !v3) <- loop i0 i1 i2 i3 (castPtr ptr) len+ -- Consume the first input word using any possibly pending input bytes from+ -- previous updates.+ --+ | a <- rlen `rem` 8 = do+ let !missing = 8 - a - -- end- let (!off, !r) = quotRem len 8- w <- ptrToWord64 (plusPtr ptr (off * 8)) r- let !b = shiftL (fromIntegral len) 56 .|. w- (# !v0', !v1', !v2', !v3' #) = cRound v0 v1 v2 (v3 `xor` b)- (# !v0'', !v1'', !v2'', !v3'' #) = dRound (v0' `xor` b) v1' (v2' `xor` 0xff) v3'- return $! v0'' `xor` v1'' `xor` v2'' `xor` v3''+ -- get enough bytes to fill up next word (if there are less than 8 - a+ -- bytes the most significant bytes are set to 0)+ !m <- ptrToWord64 ptr64 $ fromIntegral missing + -- add new bytes to get full word64. Input is parsed as little endian,+ -- so new bytes are more significant than pending bytes.+ let !m' = (0x00ffffffffffffff .&. r {- pending bytes -}) .|. m++ if len64 < missing+ then+ -- nothing left to do+ return $ SipHashContext s0 s1 s2 s3 (shiftL (rlen + len64) 56 .|. m')+ else do+ -- compute c round with first word+ let (# v0', v1', v2', v3' #) = rounds @c s0 s1 s2 (s3 `xor` m')+ loop (v0' `xor` m') v1' v2' v3' (plusPtr ptr64 (fromIntegral missing)) (len64 - missing) where+ len64 = fromIntegral len+ {-# INLINE len64 #-} + !ptr64 = castPtr ptr8+ {-# INLINE ptr64 #-}++ !rlen = 0xff00000000000000 .&. r+ {-# INLINE rlen #-}+++ -- Assumes that there are no pending bytes. loop !v0 !v1 !v2 !v3 !p !l- | l < 8 = return $ S v0 v1 v2 v3+ | l < 8 = do+ !m <- ptrToWord64 p l+ return $ SipHashContext v0 v1 v2 v3 (shiftL (rlen + len64) 56 .|. m) | otherwise = do+ -- TODO enforce little endian encoding !m <- peek p- let (# v0', v1', v2', v3' #) = cRound v0 v1 v2 (v3 `xor` m)+ let (# v0', v1', v2', v3' #) = rounds @c v0 v1 v2 (v3 `xor` m) loop (v0' `xor` m) v1' v2' v3' (plusPtr p 8) (l - 8)+ {-# INLINE loop #-}+{-# INLINE sipHashUpdate #-} - !i0 = 0x736f6d6570736575 `xor` k0- !i1 = 0x646f72616e646f6d `xor` k1- !i2 = 0x6c7967656e657261 `xor` k0- !i3 = 0x7465646279746573 `xor` k1- {-# INLINE i0 #-}- {-# INLINE i1 #-}- {-# INLINE i2 #-}- {-# INLINE i3 #-}-{-# INLINE sipHashInternal #-}+sipHashFinalize+ :: forall (c :: Nat) (d :: Nat)+ . SipHashParam c+ => SipHashParam d+ => SipHashContext c d+ -> SipHash c d+sipHashFinalize (SipHashContext v0 v1 v2 v3 m) =+ SipHash $! v0'' `xor` v1'' `xor` v2'' `xor` v3''+ where+ (# !v0', !v1', !v2', !v3' #) = rounds @c v0 v1 v2 (v3 `xor` m)+ (# !v0'', !v1'', !v2'', !v3'' #) = rounds @d (v0' `xor` m) v1' (v2' `xor` 0xff) v3'+{-# INLINE sipHashFinalize #-} -ptrToWord64 :: Ptr Word64 -> Int -> IO Word64+ptrToWord64 :: Ptr Word64 -> Word64 -> IO Word64 ptrToWord64 _ 0 = pure 0 ptrToWord64 !p 1 = fromIntegral <$!> peek @Word8 (castPtr p) ptrToWord64 !p 2 = fromIntegral <$!> peek @Word16 (castPtr p)@@ -173,60 +255,92 @@ -- using 'with' within unsafeDupablePerformIO is probably safe because -- with uses 'alloca', which guarantees that the memory is released -- when computation is abondended before being terminated.- copyBytes p' p i+ copyBytes p' p (fromIntegral i) peek p' {-# INLINE ptrToWord64 #-} -rounds1 :: Word64 -> Word64 -> Word64 -> Word64 -> (# Word64, Word64, Word64, Word64 #)-rounds1 !v0 !v1 !v2 !v3 = sipRound v0 v1 v2 v3-{-# INLINE rounds1 #-}+class SipHashParam (n :: Nat) where+ rounds :: Word64 -> Word64 -> Word64 -> Word64 -> (# Word64, Word64, Word64, Word64 #) -rounds2 :: Word64 -> Word64 -> Word64 -> Word64 -> (# Word64, Word64, Word64, Word64 #)-rounds2 !v0 !v1 !v2 !v3 =- let (# !v0', !v1', !v2', !v3' #) = sipRound v0 v1 v2 v3- in sipRound v0' v1' v2' v3'-{-# INLINE rounds2 #-}+instance SipHashRounds n (SlowRounds n) => SipHashParam (n :: Nat) where+ rounds = rounds_ @n @(SlowRounds n)+ {-# INLINE rounds #-} -rounds3 :: Word64 -> Word64 -> Word64 -> Word64 -> (# Word64, Word64, Word64, Word64 #)-rounds3 !v0 !v1 !v2 !v3 =- let (# !v0', !v1', !v2', !v3' #) = sipRound v0 v1 v2 v3- (# !v0'', !v1'', !v2'', !v3'' #) = sipRound v0' v1' v2' v3'- in sipRound v0'' v1'' v2'' v3''-{-# INLINE rounds3 #-}+-- -------------------------------------------------------------------------- --+-- SipHash Rounds -rounds4 :: Word64 -> Word64 -> Word64 -> Word64 -> (# Word64, Word64, Word64, Word64 #)-rounds4 !v0 !v1 !v2 !v3 =- let (# !v0', !v1', !v2', !v3' #) = sipRound v0 v1 v2 v3- (# !v0'', !v1'', !v2'', !v3'' #) = sipRound v0' v1' v2' v3'- (# !v0''', !v1''', !v2''', !v3''' #) = sipRound v0'' v1'' v2'' v3''- in sipRound v0''' v1''' v2''' v3'''-{-# INLINE rounds4 #-}+-- Decide wether to pick an fast specialized routes implementation or a somewhat+-- less efficient generic implementation.+--+type SlowRounds r = CmpNat r 8 == 'GT -rounds8 :: Word64 -> Word64 -> Word64 -> Word64 -> (# Word64, Word64, Word64, Word64 #)-rounds8 !v0 !v1 !v2 !v3 =- let (# !v0', !v1', !v2', !v3' #) = sipRound v0 v1 v2 v3- (# !v0'', !v1'', !v2'', !v3'' #) = sipRound v0' v1' v2' v3'- (# !v0''', !v1''', !v2''', !v3''' #) = sipRound v0'' v1'' v2'' v3''- (# !v0'''', !v1'''', !v2'''', !v3'''' #) = sipRound v0''' v1''' v2''' v3'''- (# !v0''''', !v1''''', !v2''''', !v3''''' #) = sipRound v0'''' v1'''' v2'''' v3''''- (# !v0'''''', !v1'''''', !v2'''''', !v3'''''' #) = sipRound v0''''' v1''''' v2''''' v3'''''- (# !v0''''''', !v1''''''', !v2''''''', !v3''''''' #) = sipRound v0'''''' v1'''''' v2'''''' v3''''''- in sipRound v0''''''' v1''''''' v2''''''' v3'''''''-{-# INLINE rounds8 #-}+-- TODO: create benchmark to check how well inlining works for recursive type class function calls,+-- It's possibly, that we don't need all these specializations but inlining gets the job done all by+-- itself. -rounds :: Int -> Word64 -> Word64 -> Word64 -> Word64 -> (# Word64, Word64, Word64, Word64 #)-rounds 1 !v0 !v1 !v2 !v3 = rounds1 v0 v1 v2 v3-rounds 2 !v0 !v1 !v2 !v3 = rounds2 v0 v1 v2 v3-rounds 3 !v0 !v1 !v2 !v3 = rounds3 v0 v1 v2 v3-rounds 4 !v0 !v1 !v2 !v3 = rounds4 v0 v1 v2 v3-rounds 8 !v0 !v1 !v2 !v3 = rounds8 v0 v1 v2 v3-rounds !c !v0 !v1 !v2 !v3 = case sipRound v0 v1 v2 v3 of- (# v0', v1', v2', v3' #) -> rounds (c - 1) v0' v1' v2' v3'-{-# INLINE rounds #-}+class SipHashRounds (n :: Nat) (x :: Bool) where+ rounds_ :: Word64 -> Word64 -> Word64 -> Word64 -> (# Word64, Word64, Word64, Word64 #) +instance SipHashRounds 1 'False where+ rounds_ !v0 !v1 !v2 !v3 = sipRound v0 v1 v2 v3+ {-# INLINE rounds_ #-}++instance SipHashRounds 2 'False where+ rounds_ !v0 !v1 !v2 !v3 =+ let (# !v0', !v1', !v2', !v3' #) = sipRound v0 v1 v2 v3+ in sipRound v0' v1' v2' v3'+ {-# INLINE rounds_ #-}++instance SipHashRounds 3 'False where+ rounds_ !v0 !v1 !v2 !v3 =+ let (# !v0', !v1', !v2', !v3' #) = sipRound v0 v1 v2 v3+ (# !v0'', !v1'', !v2'', !v3'' #) = sipRound v0' v1' v2' v3'+ in sipRound v0'' v1'' v2'' v3''+ {-# INLINE rounds_ #-}++instance SipHashRounds 4 'False where+ rounds_ !v0 !v1 !v2 !v3 =+ let (# !v0', !v1', !v2', !v3' #) = sipRound v0 v1 v2 v3+ (# !v0'', !v1'', !v2'', !v3'' #) = sipRound v0' v1' v2' v3'+ (# !v0''', !v1''', !v2''', !v3''' #) = sipRound v0'' v1'' v2'' v3''+ in sipRound v0''' v1''' v2''' v3'''+ {-# INLINE rounds_ #-}++instance SipHashRounds 5 'False where+ rounds_ !v0 !v1 !v2 !v3 = case rounds_ @4 @'False v0 v1 v2 v3 of+ (# v0', v1', v2', v3' #) -> rounds_ @1 @'False v0' v1' v2' v3'+ {-# INLINE rounds_ #-}++instance SipHashRounds 6 'False where+ rounds_ !v0 !v1 !v2 !v3 = case rounds_ @4 @'False v0 v1 v2 v3 of+ (# v0', v1', v2', v3' #) -> rounds_ @2 @'False v0' v1' v2' v3'+ {-# INLINE rounds_ #-}++instance SipHashRounds 7 'False where+ rounds_ !v0 !v1 !v2 !v3 = case rounds_ @4 @'False v0 v1 v2 v3 of+ (# v0', v1', v2', v3' #) -> rounds_ @3 @'False v0' v1' v2' v3'+ {-# INLINE rounds_ #-}++instance SipHashRounds 8 'False where+ rounds_ !v0 !v1 !v2 !v3 =+ let (# !v0', !v1', !v2', !v3' #) = sipRound v0 v1 v2 v3+ (# !v0'', !v1'', !v2'', !v3'' #) = sipRound v0' v1' v2' v3'+ (# !v0''', !v1''', !v2''', !v3''' #) = sipRound v0'' v1'' v2'' v3''+ (# !v0'''', !v1'''', !v2'''', !v3'''' #) = sipRound v0''' v1''' v2''' v3'''+ (# !v0''''', !v1''''', !v2''''', !v3''''' #) = sipRound v0'''' v1'''' v2'''' v3''''+ (# !v0'''''', !v1'''''', !v2'''''', !v3'''''' #) = sipRound v0''''' v1''''' v2''''' v3'''''+ (# !v0''''''', !v1''''''', !v2''''''', !v3''''''' #) = sipRound v0'''''' v1'''''' v2'''''' v3''''''+ in sipRound v0''''''' v1''''''' v2''''''' v3'''''''+ {-# INLINE rounds_ #-}++instance ((CmpNat n 8 == 'GT) ~ 'True, SipHashRounds (n-8) t) => SipHashRounds n 'True where+ rounds_ !v0 !v1 !v2 !v3 = case rounds_ @8 @'False v0 v1 v2 v3 of+ (# v0', v1', v2', v3' #) -> rounds_ @(n - 8) @t v0' v1' v2' v3'+ {-# INLINE rounds_ #-}+ sipRound :: Word64 -> Word64 -> Word64 -> Word64 -> (# Word64, Word64, Word64, Word64 #) sipRound !v0 !v1 !v2 !v3 = (# v0''', v1'''', v2''', v3'''' #)- where+ where !v0' = v0 + v1 !v2' = v2 + v3 !v1' = v1 `rotateL` 13@@ -242,4 +356,5 @@ !v3'''' = v3''' `xor` v0''' !v2''' = v2'' `rotateL` 32 {-# INLINE sipRound #-}+
− src/Data/Hash/Utils.hs
@@ -1,144 +0,0 @@-{-# LANGUAGE BangPatterns #-}-{-# LANGUAGE LambdaCase #-}-{-# LANGUAGE MagicHash #-}-{-# LANGUAGE OverloadedStrings #-}-{-# LANGUAGE ScopedTypeVariables #-}-{-# LANGUAGE UnboxedTuples #-}---- |--- Module: Data.Hash.Utils--- Copyright: Copyright © 2021 Lars Kuhtz <lakuhtz@gmail.com>--- License: MIT--- Maintainer: Lars Kuhtz <lakuhtz@gmail.com>--- Stability: experimental----module Data.Hash.Utils-(--- * Pure API- hashStorable-, hashStorable_-, hashByteString-, hashByteString_-, hashByteArray-, hashByteArray_-, hashPtr-, hashPtr_---- * IO API-, hashStorableIO-, hashStorableIO_-, hashByteStringIO-, hashByteStringIO_-, hashByteArrayIO-, hashByteArrayIO_-) where--import qualified Data.ByteString as B-import qualified Data.ByteString.Unsafe as B-import Data.Word--import Foreign.Marshal.Utils-import Foreign.Ptr-import Foreign.Storable--import GHC.Exts-import GHC.IO-import Foreign.Marshal.Alloc---- -------------------------------------------------------------------------- ----- Pure API---- Storable--hashStorable :: Storable a => (Ptr Word8 -> Int -> IO b) -> a -> b-hashStorable f = unsafeDupablePerformIO . hashStorableIO f-{-# INLINE hashStorable #-}--hashStorable_ :: Storable a => (Ptr Word8 -> Int -> b -> IO b) -> a -> b -> b-hashStorable_ f a = unsafeDupablePerformIO . hashStorableIO_ f a-{-# INLINE hashStorable_ #-}---- ByteString--hashByteString :: (Ptr Word8 -> Int -> IO b) -> B.ByteString -> b-hashByteString f = unsafeDupablePerformIO . hashByteStringIO f-{-# INLINE hashByteString #-}--hashByteString_ :: (Ptr Word8 -> Int -> b -> IO b) -> B.ByteString -> b -> b-hashByteString_ f a = unsafeDupablePerformIO . hashByteStringIO_ f a-{-# INLINE hashByteString_ #-}---- ByteArray--hashByteArray :: (Ptr Word8 -> Int -> IO b) -> ByteArray# -> b-hashByteArray f a# = unsafeDupablePerformIO $! hashByteArrayIO f a#-{-# INLINE hashByteArray #-}--hashByteArray_ :: (Ptr Word8 -> Int -> b -> IO b) -> ByteArray# -> b -> b-hashByteArray_ f a# = unsafeDupablePerformIO . hashByteArrayIO_ f a#-{-# INLINE hashByteArray_ #-}---- Ptr--hashPtr :: (Ptr Word8 -> Int -> IO b) -> Ptr Word8 -> Int -> b-hashPtr f ptr = unsafeDupablePerformIO . f ptr-{-# INLINE hashPtr #-}--hashPtr_ :: (Ptr Word8 -> Int -> b -> IO b) -> Ptr Word8 -> Int -> b -> b-hashPtr_ f ptr l = unsafeDupablePerformIO . f ptr l-{-# INLINE hashPtr_ #-}---- -------------------------------------------------------------------------- ----- IO API---- Storable--hashStorableIO :: Storable a => (Ptr Word8 -> Int -> IO b) -> a -> IO b-hashStorableIO f a = with a $ \ptr -> f (castPtr ptr) (sizeOf a)-{-# INLINE hashStorableIO #-}--hashStorableIO_ :: Storable a => (Ptr Word8 -> Int -> b -> IO b) -> a -> b -> IO b-hashStorableIO_ f a b = with a $ \ptr -> f (castPtr ptr) (sizeOf a) b-{-# INLINE hashStorableIO_ #-}---- ByteString--hashByteStringIO :: (Ptr Word8 -> Int -> IO b) -> B.ByteString -> IO b-hashByteStringIO f a = B.unsafeUseAsCStringLen a $ \(!p, !l) -> f (castPtr p) l-{-# INLINE hashByteStringIO #-}--hashByteStringIO_ :: (Ptr Word8 -> Int -> b -> IO b) -> B.ByteString -> b -> IO b-hashByteStringIO_ f a b = B.unsafeUseAsCStringLen a $ \(!p, !l) -> f (castPtr p) l b-{-# INLINE hashByteStringIO_ #-}---- ByteArray--hashByteArrayIO :: (Ptr Word8 -> Int -> IO b) -> ByteArray# -> IO b-hashByteArrayIO f a# = case isByteArrayPinned# a# of- -- Pinned ByteArray- 1# -> f (Ptr (byteArrayContents# a#)) (I# size#)-- -- Unpinned ByteArray, copy content to newly allocated pinned ByteArray- _ -> allocaBytes (I# size#) $ \ptr@(Ptr addr#) -> IO $ \s0 ->- case copyByteArrayToAddr# a# 0# addr# size# s0 of- s1 -> case f ptr (I# size#) of- IO run -> run s1- where- size# = sizeofByteArray# a#-{-# INLINE hashByteArrayIO #-}---hashByteArrayIO_ :: (Ptr Word8 -> Int -> b -> IO b) -> ByteArray# -> b -> IO b-hashByteArrayIO_ f a# b = case isByteArrayPinned# a# of- -- Pinned ByteArray- 1# -> f (Ptr (byteArrayContents# a#)) (I# size#) b-- -- Unpinned ByteArray, copy content to newly allocated pinned ByteArray- _ -> allocaBytes (I# size#) $ \ptr@(Ptr addr#) -> IO $ \s0 ->- case copyByteArrayToAddr# a# 0# addr# size# s0 of- s1 -> case f ptr (I# size#) b of- IO run -> run s1- where- size# = sizeofByteArray# a#-{-# INLINE hashByteArrayIO_ #-}-
+ test/Cryptonite.hs view
@@ -0,0 +1,166 @@+{-# LANGUAGE AllowAmbiguousTypes #-}+{-# LANGUAGE CPP #-}+{-# LANGUAGE DataKinds #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE LambdaCase #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TypeApplications #-}++-- |+-- Module: Cryptonite+-- Copyright: Copyright © 2021 Lars Kuhtz <lakuhtz@gmail.com>+-- License: MIT+-- Maintainer: Lars Kuhtz <lakuhtz@gmail.com>+-- Stability: experimental+--+-- Compatibility with Cryptonite+--+module Cryptonite+( run+, tests+) where++import Control.Monad++#if defined(WITH_OPENSSL)+import qualified Crypto.Hash as C+import qualified Data.ByteArray as BA+import qualified Data.ByteString.Short as BS+import Data.Coerce+#endif++import qualified Data.ByteArray.Hash as BA+import qualified Data.ByteString as B+import Data.Word++import Test.QuickCheck+import Test.Syd++-- internal modules++#if defined(WITH_OPENSSL)+import Data.Hash.SHA2+import Data.Hash.SHA3+import Data.Hash.Blake2+import Data.Hash.Keccak+import qualified Data.Hash.Class.Mutable as M+#endif++import qualified Data.Hash.SipHash as SH+import qualified Data.Hash.FNV1 as FH++-- -------------------------------------------------------------------------- --+-- OpenSSL++run :: IO ()+run = forM_ properties $ \(n, t) -> do+ putStrLn $ "cryptonite compatiblity for " <> n+ quickCheck t++tests :: Spec+tests = mapM_ (uncurry prop) properties++#if defined(WITH_OPENSSL)+prop_eq+ :: forall alg calg+ . Coercible BS.ShortByteString alg+ => C.HashAlgorithm calg+ => M.Hash alg+ => [Word8]+ -> Property+prop_eq b = internal === cryptonite+ where+ bytes = B.pack b+ cryptonite = BS.toShort $ BA.convert $ C.hash @_ @calg bytes+ internal = coerce $ M.hashByteString @alg bytes+#endif++-- -------------------------------------------------------------------------- --+-- SipHash++-- | Compare with SipHash from the memory package+--+prop_eq_sip :: Word64 -> Word64 -> [Word8] -> Property+prop_eq_sip w0 w1 b = internal === memory+ where+ bytes = B.pack b+ SH.SipHash internal = SH.hashByteString @(SH.SipHash 2 4) (SH.SipHashKey w0 w1) bytes+ BA.SipHash memory = BA.sipHash (BA.SipKey w0 w1) bytes++-- -------------------------------------------------------------------------- --+-- Fvn1Hash++prop_eq_fnv132 :: [Word8] -> Property+prop_eq_fnv132 b = internal === memory+ where+ bytes = B.pack b+ FH.Fnv132Hash internal = FH.hashByteString @FH.Fnv132Hash bytes+ BA.FnvHash32 memory = BA.fnv1Hash bytes++prop_eq_fnv164 :: [Word8] -> Property+prop_eq_fnv164 b = internal === memory+ where+ bytes = B.pack b+ FH.Fnv164Hash internal = FH.hashByteString @FH.Fnv164Hash bytes+ BA.FnvHash64 memory = BA.fnv1_64Hash bytes++-- FIXME: assumes x_64+prop_eq_fnv1Host :: [Word8] -> Property+prop_eq_fnv1Host b = fromIntegral internal64 === internalHost+ where+ bytes = B.pack b+ FH.Fnv164Hash internal64 = FH.hashByteString @FH.Fnv164Hash bytes+ FH.Fnv1Hash internalHost = FH.hashByteString @FH.Fnv1Hash bytes++prop_eq_fnv1a32 :: [Word8] -> Property+prop_eq_fnv1a32 b = internal === memory+ where+ bytes = B.pack b+ FH.Fnv1a32Hash internal = FH.hashByteString @FH.Fnv1a32Hash bytes+ BA.FnvHash32 memory = BA.fnv1aHash bytes++prop_eq_fnv1a64 :: [Word8] -> Property+prop_eq_fnv1a64 b = internal === memory+ where+ bytes = B.pack b+ FH.Fnv1a64Hash internal = FH.hashByteString @FH.Fnv1a64Hash bytes+ BA.FnvHash64 memory = BA.fnv1a_64Hash bytes++-- FIXME: assumes x_64+prop_eq_fnv1aHost :: [Word8] -> Property+prop_eq_fnv1aHost b = fromIntegral internal64 === internalHost+ where+ bytes = B.pack b+ FH.Fnv1a64Hash internal64 = FH.hashByteString @FH.Fnv1a64Hash bytes+ FH.Fnv1aHash internalHost = FH.hashByteString @FH.Fnv1aHash bytes++-- -------------------------------------------------------------------------- --+-- Tests++properties :: [(String, Property)]+properties =+ [ ("prop_eq_sip", property prop_eq_sip)+ , ("prop_eq_fnv132", property prop_eq_fnv132)+ , ("prop_eq_fnv164", property prop_eq_fnv164)+ , ("prop_eq_fnv1Host", property prop_eq_fnv1Host)+ , ("prop_eq_fnv1a32", property prop_eq_fnv1a32)+ , ("prop_eq_fnv1a64", property prop_eq_fnv1a64)+ , ("prop_eq_fnv1aHost", property prop_eq_fnv1aHost)+#if defined(WITH_OPENSSL)+ , ("SHA2_224", property $ prop_eq @Sha2_224 @C.SHA224)+ , ("SHA2_256", property $ prop_eq @Sha2_256 @C.SHA256)+ , ("SHA2_384", property $ prop_eq @Sha2_384 @C.SHA384)+ , ("SHA2_512", property $ prop_eq @Sha2_512 @C.SHA512)+ , ("SHA2_512_224", property $ prop_eq @Sha2_512_224 @C.SHA512t_224)+ , ("SHA2_512_256", property $ prop_eq @Sha2_512_256 @C.SHA512t_256)+ , ("SHA3_224", property $ prop_eq @Sha3_224 @C.SHA3_224)+ , ("SHA3_256", property $ prop_eq @Sha3_256 @C.SHA3_256)+ , ("SHA3_384", property $ prop_eq @Sha3_384 @C.SHA3_384)+ , ("SHA3_512", property $ prop_eq @Sha3_512 @C.SHA3_512)+ , ("Blake2s256", property $ prop_eq @Blake2s256 @C.Blake2s_256)+ , ("Blake2b512", property $ prop_eq @Blake2b512 @C.Blake2b_512)+ , ("Keccak256", property $ prop_eq @Keccak256 @C.Keccak_256)+#endif+ ]+
test/Main.hs view
@@ -1,4 +1,4 @@-+{-# LANGUAGE CPP #-} -- | -- Module: Main -- Copyright: Copyright © 2021 Lars Kuhtz <lakuhtz@gmail.com>@@ -8,15 +8,29 @@ -- module Main ( main+, tests ) where import qualified Test.Data.Hash.FNV1 import qualified Test.Data.Hash.SipHash-import qualified Test.Data.Hash.Utils+import qualified Test.Data.Hash.Class.Pure +#if defined(TEST_CRYPTONITE)+import qualified Cryptonite+#endif++import Test.Syd+ main :: IO ()-main = do- putStrLn "Test.Data.Hash.FNV1.tests: " >> Test.Data.Hash.FNV1.tests- putStrLn "Test.Data.Hash.SipHash.tests: " >> Test.Data.Hash.SipHash.tests- putStrLn "Test.Data.Hash.Utils:" >> Test.Data.Hash.Utils.tests+main = sydTest tests++tests :: Spec+tests = do+ describe "Test.Data.Hash.FNV1.tests" Test.Data.Hash.FNV1.tests+ describe "Test.Data.Hash.SipHash.tests" Test.Data.Hash.SipHash.tests+ describe "Test.Data.Hash.Class.Pure" Test.Data.Hash.Class.Pure.tests++#if defined(TEST_CRYPTONITE)+ describe "Cryptonite" Cryptonite.tests+#endif
+ test/Test/Data/Hash/Class/Pure.hs view
@@ -0,0 +1,115 @@+{-# LANGUAGE BangPatterns #-}+{-# LANGUAGE LambdaCase #-}+{-# LANGUAGE MagicHash #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TypeApplications #-}+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE UnboxedTuples #-}++-- |+-- Module: Test.Data.Hash.Class.Pure+-- Copyright: Copyright © 2021 Lars Kuhtz <lakuhtz@gmail.com>+-- License: MIT+-- Maintainer: Lars Kuhtz <lakuhtz@gmail.com>+-- Stability: experimental+--+module Test.Data.Hash.Class.Pure+( tests+, run+) where++import Data.Bits+import qualified Data.ByteString as B+import qualified Data.ByteString.Lazy as BL+import qualified Data.ByteString.Short as BS+import qualified Data.ByteString.Unsafe as B++import Foreign.Marshal+import Foreign.Ptr++import GHC.Exts+import GHC.IO+import GHC.Word++import Test.QuickCheck+import Test.Syd++-- internal modules++import Data.Hash.Class.Pure.Salted++-- -------------------------------------------------------------------------- --+--++tests :: Spec+tests = do+ prop "prop_hashByteString" prop_hashByteString+ prop "prop_hashByteStringLazy" prop_hashByteStringLazy+ prop "prop_hashShortByteString" prop_hashShortByteString+ prop "prop_hashStorable" prop_hashStorable+ prop "prop_hashPtr" prop_hashPtr+ prop "prop_hashByteArray" prop_hashByteArray++run :: IO ()+run = do+ putStrLn "prop_hashByteString"+ quickCheck prop_hashByteString+ putStrLn "prop_hashByteStringLazy"+ quickCheck prop_hashByteStringLazy+ putStrLn "prop_hashShortByteString"+ quickCheck prop_hashShortByteString+ putStrLn "prop_hashStorable"+ quickCheck prop_hashStorable+ putStrLn "prop_hashPtr"+ quickCheck prop_hashPtr+ putStrLn "prop_hashByteArray"+ quickCheck prop_hashByteArray++word8sToWord64 :: [Word8] -> Word64+word8sToWord64 = foldr (\b c -> fromIntegral b + shiftL c 8) 0++newtype TestHash = TestHash { _getTestHash :: [Word8] }+ deriving (Eq, Ord, Show)++instance IncrementalHash TestHash where+ type Context TestHash = [Word8]+ update ctx p l = (ctx ++) <$> peekArray l p+ finalize = TestHash++instance Hash TestHash where+ type Salt TestHash = ()+ initialize _ = []++prop_hashStorable :: Word64 -> Property+prop_hashStorable b = word8sToWord64 (_getTestHash $ hashStorable @TestHash () b) === b++prop_hashPtr :: [Word8] -> Property+prop_hashPtr b = unsafeDupablePerformIO $+ B.unsafeUseAsCStringLen (B.pack b) $ \(ptr, len) -> do+ return $ unsafeDupablePerformIO (hashPtr @TestHash () (castPtr ptr) len) === TestHash b++prop_hashByteString :: [Word8] -> Property+prop_hashByteString b = hashByteString @TestHash () (B.pack b) === TestHash b++prop_hashByteStringLazy :: [Word8] -> Property+prop_hashByteStringLazy b = hashByteStringLazy @TestHash () (BL.pack b) === TestHash b++prop_hashShortByteString :: [Word8] -> Property+prop_hashShortByteString b = hashShortByteString @TestHash () (BS.pack b) === TestHash b++prop_hashByteArray :: [Word8] -> Property+prop_hashByteArray bytes = unsafeDupablePerformIO $ IO $ \s0 ->+ case newPinnedByteArray# size s0 of+ (# s1, a# #) ->+ case copyToArray 0# bytes a# s1 of+ s2 -> case unsafeFreezeByteArray# a# s2 of+ (# s3, b# #) ->+ let r = hashByteArray @TestHash () b# === TestHash bytes+ in (# s3, r #)+ where+ !(I# size) = length bytes++ copyToArray _ [] _ s = s+ copyToArray i ((W8# h):t) a s = case writeWord8Array# a i h s of+ s' -> copyToArray (i +# 1#) t a s'
test/Test/Data/Hash/FNV1.hs view
@@ -1,7 +1,9 @@ {-# LANGUAGE CPP #-} {-# LANGUAGE LambdaCase #-}+{-# LANGUAGE MagicHash #-} {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TypeApplications #-} -- | -- Module: Test.Data.Hash.FNV1@@ -12,16 +14,20 @@ -- module Test.Data.Hash.FNV1 ( tests+, run ) where import Data.Bifunctor import qualified Data.ByteString as B+import qualified Data.ByteString.Unsafe as B import Data.Word import GHC.Ptr -import Test.QuickCheck+import System.IO.Unsafe +import Test.Syd+ -- internal modules import Data.Hash.FNV1@@ -29,26 +35,42 @@ -- -------------------------------------------------------------------------- -- -- All tests -tests :: IO ()-tests = quickCheck $ tests64- && tests32- && tests64a- && tests32a- && testsPrim- && testsPrima+run :: Bool+run = run64+ && run32+ && run64a+ && run32a+ && runPrim+ && runPrima +tests :: Spec+tests = do+ describe "FNV1 64 bit" tests64+ describe "FNV1 32 bit" tests32+ describe "FNV1a 64 bit" tests64a+ describe "FNV1a 32 bit" tests32a+ describe "FNV1 host word size" testsPrim+ describe "FNV1a host word size" testsPrima+ -- -------------------------------------------------------------------------- -- -- 64 bit FNV1 -tests64 :: Bool-tests64 = all test64 testVectors64+run64 :: Bool+run64 = all test64 testVectors64 && all testZero64 zeros64 +tests64 :: Spec+tests64 = do+ describe "Test Vectors" $ do+ mapM_ (\x -> it (show x) (test64 x)) testVectors64+ describe "Inputs up to 9 bytes that hash to 0" $ do+ mapM_ (\x -> it (show x) (testZero64 x)) zeros64+ test64 :: (B.ByteString, Word64) -> Bool-test64 (b, r) = hashByteString fnv1_64 b == r+test64 (b, r) = hashByteString @Fnv164Hash b == Fnv164Hash r testZero64 :: B.ByteString -> Bool-testZero64 b = hashByteString fnv1_64 b == 0+testZero64 b = hashByteString @Fnv164Hash b == Fnv164Hash 0 testVectors64 :: [(B.ByteString, Word64)] testVectors64 = []@@ -303,15 +325,22 @@ -- -------------------------------------------------------------------------- -- -- 64 bit FNV1a -tests64a :: Bool-tests64a = all test64a testVectors64a+run64a :: Bool+run64a = all test64a testVectors64a && all testZero64a zeros64a +tests64a :: Spec+tests64a = do+ describe "Test Vectors" $ do+ mapM_ (\x -> it (show x) (test64a x)) testVectors64a+ describe "Inputs up to 8 bytes that hash to 0" $ do+ mapM_ (\x -> it (show x) (testZero64a x)) zeros64a+ test64a :: (B.ByteString, Word64) -> Bool-test64a (b, r) = hashByteString fnv1a_64 b == r+test64a (b, r) = hashByteString @Fnv1a64Hash b == Fnv1a64Hash r testZero64a :: B.ByteString -> Bool-testZero64a b = hashByteString fnv1a_64 b == 0+testZero64a b = hashByteString @Fnv1a64Hash b == Fnv1a64Hash 0 testVectors64a :: [(B.ByteString, Word64)] testVectors64a = []@@ -329,19 +358,26 @@ -- -------------------------------------------------------------------------- -- -- 32 bit FNV1 -tests32 :: Bool-tests32 = all test32 testVectors32+run32 :: Bool+run32 = all test32 testVectors32 && all testZero32 zeros32 && testZero32 zero32ff +tests32 :: Spec+tests32 = do+ describe "Test Vectors" $ do+ mapM_ (\x -> it (show x) (test32 x)) testVectors32+ describe "Two out of 254 inputs of up to 5 bytes that hash to 0" $ do+ mapM_ (\x -> it (show x) (testZero32 x)) zeros32+ test32 :: (B.ByteString, Word32) -> Bool-test32 (b, r) = hashByteString fnv1_32 b == r+test32 (b, r) = hashByteString @Fnv132Hash b == Fnv132Hash r testVectors32 :: [(B.ByteString, Word32)] testVectors32 = [] testZero32 :: B.ByteString -> Bool-testZero32 b = hashByteString fnv1_32 b == 0+testZero32 b = hashByteString @Fnv132Hash b == Fnv132Hash 0 -- | Two out of 254 inputs of up to 5 bytes length that result in a -- fnv1 32 bit hash of 0.@@ -365,19 +401,26 @@ -- -------------------------------------------------------------------------- -- -- 32 bit FNV1a -tests32a :: Bool-tests32a = all test32a testVectors32a+run32a :: Bool+run32a = all test32a testVectors32a && all testZero32a zeros32a && testZero32a zero32ffa +tests32a :: Spec+tests32a = do+ describe "Test Vectors" $ do+ mapM_ (\x -> it (show x) (test32a x)) testVectors32a+ describe "Inputs up to 4 bytes that hash to 0" $ do+ mapM_ (\x -> it (show x) (testZero32a x)) zeros32a+ test32a :: (B.ByteString, Word32) -> Bool-test32a (b, r) = hashByteString fnv1a_32 b == r+test32a (b, r) = hashByteString @Fnv1a32Hash b == Fnv1a32Hash r testVectors32a :: [(B.ByteString, Word32)] testVectors32a = [] testZero32a :: B.ByteString -> Bool-testZero32a b = hashByteString fnv1a_32 b == 0+testZero32a b = hashByteString @Fnv1a32Hash b == Fnv1a32Hash 0 -- | All FNV1a 32 bit inputs that result in a hash of 0 up to a length of four -- bytes.@@ -397,14 +440,21 @@ -- Primitive FNV1 primitiveFnv1 :: B.ByteString -> Word-primitiveFnv1 = hashByteString $ \(Ptr addr) n ->- fromIntegral <$> fnv1 addr n+primitiveFnv1 b = unsafeDupablePerformIO $+ B.unsafeUseAsCStringLen b $ \(addr, n) -> fnv1_host (castPtr addr) n {-# INLINE primitiveFnv1 #-} -testsPrim :: Bool-testsPrim = all testPrim testVectorsPrim+runPrim :: Bool+runPrim = all testPrim testVectorsPrim && all testZeroPrim zerosPrim +testsPrim :: Spec+testsPrim = do+ describe "Test Vectors" $ do+ mapM_ (\x -> it (show x) (testPrim x)) testVectorsPrim+ describe "Inputs up to 9 bytes that hash to 0" $ do+ mapM_ (\x -> it (show x) (testZeroPrim x)) zerosPrim+ testPrim :: (B.ByteString, Word) -> Bool testPrim (b, r) = primitiveFnv1 b == r @@ -433,13 +483,20 @@ -- Primitive FNV1a primitiveFnv1a :: B.ByteString -> Word-primitiveFnv1a = hashByteString $ \(Ptr addr) n ->- fromIntegral <$> fnv1a addr n+primitiveFnv1a b = unsafeDupablePerformIO $+ B.unsafeUseAsCStringLen b $ \(addr, n) -> fnv1a_host (castPtr addr) n {-# INLINE primitiveFnv1a #-} -testsPrima :: Bool-testsPrima = all testPrima testVectorsPrima+runPrima :: Bool+runPrima = all testPrima testVectorsPrima && all testZeroPrima zerosPrima++testsPrima :: Spec+testsPrima = do+ describe "Test Vectors" $ do+ mapM_ (\x -> it (show x) (testPrima x)) testVectorsPrima+ describe "Inputs up to 8 bytes that hash to 0" $ do+ mapM_ (\x -> it (show x) (testZeroPrima x)) zerosPrima testPrima :: (B.ByteString, Word) -> Bool testPrima (b, r) = primitiveFnv1a b == r
test/Test/Data/Hash/SipHash.hs view
@@ -1,3 +1,4 @@+{-# LANGUAGE DataKinds #-} {-# LANGUAGE LambdaCase #-} {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE ScopedTypeVariables #-}@@ -12,6 +13,7 @@ -- module Test.Data.Hash.SipHash ( tests+, run ) where import qualified Data.ByteString as B@@ -20,7 +22,7 @@ import System.IO.Unsafe -import Test.QuickCheck+import Test.Syd -- internal modules @@ -36,13 +38,16 @@ -- -------------------------------------------------------------------------- -- -- Tests --- internal sip hash implementation-tests :: IO ()-tests = quickCheck $ all test [0..63]+tests :: Spec+tests = describe "SipHash-2-4 Test Vectors" $ do+ mapM_ (\i -> it (show i) (test i)) [0..length testVectors - 1] test :: Int -> Bool-test i = hashByteString (uncurry sipHash24 testKey) (testInput i) == (testVectors !! i)+test i = hashByteString @(SipHash 2 4) testKey (testInput i) == (testVectors !! i) +run :: Bool+run = all test [0..length testVectors - 1]+ -- -------------------------------------------------------------------------- -- -- Test Vectors from https://svn.grid.pub.ro/svn/bhyve-save-restore/trunk/sys/crypto/siphash/siphash_test.c @@ -76,14 +81,14 @@ */ -} -testKey :: (Word64, Word64)-testKey = (bytesToWord64 [0..7], bytesToWord64 [8..15])+testKey :: SipHashKey+testKey = SipHashKey (bytesToWord64 [0..7]) (bytesToWord64 [8..15]) testInput :: Int -> B.ByteString testInput i = B.pack $ fromIntegral <$> [0..i-1] -testVectors :: [Word64]-testVectors = bytesToWord64 <$>+testVectors :: [SipHash 2 4]+testVectors = SipHash . bytesToWord64 <$> [ [ 0x31, 0x0e, 0x0e, 0xdd, 0x47, 0xdb, 0x6f, 0x72 ] , [ 0xfd, 0x67, 0xdc, 0x93, 0xc5, 0x39, 0xf8, 0x74 ] , [ 0x5a, 0x4f, 0xa9, 0xd9, 0x09, 0x80, 0x6c, 0x0d ]
− test/Test/Data/Hash/Utils.hs
@@ -1,78 +0,0 @@-{-# LANGUAGE BangPatterns #-}-{-# LANGUAGE LambdaCase #-}-{-# LANGUAGE MagicHash #-}-{-# LANGUAGE OverloadedStrings #-}-{-# LANGUAGE ScopedTypeVariables #-}-{-# LANGUAGE UnboxedTuples #-}---- |--- Module: Test.Data.Hash.Utils--- Copyright: Copyright © 2021 Lars Kuhtz <lakuhtz@gmail.com>--- License: MIT--- Maintainer: Lars Kuhtz <lakuhtz@gmail.com>--- Stability: experimental----module Test.Data.Hash.Utils-( tests-) where--import qualified Data.ByteString as B-import qualified Data.ByteString.Unsafe as B--import Foreign.Marshal-import Foreign.Ptr-import Foreign.Storable--import GHC.Exts-import GHC.IO-import GHC.Word--import Test.QuickCheck---- internal modules--import Data.Hash.Utils---- -------------------------------------------------------------------------- -------tests :: IO ()-tests = do- putStrLn "prop_hashByteString"- quickCheck prop_hashByteString- putStrLn "prop_hashStorable"- quickCheck prop_hashStorable- putStrLn "prop_hashPtr"- quickCheck prop_hashPtr- putStrLn "prop_hashByteArray"- quickCheck prop_hashByteArray--ptrToList :: Ptr Word8 -> Int -> IO [Word8]-ptrToList = flip peekArray--prop_hashStorable :: Word64 -> Property-prop_hashStorable b = hashStorable (\ptr _ -> peek (castPtr ptr)) b === b--prop_hashPtr :: [Word8] -> Property-prop_hashPtr b = unsafeDupablePerformIO $- B.unsafeUseAsCStringLen (B.pack b) $ \(ptr, len) -> do- return $ hashPtr ptrToList (castPtr ptr) len === b--prop_hashByteString :: [Word8] -> Property-prop_hashByteString b = hashByteString ptrToList (B.pack b) === b--prop_hashByteArray :: [Word8] -> Property-prop_hashByteArray bytes = unsafeDupablePerformIO $ IO $ \s0 ->- case newPinnedByteArray# size s0 of- (# s1, a# #) ->- case copyToArray 0# bytes a# s1 of- s2 -> case unsafeFreezeByteArray# a# s2 of- (# s3, b# #) ->- let r = hashByteArray ptrToList b# === bytes- in (# s3, r #)- where- !(I# size) = length bytes-- copyToArray _ [] _ s = s- copyToArray i ((W8# h):t) a s = case writeWord8Array# a i h s of- s' -> copyToArray (i +# 1#) t a s'