2015-06-22 70 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