字符串的 sha1 哈希的十六进制形式?

Hex form for a sha1 hash of a String?

我需要一个十六进制形式的字符串的 sha1 散列。这是基本代码:

import Data.ByteString.UTF8
import Crypto.Hash.SHA1 (hash)

toArgs :: String -> (String,String)
toArgs str = let h = show .  hash . fromString $ str
    in (str,h)

生成散列,但格式如下:

$ toArgs "Hejsan"
("Hejsan","\"A\CAN]]\131\168\210|\n\NUL\NAK\187j\181Q\STX\146o\fP\"")

我尝试使用 printf 将其转换为 HEX:

import Data.ByteString.UTF8
import Crypto.Hash.SHA1 (hash)
import Text.Printf (printf)

toArgs :: String -> (String,String)
toArgs str = let h = printf "%02x" $ show . hash . fromString $ str
    in (str,h)

编译成功,但执行时抛出异常:

toArgs "Hejsan"
("Hejsan","*** Exception: Printf.printf: bad argument

有什么想法吗?

printf 在 Haskell 中的特定实现不是类型安全的。您已经 运行 遇到了这个问题。 %x 说明符需要一个数字,但您传递的是一个字符串。

假设您使用的是 cryptohash 包,获得十六进制表示的最佳方法是使用 Crypto.Hash 中的函数,有点像这样:

import Crypto.Hash

sha1Hex :: ByteString -> ByteString
sha1Hex s = digestToHexByteString (hash s :: Digest SHA1)

我建议使用 base16-bytestring 包。请注意,您需要将 String 转换为 ByteString,我建议您将其作为 UTF8 编码。总而言之,这看起来像:

Data.Text.unpack . decodeUtf8 . Base16.encode . encodeUtf8 . Data.Text.pack

如果您坚持使用 Text 而不是 String(我建议这样做),您可以省略 unpackpack.