cryptonite 包中散列函数的散列
Hash of hash functions in cryptonite package
我正在尝试使用 Crypto.Hash module(cryptonite 包)并生成 "hash of hash" 结果。
问题是模块的哈希函数的签名是 hashlazy :: HashAlgorithm a => ByteString -> Digest a
,因此在我生成 hashlazy (hashlazy x)
之前,我需要将 Digest 转换为 ByteString。
虽然提供了digestFromByteString 函数,但没有这样的函数用于反向(也许它对所有摘要都没有意义?)。
所以我找到的唯一方法就是这样做:
-- 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 ===
我接受了 ben 的回答,并从中吸取了教训,但为了将来参考,将 Crypto.Hash 的 Digest a
转换为 ByteString
的一种方法是通过 memory package's Data.ByteArray module and the 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
那里的哈希函数通常需要一个 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
class 上的操作,或转换为常规旧的从那里严格 ByteString
s。
我正在尝试使用 Crypto.Hash module(cryptonite 包)并生成 "hash of hash" 结果。
问题是模块的哈希函数的签名是 hashlazy :: HashAlgorithm a => ByteString -> Digest a
,因此在我生成 hashlazy (hashlazy x)
之前,我需要将 Digest 转换为 ByteString。
虽然提供了digestFromByteString 函数,但没有这样的函数用于反向(也许它对所有摘要都没有意义?)。
所以我找到的唯一方法就是这样做:
-- 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 ===
我接受了 ben 的回答,并从中吸取了教训,但为了将来参考,将 Crypto.Hash 的 Digest a
转换为 ByteString
的一种方法是通过 memory package's Data.ByteArray module and the 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
那里的哈希函数通常需要一个 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
class 上的操作,或转换为常规旧的从那里严格 ByteString
s。