我正在尝试使用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
答案 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
从那里开始。