使用Peter Weinberger的Hash算法创建加密/解密函数

时间:2013-01-12 09:37:02

标签: c++ encryption hash cryptography

是否有可能解密Peter Weinberger的Hash算法?

我正在尝试编写自己的Encrypt Decrypt函数。我理解哈希值意味着你不能或不应该解密哈希值的概念,但我认为因为算法相对简单,在这种情况下可能解密这种哈希。我已经完成了使用简单旋转的简单加密解密,现在我想尝试更困难的事情。

那么可以解密Peter Weinberger的哈希算法产生的哈希值吗?

以下加密函数是Peter Weinberger的精确哈希算法,解密是我自己的尝试,但不起作用:

int encrypt(char *s)
{
    /* Peter Weinberger's */

    char *p;
    unsigned int h, g;
    h = 0;
    for(p=s; *p!='\0'; p++){
        h = (h<<4) + *p; printf("Step : ");
        if (g = h&0xF0000000) {
            h ^= g>>24;
            h ^= g;
        }
    }
    return h % 211;
}

std::string decrypt(int v)
{
    /* Peter Weinberger's */

    unsigned int h, g;
    h = 0;
    v /= 211;
    int s = sqrt(v);

    /* Not sure what to do here
    for(p=s; *p!='\0'; p++){

    }
    */

    return string(h);
}

2 个答案:

答案 0 :(得分:3)

考虑到极小的输出尺寸,蛮力攻击是微不足道的。

  1. 生成一个字符串(例如随机)
  2. 哈希吧
  3. 如果匹配已知值,则找到第一个预映像,否则转到步骤1
  4. 这将平均需要211次尝试才能获得与给定哈希匹配的字符串。它可能不会是原始字符串,但考虑到散列的有损性质,这是可以预期的。


    对于两个字符输入,此哈希变为(16*s[0]+s[1])%211,您可以将其重写为(16*(s[0]-'A')+(s[1]-'A') + 50)%211

    解决你得到的字符串:

    s[0]=(hash+161)/16+'A';
    s[1]=(hash+161)%16+'A';
    

    例如,对于s == "AB",您获得hash==51。然后使用上面的公式来反转它:

    s[0] = 13 +'A' = 'N'
    s[1] =  4 +'A' = 'E'
    

    =&GT; s="NE"与哈希51匹配,但不是原始字符串。

答案 1 :(得分:0)

如果我正确理解算法,则对每个字符都这样做:

  1. 将哈希乘以16(向左移动4位)
  2. 添加字符串
  3. 的字符
  4. 如果结果超过28位,则删除高4位并将其与散列中的某处进行异或。
  5. 通过将字符串限制为大小为6(如果第一个字节小于16,则为7),将永远不会发生步骤3。所以剩下的就是一个简单的移位和添加。

    当字符串有6个字符时,最终结果是这个总和(h =字符的高4位,l =低4位):

    pos: bits
    0: .hl00000
    1: ..hl0000
    2: ...hl000
    3: ....hl00
    4: .....hl0
    5: ......hl
    ----------- +
       0*******  Result is 32 bits with upper 4 bits zero
    

    我们看到位24-27由位置0处字符的高4位确定,加上低位中加法的可能进位。第20-23位是char 0的低位和char 1的高位(加上可能的进位)的总和。

    如果输入字符可以包含所有255个可能值(零除外),则创建生成哈希值的字符串并不难。

    1. 查看哈希中的最高4位。这将是pos 0角色的重要部分。
    2. 查看哈希中的下4位。这是char 1的高位部分和char 0的下半部分的添加。
    3. 选择最高部分的值。例如。 “最高部分始终为零”或“最高部分始终为0100(大写字母)”。
    4. 如果has中的位小于您在步骤3中选择的值,则从先前的位中借用一些(如果这些位为零,则将其波动到下一位组)。
    5. 现在你有char 0的下半部分和char 1的高位。
    6. 返回步骤2接下来的4位,直到到达散列结尾
    7. 检查字符串中是否没有值为0的字符。
    8. 代码会更复杂,因为存在各种边缘情况(例如散列01000000),并且留给读者作为练习;)。

      编辑:我完全错过了h % 211操作。这使得它变得更加容易,正如CodesInChaos演示的那样。