Algorithm 整数的对称双射算法
我需要一个算法,可以做一个一对一映射(即没有冲突)的32位有符号整数到另一个32位有符号整数 我真正关心的是足够的熵,使得函数的输出看起来是随机的。基本上,我正在寻找一个类似于XOR密码的密码,但它可以生成更多任意外观的输出。安全不是我真正关心的问题,尽管默默无闻才是 为澄清目的编辑:Algorithm 整数的对称双射算法,algorithm,encryption-symmetric,block-cipher,bijection,Algorithm,Encryption Symmetric,Block Cipher,Bijection,我需要一个算法,可以做一个一对一映射(即没有冲突)的32位有符号整数到另一个32位有符号整数 我真正关心的是足够的熵,使得函数的输出看起来是随机的。基本上,我正在寻找一个类似于XOR密码的密码,但它可以生成更多任意外观的输出。安全不是我真正关心的问题,尽管默默无闻才是 为澄清目的编辑: 算法必须是对称的,这样我就可以在没有密钥对的情况下反转操作 算法必须是双射的,每个32位输入数必须生成一个32位唯一数 函数的输出必须足够模糊,只向输入中添加一个会对输出产生很大影响 预期结果示例: F(100
F(100)=98456
F(101)=-758
F(102)=10875498
F(103)=986541
F(104)=945451245
F(105)=-488554 就像MD5一样,改变一件事可能会改变很多事情
我正在寻找一个数学函数,所以手动映射整数对我来说不是一个解决方案。对于那些提问的人来说,算法的速度不是很重要。在一张大纸上画一个大圆圈。从圆圈顶部顺时针等距写入从0到MAXINT的所有整数。逆时针写入0到MININT之间的所有整数,再次等距写入。请注意,MININT位于圆底部的MAXINT旁边。现在在一张硬卡片的两面复制这个图形。将硬卡通过两个圆心固定到圆上。选择一个旋转角度,任意角度。现在您有了一个1-1映射,它满足了您的一些需求,但可能还不够模糊。解开卡片,将其翻转一个直径,任意直径。重复这些步骤(以任何顺序),直到你有一个你满意的双射 如果您一直在密切关注,用您喜欢的语言编程应该不会有什么困难
如需澄清请在评论后回复:如果您仅针对纸张旋转卡片,则该方法与您抱怨的方法一样简单。但是,当您将卡翻转过来时,对于任何
m
,映射并不等同于(x+m)mod MAXINT
。例如,如果将卡保持不旋转状态,并将其绕直径0翻转(位于钟面顶部),则1将映射为-1,2映射为-2,依此类推(x+m)mod MAXINT
仅与卡的旋转相对应。您可以使用随机生成的查找表吗?只要表中的随机数是唯一的,就可以得到一个双射映射。但它不是对称的
一个用于所有32位值的16 GB查找表可能不实用,但可以使用两个单独的16位查找表用于高位字和低位字
PS:我想你可以生成一个对称的双射查找表,如果这很重要的话。该算法将从一个空LUT开始:
+----+ +----+
| 1 | -> | |
+----+ +----+
| 2 | -> | |
+----+ +----+
| 3 | -> | |
+----+ +----+
| 4 | -> | |
+----+ +----+
拾取第一个元素,为其指定一个随机映射。若要使映射对称,请也指定反向:
+----+ +----+
| 1 | -> | 3 |
+----+ +----+
| 2 | -> | |
+----+ +----+
| 3 | -> | 1 |
+----+ +----+
| 4 | -> | |
+----+ +----+
选择下一个数字,再次分配一个随机映射,但选择一个尚未分配的数字。(即,在这种情况下,不要选择1或3)。重复此操作,直到LUT完成。这将生成一个随机双射对称映射。我将尝试在一个更简单的示例中解释我的解决方案,然后可以很容易地扩展到您的大型示例中 假设我有一个4位数字。有16个不同的值。将其视为一个四维立方体:
(来源:)
每个顶点代表这些数字中的一个,每个位代表一个维度。所以它的基本值是XYZW,其中每个维度只能有0或1。现在假设您使用不同的维度顺序。例如XZYW。每个顶点现在都更改了其编号
您可以对任意数量的维度执行此操作,只需排列这些维度即可。如果您不关心安全问题,这可能是一个很好的快速解决方案。另一方面,我不知道输出是否足够“模糊”以满足您的需要,当然,在完成大量映射后,映射可以反转(这可能是优势还是劣势,取决于您的需要)。取一个数字,乘以9,反数,除以9
123 <> 1107 <> 7011 <> 779
256 <> 2304 <> 4032 <> 448
1028 <> 9252 <> 2529 <> 281
1231107701779
256 2304 4032 448
1028 9252 2529 281
应该够晦涩的
编辑:它不是0结尾整数的双射
900 <> 8100 <> 18 <> 2
2 <> 18 <> 81 <> 9
900 8100 18 2
2 18 81 9
您始终可以添加特定规则,如:
取一个数字,除以10倍,乘以9,倒数,除以9,乘以10^x
诸如此类
900 <> 9 <> 81 <> 18 <> 2 <> 200
200 <> 2 <> 18 <> 81 <> 9 <> 900
900981182200
200 2 18 81 9 900
W00t它起作用了
编辑2:要获得更多的模糊度,可以添加任意数字,并在末尾减去
900 < +256 > 1156 < *9 > 10404 < invert > 40401 < /9 > 4489 < -256 > 4233
123 < +256 > 379 < *9 > 3411 < invert > 1143 < /9 > 127 < -256 > -129
900<+256>1156<*9>10404404019>4489<-256>4233
123<+256>379<*9>341111439>127<-256>-129
以下文章给出了4或5个映射示例,为您提供了函数,而不是构建映射集:使用任何32位分组密码!根据定义,分组密码以可逆的方式将其范围内的每个可能的输入值映射到唯一的输出值,并且根据设计,很难确定没有密钥的任何给定值将映射到什么。只需选择一个密钥,如果安全性或隐蔽性很重要,则将其保密,并使用密码作为转换
要将这个想法扩展到非2次方范围,请参阅我在上的帖子
解决您的具体问题:
I: 0111 O: ____
_
I: 0_11 O: 1___
_
I: 0__1 O: 11__
_
I: ___1 O: 110_
_
I: ____ O: 1101
void Main()
{
var clearText = Enumerable.Range(0, 10);
var key = new[] { 10, 20, Int32.MaxValue };
var cipherText = Encode(clearText, key);
var clearText2 = Decode(cipherText, key);
}
IEnumerable<Int32> Encode(IEnumerable<Int32> clearText, IList<Int32> key) {
return clearText.Select((i, n) => unchecked(i + key[n%key.Count]));
}
IEnumerable<Int32> Decode(IEnumerable<Int32> cipherText, IList<Int32> key) {
return cipherText.Select((i, n) => unchecked(i - key[n%key.Count]));
}
((n + 173741789) * 507371178) % 1073741789
(n * 233233408 + 1073741789 - 173741789) % 1073741789