haskell中的SHA-1产生错误的哈希值

时间:2015-06-22 00:43:40

标签: haskell hash sha1

我编写了一个在haskell中执行SHA-1的程序,虽然它确实产生哈希,但它们与其他SHA-1程序生成的哈希不匹配

示例:>>> bool(0) False >>> bool(1) True >>> bool([]) False >>> bool([1,2]) True 哈希到:cat但是应该哈希到b5be86bc8bccfc24b01b093228ebb96fc92fa804

我的代码是:

9d989e8d27dc9e0ec3389fc855f142c3d40f0c50

我不知道出了什么问题。有人能告诉我哪里弄错了吗?

修改 我修复了指出的东西,但它仍然无法正常工作。它正常工作直到内循环。 我清理了代码,因此内部循环的函数可用(old code omitted) f1f2 f3现在有趣地散布到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 h@(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 是否可以设置多个变量?

1 个答案:

答案 0 :(得分: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包,并在尽可能细粒度的水平上进行比较。

编辑:还有两个错误,基本上是转录错误。如果你仍然被困住,请四处寻找并大喊。