如何反转此算法以取回原始文本?

时间:2010-08-22 10:35:36

标签: vb.net algorithm reverse-engineering checksum

任何人都可以用简单的编码解释如何反转这个算法,以便我找回原始文本字符串?

Public Function CreateIntChecksum(ByVal s As String) As Integer
    Dim r As Integer = 0
    For i As Integer = 0 To (s.Length() - 1)
        Dim bchar As Byte = Convert.ToByte(s(i))
        r = bchar + ((r << 5) - r)
    Next
    Return r
End Function

6 个答案:

答案 0 :(得分:4)

虽然无法找到原始文本,但可以轻松找到原像。关键点是

r = bchar + ((r << 5) - r)

相当于

r = bchar + r*31

因此,哈希对base-31中的字符串进行编码。要查找preimage,只需重写基数31中的整数。

例如,如果结果是3456,我们知道3456 = 3×31 2 + 18×31 + 15,因此一个可能的原始文本是“\x03\x12\x0f”。当然,我们可以重新排列数字以给出110×31 + 46(“n.”)或109×31 + 77(“mM”)等,这表明没有唯一的原像。 / p>

答案 1 :(得分:2)

  

如何反转此算法以便我返回原始文本字符串?

你不能,按设计。
这是一个(简单的)校验和或散列函数。

查看输入和输出信息的大小:该函数将任意长度的字符串s转换为32位整数。对于每个整数值,将有许多输出字符串将产生该结果。


编辑:显然你想要一个改组算法。也许看看ROT13。请注意,这不是一种(非常)安全的加密形式。

答案 2 :(得分:2)

你做不到。你在这里有一个Checksum,它是一个基本的散列函数。散列函数的整个 point 是不可逆的。散列函数将一组输入(通常是无限的)映射到较小的输出集 - 因此多个输入可以以相同的输出结束,因此这使得无法反转散列(假设正确完成散列)。这就是为什么它们用于存储密码 - 没有办法读取哈希并去“哦,这是密码XYZ”。

尝试找出原始值的一种方法是使用彩虹表。这只是一个庞大的输入表及其等效哈希(或在这种情况下是校验和)值。如果您具有未知字符串的散列值,则可以在表中搜索它并获取可能的输入集。这不是一种反转哈希函数的方法,这是不可能的;它只是一种蛮力猜测方法。另请注意,在这种情况下(假设散列函数没有偏差),每个校验和值都有无限数量的字符串,因为视觉基本string可以是任意长度。这会使得彩虹表非常不实用 - 你可以覆盖散列的可能输入集(因为大多数普通用户不会输入超过10个字符的代码),但没有什么能阻止用户使用67个字符的代码,或109,或......

阅读Hash FunctionsChecksumsRainbow Tables的维基百科文章。

答案 3 :(得分:1)

你根本无法逆转它。这是一个不可逆的校验和。

答案 4 :(得分:0)

你做不到。如果没有别的,那么只是因为Integer只包含32位数据而String可以有任何长度。

答案 5 :(得分:0)

首先,发布的代码将抛出除最短字符串之外的任何内容。

以下代码包括OP的原始代码,加上一个简单的校验和,以及猜测如何使用校验和。

Private Sub Button2_Click(ByVal sender As System.Object, _
                          ByVal e As System.EventArgs) Handles Button2.Click

    Dim buffer() As Byte

    Dim tstString As String = "Calculate a checksum for a given string"

    Dim chkSumFix As Integer = CreateIntChecksumFixed(tstString) 'get a checksum

    buffer = SendPacket(tstString, chkSumFix) 'create a byte buffer to send
    tstString = decodePacket(buffer)

    'do the same using the OP's original code
    Dim chkSum As Integer = CreateIntChecksum(tstString) 'error

    buffer = SendPacket(tstString, chkSum)
End Sub

'OP
Public Function CreateIntChecksum(ByVal s As String) As Integer
    Dim r As Integer = 0
    For i As Integer = 0 To (s.Length() - 1)
        Dim bchar As Byte = Convert.ToByte(s(i))
        r = bchar + ((r << 5) - r)
    Next
    Return r
End Function

'a very simple checksum
Public Function CreateIntChecksumFixed(ByVal s As String) As Integer
    Dim r As Integer = 0
    For i As Integer = 0 To (s.Length() - 1)
        Dim bchar As Byte = Convert.ToByte(s(i))
        r = (r And &HFFFF) + bchar
    Next
    Return r
End Function

Private Function SendPacket(ByVal aString As String, _
                            ByVal aChecksum As Integer) As Byte()
    'construct a packet to be sent
    'Packet format
    'returns a byte buffer
    'byte(0 -3) = length of original string - use BitConverter.ToInt32 to extract
    'byte(4-n) = original string.  n = (4 + string length) - 1
    'byte(n + 1, n + 2, n + 3, n + 4) = checksum

    Dim length As Integer
    Dim retV As New List(Of Byte)
    retV.AddRange(System.Text.Encoding.ASCII.GetBytes(aString)) 'add string to packet
    length = retV.Count 'get length - use this length in case a different encoding is used
    retV.AddRange(BitConverter.GetBytes(aChecksum)) 'add checksum
    retV.InsertRange(0, BitConverter.GetBytes(length)) 'insert length at start of packet

    Return retV.ToArray
End Function

Private Function decodePacket(ByVal buffer As Byte()) As String
    Dim sLen As Integer = BitConverter.ToInt32(buffer, 0)
    If sLen + 8 <> buffer.Length Then Throw New ArgumentOutOfRangeException

    Dim s As String = System.Text.Encoding.ASCII.GetChars(buffer, 4, sLen)

    Dim chksum As Integer = CreateIntChecksumFixed(s)

    Dim embeddedChecksum As Integer = BitConverter.ToInt32(buffer, sLen + 4)

    If chksum <> embeddedChecksum Then Throw New ArgumentException("Invalid checksum")
    Return s
End Function