在cryptonite包

时间:2016-09-18 10:00:20

标签: haskell hash libraries

我正在尝试使用Crypto.Hash module(cryptonite包)并生成“哈希哈希”结果。

问题是模块的哈希函数的签名是hashlazy :: HashAlgorithm a => ByteString -> Digest a,所以在我生成hashlazy (hashlazy x)之前,我需要将摘要转换为ByteString。

虽然提供了digestFromByteString函数,但是反向没有这样的函数(可能对所有Digests都没有意义?)。

所以我找到的唯一方法是这样做:

-- produce a hexadecimal string representation of the digest
myHash :: ByteString -> String
myHash b = show (hashlazy bs :: Digest SHA256)

-- convert a hexadecimal string into a ByteString
fromHexString :: String -> ByteString
fromHexString = undefined 

然后我现在可以做hashhash x = myHash $ fromHexString $ myHash x ...

但这看起来非常麻烦。

我的问题:我是否正确使用了库函数?我错过了某处的转换功能吗?或者我应该采取不同的做法?

===编辑1 ===

我想保持我的问题简单并避免其他我认为不重要的细节,但我确实需要将哈希结果转换回ByteString,因为我需要在再次散列之前对其进行操作。例如,

-- myByteString is a constant
-- firstByteString is original input
finalResult = hash $ append myByteString (hash firstByteString)

===编辑2 ===

我接受了本的答案,并从中学习,但为了将来参考,将Crypto.Hash的Digest a转换为ByteString的一种方法是通过memory package's Data.ByteArray模块和pack function

module Main where

import Data.ByteString
import Data.ByteString as BS (pack)
import Data.ByteArray (ByteArrayAccess)
import qualified Data.ByteArray as BA (unpack)
import Crypto.Hash (Digest, hash)
import Crypto.Hash.Algorithms (SHA256(..))

somehash = hash ("foo" :: ByteString) :: Digest SHA256

toByteString :: ByteArrayAccess a => a -> ByteString
toByteString = BS.pack . BA.unpack

somebytestring = toByteString somehash

1 个答案:

答案 0 :(得分:3)

那里的散列函数通常需要ByteArrayAccess个实例来输入。只有hashlazy特别需要一个懒惰的ByteString

hash (hashlazy x)应该有效,因为Digest的实例为ByteArrayAccess。要将多个Digest散列在一起,您可以使用基础hashInit / hashUpdates / hashFinalize函数,将所有Digest传递给hashUpdates

快速举例:

import System.IO
import Crypto.Hash
import Crypto.Hash.Algorithms
import Data.ByteString.UTF8 as B

main = do
  putStr "Enter something to hash: " >> hFlush stdout
  line1 <- fmap B.fromString getLine
  let hash1 = hash line1 :: Digest SHA512
  putStrLn $ "First hash is " ++ show hash1
  putStr "Enter something else to hash: " >> hFlush stdout
  line2 <- fmap B.fromString getLine
  let
    ctx1 :: Context SHA512
    ctx1 = hashInit
    ctx2 = hashUpdate ctx1 hash1
    ctx3 = hashUpdate ctx2 line2
    hash2 = hashFinalize ctx3
  putStrLn $ "Second hash is " ++ show hash2

给出:

Enter something to hash: foo
First hash is f7fbba6e0636f890e56fbbf3283e524c6fa3204ae298382d624741d0dc6638326e282c41be5e4254d8820772c5518a2c5a8c0c7f7eda19594a7eb539453e1ed7
Enter something else to hash: bar
Second hash is b612043d657248615f4c184407f4e5bfc0e6334f86056dfb641cf35ce1e33d86e5349d8e82b3b5018adb07e6b6d653d288e9ed883af624e7f34f12117a620c00

验证

 $ (echo -n foo | sha512sum | head -c 128 | xxd -p -r ; echo -n bar) | sha512sum
 b612043d657248615f4c184407f4e5bfc0e6334f86056dfb641cf35ce1e33d86e5349d8e82b3b5018adb07e6b6d653d288e9ed883af624e7f34f12117a620c00  -

编辑2:请注意,如果您确实需要操作作为字节数组获取的摘要,则可以使用BytesArrayAccess类上的操作,或转换为常规旧严格ByteString从那里开始。