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

时间:2015-03-09 07:37:45

标签: string haskell hash hex sha

我需要HEX格式的字符串的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

有什么想法吗?

2 个答案:

答案 0 :(得分:3)

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

假设您正在使用cryptohash包,获取十六进制表示的最佳方法是使用Crypto.Hash中的函数,类似这样:

import Crypto.Hash

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

答案 1 :(得分:2)

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

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

如果你坚持使用Text代替String(我建议),你可以不用unpackpack