2016-09-18 6 views
1

Crypto.Hash module(クリプトンパッケージ)を使用して「ハッシュのハッシュ」結果を生成しようとしています。クリプトンパッケージのハッシュ関数のハッシュ

問題は、モジュールのハッシュ関数の署名がhashlazy :: HashAlgorithm a => ByteString -> Digest aであるため、hashlazy (hashlazy x)を生成する前に、ダイジェストを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 ...

を行うことができますしかし、それは非常に面倒になります。

だから私が見つけた唯一の方法は、これを行うことです。

私の質問:ライブラリ機能を正しく使用していますか?私はどこかで変換関数が欠けていましたか?あるいは私は物事を違うようにすべきですか?

=== EDIT 1 ===

私は、単純な私の質問を維持したいと私は重要ではないと思っていたその他の詳細を避けたが、私のように、延ByteStringに戻すハッシュ結果を変換する必要があります私は再びハッシュする前にそれを操作する必要があります。例えば、

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

=== EDIT 2 ===

私はベンの答えを受け入れて、それから学んだが、今後の参考のために、ByteStringにCrypto.HashのDigest aを変換する一つの方法がある経由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

'cryptonite 'は暗号化された**プリミティブです** library_ - 生のバイナリデータからハッシュを計算しますが、実際にハスケル値をハッシュするためのインターフェイスを提供するようには思えません。その目的のためにあなたの好きなシリアライゼーションライブラリと組み合わせなければならないという考えがあると思います。 ['cereal'](http://hackage.haskell.org/package/cereal)。また、あなたのようなアプリケーションをターゲットとするような[crypto-simple']ライブラリ(http://hackage.haskell.org/package/crypto-simple)もあります。 – leftaroundabout

答えて

2

一般に存在ハッシュ関数は、それらの入力のためにByteArrayAccessインスタンスを必要とします。特にhashlazyには、特に怠け者ByteStringが必要です。 DigestのインスタンスがByteArrayAccessであるため、

hash (hashlazy x)が有効です。 Digestを複数ハッシュするには、基底のhashInit/hashUpdates/hashFinalize関数を使用し、すべてDigesthashUpdatesに渡します。

クイック例:

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クラスの操作を使用するか、通常の古いstrict 012に変換できますそこからが出ます。

+0

ありがとう、それは完全に正しいと私はチェックしている必要がありますが、私はダイジェストをストレートハッシングよりも少し多くする必要があるということです。たとえば、ハッシュを取得する前に、指定されたByteStringを連結する必要があります。例えば、 'hash(append someBstring hash firstBstring)'のようなものです。私は私の質問を更新します。 – Janthelme

+0

'hashUpdate'を複数回呼び出すことができます。前のハッシュからのダイジェストに1回、余分なバイトストリングで1回です。 – ben

+0

ありがとうございます。私は 'hasUpdate'関数を正しく理解しているとは思わない。前のハッシュの結果に、指定されたByteStringの連結をハッシュするために、それをどのように使うべきですか?前のハッシュの結果をByteStringに変換する必要はありませんか? – Janthelme