2015-06-22 95 views
1

我寫一個程序來在Haskell執行SHA-1,而它確實產生散列,它們不與其他SHA-1方案SHA-1在Haskell產生錯誤哈希

實施例中製造的那些相匹配: cat 散列到:b5be86bc8bccfc24b01b093228ebb96fc92fa804,但應該散列到9d989e8d27dc9e0ec3389fc855f142c3d40f0c50

我的代碼是:

(old code omitted) 

我不知道什麼是錯的。有人能告訴我我犯了什麼錯誤嗎?

編輯︰ 我修正了指出的東西,但它仍然無法正常工作。它直到內部循環才能正常工作。 我清理了代碼,因此內循環的函數可用爲f1,f2f3 cat現在有趣地哈希到ebe6c9fa1afa0ef5a0ca80bab251fd41cc29127e

代碼:

import Data.Word 
import Data.Bits 
import Data.Char (ord, intToDigit) 
import Data.Binary (encode, decode) 
import Numeric (showHex, showIntAtBase) 
import System.IO (stdin) 
import Data.Sequence ((<|), (|>)) 
import qualified Data.Sequence as S 
import qualified Data.ByteString.Lazy as B 
type Quintuple32 = (Word32, Word32, Word32, Word32, Word32) 

addQuintuple (a, b, c, d, e) (f, g, h, i, j) = 
    (a + f, b + g, c + h, d + i, e + j) 

shower :: Quintuple32 -> String 
shower (a, b, c, d, e) = concatMap (`showHex` "") [a, b, c, d, e] 

hash :: Int -> S.Seq Word32 -> Quintuple32 -> Quintuple32 
hash i w [email protected](a, b, c, d, e) 
    | i < 20 = hash (i + 1) w (newhash (f1 h + k1)) 
    | i < 40 = hash (i + 1) w (newhash (f2 h + k2)) 
    | i < 60 = hash (i + 1) w (newhash (f3 h + k3)) 
    | i < 80 = hash (i + 1) w (newhash (f2 h + k4)) 
    | otherwise = h 
    where (k1, k2, k3, k4) = (0x5A827999, 0x6ED9EBA1, 0x8F1BBCDC, 0xCA62C1D6) 
     newhash a' = (rotate a 5 + a' + e + (w `S.index` i), a, rotate b 30, c, d) 

f1 :: Quintuple32 -> Word32 
f1 (_, b, c, _, _) = (b .&. c) .|. (complement b .&. c) 

f2 :: Quintuple32 -> Word32 
f2 (_, b, c, d, _) = b `xor` c `xor` d 

f3 :: Quintuple32 -> Word32 
f3 (_, b, c, d, _) = (b .&. c) .|. (b .&. d) .|. (c .&. d) 

starting :: Quintuple32 
starting = (0x67452301 
      , 0xEFCDAB89 
      , 0x98BADCFE 
      , 0x10325476 
      , 0xC3D2E1F0) 

hasher :: Quintuple32 -> S.Seq Word32 -> Quintuple32 
hasher acc x = addQuintuple acc (hash 0 (extend x) acc) 

process :: B.ByteString -> Quintuple32 
process = foldl hasher starting . chunks . pad 

extend :: S.Seq Word32 -> S.Seq Word32 
extend = extend' 16 

extend' :: Int -> S.Seq Word32 -> S.Seq Word32 
extend' 80 a = a 
extend' i a = extend' (i + 1) (a |> xored) 
    where xored = rotate ((a `S.index` (i - 3)) `xor` 
         (a `S.index` (i - 8)) `xor` 
         (a `S.index` (i - 14)) `xor` 
         (a `S.index` (i - 16))) 1 

toBytes :: String -> B.ByteString 
toBytes = B.pack . map (fromIntegral . ord) 

splitEvery n xs 
    | B.null xs = S.empty 
    | otherwise = B.take n xs <| splitEvery n (B.drop n xs) 

chunks :: B.ByteString -> [S.Seq Word32] 
chunks xs 
    | B.null xs = [] 
    | otherwise = x : chunks (B.drop 64 xs) 
    where x = fmap decode (splitEvery 4 (B.take 64 xs)) 

pad :: B.ByteString -> B.ByteString 
pad xs = B.append (add0 $ add1 xs) length64 
    where length64 = encode (fromIntegral (8 * B.length xs) :: Word64) 

add1 :: B.ByteString -> B.ByteString 
add1 = flip B.append (B.singleton 128) 

add0 :: B.ByteString -> B.ByteString 
add0 xs 
    | modulo /= 448 = add0 $ B.append xs (B.singleton 0) 
    | otherwise = xs 
    where modulo = (B.length xs * 8) `rem` 512 

而且,一個小問題:是像(a, b) = (8, 9)可接受的事情來設置多個變量?

+0

爲了節省我們一些時間搞清楚你的​​代碼,你用來測試「貓」的'main'函數是什麼? – Alec

+1

@Alec'shower $ process $ toBytes「cat」' – tolUene

+2

爲那些包含大量邏輯的函數編寫測試可能會幫助您弄清楚。 – user2407038

回答

6

哦,另一個!

兩個錯誤我馬上跳出:

pad :: B.ByteString -> B.ByteString 
pad xs = B.append (add0 $ add1 xs) length64 
    where length64 = encode (fromIntegral (B.length xs) :: Word64) 

通知你追加的長度應該是位長度,而不是字節長度。

add1 :: B.ByteString -> B.ByteString 
add1 = flip B.append (B.singleton 255) 

注意事項255 /= 0b10000000和墊應該是後者。

一般來說,你可以通過1)一遍又一遍地檢查規格。 2)與另一個實現比較,比如Adam Wick的SHA包,並儘可能細化地比較平等。

編輯:還有兩個錯誤,基本上是轉錄錯誤。如果你仍然陷入困境,請環顧一下並大聲呼喊。

+0

謝謝你的回答。我修正了你所說的話以及我注意到的其他一些事情,並且直到(包括)擴展步驟,即在實際的哈希函數發生之前,它才正確地工作,但是我確實仍然卡住了。我的代碼在這裏:http://lpaste.net/4913292567711318016 – tolUene

+0

我現在沒有時間來看看這個新版本,但'哈希'功能是錯誤的(壞的名字看作是內部壓縮, SHA-1哈希函數)。從另一個SHA1實現中刪除一個'hash'版本會導致至少對於空字符串有適當的功能。您遇到了我之前看到的'c/d'命名和'移位/旋轉'問題。 –

+0

我認爲這個名字是合適的,因爲它是做實際哈希的函數。我用我更新的代碼編輯原始帖子,但我確實仍然卡住 – tolUene