【问题标题】:Simple encryption - Sum of Hashes in C简单加密 - C 中的哈希总和
【发布时间】:2012-06-12 16:03:23
【问题描述】:

我正在尝试针对用 C 编写的游戏中的一段代码中的漏洞演示一个简单的概念证明。

假设我们要验证字符登录。登录由用户从图形菜单中选择n 项目(我们现在假设n=5)处理。这些物品都是中世纪的主题:

例如:

 _______________________________
|           |           |       |
| Bow       | Sword     | Staff |
|-----------|-----------|-------|
| Shield    | Potion    | Gold  |
|___________|___________|_______|

用户必须点击每个项目,然后为每个项目选择一个数字。

验证算法然后执行以下操作:

  1. 确定选择了哪些项目
  2. 将每个字符串删除为小写(即:Bow 变为 bow 等)
  3. 为每个字符串计算一个简单的字符串哈希(即:`bow => b=2, o=15, w=23, sum = (2+15+23=40)
  4. 将哈希乘以用户为相应项目选择的值;这个新值称为key
  5. 将每个选定项目的keys 相加;这是最终的验证哈希
  6. 重要提示:验证器将接受此哈希以及它的非零倍数(即:如果最终哈希等于 1111,则 2222、3333、8888 等也是有效的)。

例如,假设我选择:

Bow (1)
Sword (2)
Staff (10)
Shield (1)
Potion (6)

该算法将这些字符串中的每一个都删除为小写,计算它们的字符串哈希,将该哈希乘以为每个字符串选择的数字,然后将这些键相加。

例如:

Final_Validation_Hash = 1*HASH(Bow) + 2*HASH(Sword) + 10*HASH(Staff) + 1*HASH(Shield) + 6*HASH(Potion)

通过应用欧拉方法,我打算证明这些哈希不是唯一的,并想设计一个简单的应用程序来证明它。

就我而言,对于 5 个项目,我基本上会尝试计算:

(B)(y) = (A_1)(x_1) + (A_2)(x_2) + (A_3)(x_3) + (A_4)(x_4) + (A_5)(x_5)

地点:

B is arbitrary
A_j are the selected coefficients/values for each string/category
x_j are the hash values for each string/category
y is the final validation hash (eg: 1111 above)
B,y,A_j,x_j are all discrete-valued, positive, and non-zero (ie: natural numbers)

有人可以帮助我解决这个问题或给我指出一个类似的例子(例如:代码、计算出的方程式等)吗?我只需要解决最后一步(即:(B)(Y)= ...)。


最后,我编写了一个递归算法,该算法深入n 级别,然后处理所有剩余可能组合的递增、测试等。效率不是很高,但它确实有效。我可以根据要求提供(太大,无法在此处发布)。

【问题讨论】:

  • 已更新。好点子。谢谢。 +1
  • 您在实施时遇到了哪些问题?
  • 您是否需要证明以这种方式生成的哈希对于所选字符串不会是唯一的?
  • 我唯一想不通的是总和本身的计算。我尝试了矩阵代数,但它并不像我想象的那么简单,尤其是要求所有系数都是正数且非零(即:非平凡解)。
  • @phoxis:没错。我需要证明哈希是非唯一的,并且我可以快速生成重复的哈希。

标签: c algorithm math linear-algebra discrete-mathematics


【解决方案1】:

在我看来,大多数用户会为每个项目选择相当小的数字(毕竟“2”比“438483”更容易记住)。

鉴于这种限制,蛮力可能实际上是合理的。

只需为 5 个符号生成所有可能的输入值加上一个 1..99 范围内的数字,计算生成的哈希值,并计算(例如使用字典)产生给定哈希值的不同组合的数量应该对最可能的输入值的哈希分布给出经验性的理解。

从那里我将查看实际生成了多少不同的哈希值(如果哈希是 Int32,则在 2^32 个可能的哈希值中),并查找以特定频率生成的哈希值(在字典中有很高的计数)。

【讨论】:

  • 直到现在我才这么想。谢谢! +1;接受
  • :-) 前段时间我做了类似的事情,使用具有 100m 真实输入值的 CityHash 寻找碰撞率。有时,大锤实际上是最实用的工具。
【解决方案2】:

它可能是唯一的,也可能不是唯一的,具体取决于菜单上的项目x_j、系数A_j、验证哈希y,以及所选项目的数量n

例如,如果您的验证哈希是1,会发生什么?然后一切都会验证。

另一方面,如果您的项目总数为 n,那么只有一个可能的哈希值是唯一的。

当然,这些都是极端的例子,但它们说明了这一点。这取决于你的参数。除了暴力破解之外,没有一种简单的通用方法可以检测哈希是否唯一。

【讨论】:

    【解决方案3】:

    这很简单,因为该算法接受非零倍数。如果将所有输入乘以 2,则会发生冲突:

    Bow (1)
    Sword (2)
    Staff (10)
    Shield (1)
    Potion (6)
    
    y = (A_1)(x_1) + (A_2)(x_2) + (A_3)(x_3) + (A_4)(x_4) + (A_5)(x_5)
    

    然后将它们乘以 2:

    Bow (2)
    Sword (4)
    Staff (20)
    Shield (2)
    Potion (12)
    
    2(A_1)(x_1) + 2(A_2)(x_2) + 2(A_3)(x_3) + 2(A_4)(x_4) + 2(A_5)(x_5)
    = 2((A_1)(x_1) + (A_2)(x_2) + (A_3)(x_3) + (A_4)(x_4) + (A_5)(x_5))
    = 2y
    

    【讨论】:

    • 这是一个小例子;我需要更改 A_j 和 x_j。
    【解决方案4】:

    虽然不是正式证明,但我有一个想法。

    让不同字符串的哈希为h_1h_2、...、h_n,线性和为

    y = h_1 + h_2 + ... + h_n

    一旦我们有了y,我们总能在系列中找到h_1'h_2'、...、h_n',这样至少有一对ijh_i != h_j'

    所以我们可以有重复的h 值来得到最终的总和。

    再次,由于每个h值都是由一些整数(字符的代表值)的线性和生成的,因此可以通过不同的线性和,即不同的字符串来获得特定的h值。

    乘数值可以调整。此外,即使乘数是常数,即重复哈希生成器无法选择它,也可以修改与乘数相乘的h 值,使相乘键的总和保持不变。

    因此我们可以从多个字符串中生成一个哈希。

    【讨论】:

      【解决方案5】:

      将除最后一个系数之外的所有系数都设置为 1,这样您就得到了 An*xn = r (mod y) 形式的东西,然后使用扩展欧几里得算法找到解决方案,请参阅 Wikipedia

      【讨论】:

        猜你喜欢
        • 2020-08-08
        • 1970-01-01
        • 2020-12-08
        • 2017-09-19
        • 2010-09-20
        • 2016-03-20
        • 2011-01-09
        相关资源
        最近更新 更多