【问题标题】:Find a hash encryption input from an output从输出中查找哈希加密输入
【发布时间】:2021-11-23 14:39:13
【问题描述】:

我有这个函数hash() 将给定的字符串加密为整数。

letters = 'weiojpknasdjhsuert'

def hash(string_input):
  h = 3

  for i in range(0, len(string_input)):
    h = h * 43 + letters.index(string_input[i])

  return h

所以如果我做print(hash('post')),我的输出是:11231443

如果输入只能是来自letters 的字符串,我如何才能找到我的输入才能获得像1509979332193868 这样的输出?循环体内有一个公式,但我不知道如何反转它。

【问题讨论】:

  • 只是为了直截了当地使用的术语,请看Fundamental difference between Hashing and Encryption algorithms
  • 我不认为公式是可逆的,甚至可能是多个字符串哈希到相同的值。
  • 那么我怎样才能知道输入可以得到一个单一的输出呢?
  • @Barnar 如果它是一个完全由一系列字符中的字符组成的字符串怎么办?
  • @Mark 已修复。字母其实是chars

标签: python algorithm encryption hash


【解决方案1】:

似乎因为 43 比你的字母表大,你可以把数学倒过来。我不知道如何证明没有哈希冲突,所以这可能有边缘情况。例如:

letters = 'weiojpknasdjhsuert'

def hash(string_input):
    h = 3

    for i in range(0, len(string_input)):
        h = h * 43 + letters.index(string_input[i])

    return h

n = hash('wepostjapansand')
print(n)
# 9533132150649729383107184

def rev(n):
    s = ''
    while n:
        l = n % 43  # going in reverse this is the index of the next letter
        n -= l      # now reverse the math...subtract that index
        n //= 43    # and divide by 43 to get the next n
        if n:
            s = letters[l] + s
    return s

print(rev(n))
# wepostjapansand

使用更合理的字母表,如小写 ascii 和空格,这似乎还可以:

from string import ascii_lowercase 

letters = ascii_lowercase + ' '

def hash(string_input):
    h = 3

    for i in range(0, len(string_input)):
        h = h * 43 + letters.index(string_input[i])

    return h

n = hash('this is some really long text to test how well this works')
print(n)
# 4415562436659212948343839746913950248717359454765313646276852138403823934037244869651587521298

def rev(n):
    s = ''
    # with more compact logic
    while n > 3:
        s = letters[n % 43] + s
        n = (n - (n % 43)) // 43
    return s

print(rev(n))
# this is some really long text to test how well this works

基本思想是,经过所有的数学运算,最后一个数字是:

prev * 43 + letter_index

这意味着您可以通过取 prev 模数 43 来恢复最终字母索引。然后将其减去并除以 43(这只是数学的逆运算)并再次执行此操作,直到您的数字为零。

【讨论】:

  • 我没有注意到alphabet这么小,我以为它会包含所有大小写字母,所以至少52个字符,比43大。
  • 您的第一个 def rev(n) 确实有效。你介意解释一下你的逻辑吗?
  • 是的,@Barmar,我认为这是正确的。对于所有大写和小写字母,这似乎适用于更大的倍数,例如 59
  • @oo92,我在最后添加了一些解释...希望对您有所帮助。
  • 我很好奇:为什么初始值h = 3没有出现反面?
猜你喜欢
  • 1970-01-01
  • 2021-06-26
  • 2012-01-13
  • 2020-12-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多