Hash 唯一整数到整数散列

Hash 唯一整数到整数散列,hash,Hash,我很好奇是否有一些简单和/或众所周知的哈希方法具有以下属性: 它将一个32位整数转换为另一个32位整数 没有两个不相等的输入产生相同的输出 从输出来看,两个输入是相似的(在差异和位掩码方面),这并不明显,这意味着散列(a)和散列(a+1)应该有非常不同的输出,散列(a)和散列(a&0x100000)也应该如此。(这排除了使用随机值进行简单的XOR运算。) 虽然这样的系统在理论上肯定存在,但在实践中有吗?一个简单的解决方案是制作一个位序变换数组。一些加密函数基于此方法 uint8_t arr[32

我很好奇是否有一些简单和/或众所周知的哈希方法具有以下属性:

  • 它将一个32位整数转换为另一个32位整数
  • 没有两个不相等的输入产生相同的输出
  • 从输出来看,两个输入是相似的(在差异和位掩码方面),这并不明显,这意味着散列(a)和散列(a+1)应该有非常不同的输出,散列(a)和散列(a&0x100000)也应该如此。(这排除了使用随机值进行简单的XOR运算。)

  • 虽然这样的系统在理论上肯定存在,但在实践中有吗?

    一个简单的解决方案是制作一个位序变换数组。一些加密函数基于此方法

    uint8_t arr[32]={4,7,24,9,15,3,...}; // an order you know
    uint32_t orgVal;
    uint32_t modVal =0;
    uint32_t pos = 1;
    
    for (int i=0; i<32;i++) {
      modVal += (orgVal&pos)? (1>>arr[i]):0;
      pos*=2;
    }
    
    uint8_t arr[32]={4,7,24,9,15,3,…};//你知道的命令
    uint32组织;
    uint32_t modVal=0;
    uint32_t pos=1;
    对于(int i=0;i>arr[i]):0;
    pos*=2;
    }
    
    (代码是从头开始编写的,没有IDE或测试;它可能无法工作)


    正如注释中所指出的,如果您查看位,差异将是最小的:0和1的数量将是相同的。为了解决这个问题,可以考虑使用<强>位顺序更改和XOR <强>。然后,原始值和结果值之间的差异将更加显著。

    尝试反转数字的二进制表示:

    17(10) = 1110(2) -> 10111(reversed, set first bit as indicator) = 23
    18(10) = 10010(2) -> 101001 = 41
    
    或将前半位与后半位交换:

    17(10) = 11|10(2) -> 1011 = 11
    18(10) = 100|10(2) -> 10100 = 20
    

    我不确定,但它似乎适合您。

    这一个很简单,但可能不是很有效:

    • 随机排列所有32位整数
    • 保存(相当大的)表

    现在您可以用两种方法来应用它,只有那些使用表的人才能知道数字应该是什么。

    一种简单的方法:
    hash(x)=rotate shl(x,K1)xor C


    您可以组合几个简单的操作来获得更多的“随机”结果,如旋转shl/shr,
    位反转
    异或
    等等。

    实践中有很多

    一个简单的解决方案是将输入乘以任意奇数,然后取结果的底部32位。即:

    y = (x * YOUR_ODD_NUMBER) & 0xffffffff;
    
    不过,这确实有一些弱点。它总是将零映射到零,如果选择像3这样的小数字,则映射将相当明显(类似地,如果选择像0xffffffff这样的大数字,则会得到另一个明显的映射),并且最低有效位不变。通常,低位会影响高位,但高位不会影响低位

    另一种方法是使用自身的移位版本多次对数字进行异或:

    x ^= x >> YOUR_FIRST_SHIFT;
    x ^= x << YOUR_SECOND_SHIFT;
    y = x ^ (x >> YOUR_THIRD_SHIFT);
    
    x^=x>>您的第一次换班;
    x^=x>你的第三班);
    
    您可以将这些琐碎的操作叠加到任意数量,以试图隐藏各个阶段的弱点。即使一个操作本身不是很好,它也可以在更复杂的操作链中发挥有益的作用。例如,具有某个常数的异或将避免仅通过乘法将零映射到零的问题,移位和异或技术允许低位受高位的影响

    如果你仔细观察,你会发现它们中的很多都有一个与它们的状态几乎相同大小的周期。它们通过按照您指定的方式排列它们的状态来实现这一点——通过1:1映射,其中一个状态和下一个状态之间的关系不太明显——然后它们将该状态的某些(或全部)表示为伪随机数。一些PRNG和哈希也会在一个缓和阶段结束,在这个阶段,它们会执行另一个映射来隐藏自己的一些弱点

    如果在循环中运行hash函数,在每次迭代时将y反馈回x,那么就有了一个PRNG,可以使用类似的工具测试它的随机性


    并非所有PRNG都具有理想的长周期属性,并且该属性对于一个好的散列函数来说不是必需的,但是一些PRNG算法可以成为执行操作的有用思想来源,并且它们带有全面的分析。

    听起来更像是加密而不是散列,特别是因为(2)。没错,听起来你想要的是32位分组密码。是的,我不太愿意把任何双射函数称为散列。你要的是一个32位的分组密码,可能是Skip32。你的问题让我想到了或者,更安全的。32位而不是64位的输入和输出可能是一个问题,尽管为32位派生一个类似的过程可能并不太困难。我不确定您的目标是什么,但您可能会对这一it安全性感兴趣。
    hash(2)
    hash(3)
    仍然只有1位不同,这可能是“明显的”这取决于您对结果值的看法。@JoachimSauer从技术上讲,两位是不同的。哈希(2)和哈希(3)是一个更好的例子。@JoachimSauer aa我明白你的意思了。是的,你说得对。@Smallhacker:是的,修复了我的评论。仅供参考(假设我的计算是正确的),这个表中需要2^32个条目,每个条目有4个字节,因此,需要2^34=17179869184字节=16 TB的存储空间。同时,对16 TB的数据进行洗牌也可能需要相当多的努力。@Dukeling这显然不是一件可以随时进行的事情,但有了好的硬件,创建应该(只是)可以管理。表的使用应该相当快。@Dukeling,我想你是说16GB。@sh1哎呀,是的,看来你是对的。虽然不是不可行,但仍然有很多。因为我刚刚发布了一个链接,用于一个更具体的应用程序,我应该补充一点,我通过将乘法与标准位反转变换(交换位31和0,交换位30和1,等等)混合,获得了良好的分布特性。