【问题标题】:SHA-1 in haskell producing wrong hasheshaskell 中的 SHA-1 产生错误的哈希值
【发布时间】:2015-06-25 06:38:39
【问题描述】:

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

示例:cat 散列到:b5be86bc8bccfc24b01b093228ebb96fc92fa804,但应该散列到9d989e8d27dc9e0ec3389fc855f142c3d40f0c50

我的代码是:

(old code omitted)

我不知道出了什么问题。谁能告诉我哪里出错了?

编辑: 我修复了指出的东西,但它仍然无法正常工作。它可以正常工作,直到内部循环。 我清理了代码,因此内部循环的函数可用作f1f2f3 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

还有一个小问题:像(a, b) = (8, 9) 这样的设置多个变量是否可以接受?

【问题讨论】:

  • 为了节省我们一些时间来弄清楚你的代码,你用来测试“cat”的main函数是什么?
  • @Alec shower $ process $ toBytes "cat"
  • 为那些包含大量逻辑的函数编写测试可能会帮助你弄清楚。

标签: haskell hash sha1


【解决方案1】:

哦,还有一个!

两个错误立即跳出来:

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,pad 应该是后者。

通常,您通过 1) 一次又一次地检查规范来调试这些。 2) 与其他实现进行比较,例如 Adam Wick 的 SHA 包,并在尽可能细粒度的级别上比较相等性。

编辑:还有两个错误,基本上是转录错误。环顾四周,如果您仍然卡住,请大声喊叫。

【讨论】:

  • 感谢您的回答。我修复了你所说的事情和我注意到的其他一些事情,并让它正常工作直到(包括)扩展步骤,即在实际散列函数发生之前,但我仍然被卡住了。我的代码在这里:lpaste.net/4913292567711318016
  • 我现在没有时间看这个新版本,但是hash 函数是错误的(不好的名字,因为这是 SHA-1 哈希的内部压缩函数)。从另一个 SHA1 实现中删除 hash 的版本会导致至少对于空字符串具有正确的功能。您发现了我之前看到的“c/d”命名和“移位/旋转”问题。
  • 我认为这个名称是合适的,因为它是执行实际散列的函数。我用我更新的代码编辑了原始帖子,但我真的还是卡住了
  • (b .&amp;. c) .|. (complement b .&amp;. c) != (b .&amp;. c) .|. (complement b .&amp;. d)
  • 非常感谢。我不敢相信我没听懂。
猜你喜欢
  • 2016-02-03
  • 2012-11-19
  • 2013-09-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-02-03
相关资源
最近更新 更多