使用密钥的可逆洗牌算法

2024-03-19

我如何在 C# 中编写一个可逆的洗牌算法,该算法使用密钥进行洗牌并且可​​以反转到原始状态?

例如,我有一个字符串:“Hello world”,如何对其进行洗牌,以便稍后我可以将洗牌后的字符串反转回“Hello world”。


Look at 费舍尔-耶茨洗牌 http://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle一种基于键排列字符串的方法。将密钥作为种子输入 PRNG,用它来生成 shuffle 使用的随机数。

现在,如何逆转该过程? Fisher-Yates 的工作原理是交换某些元素对。因此,要反转该过程,您可以将相同的密钥输入相同的 PRNG,然后运行 ​​Fisher-Yates 算法as if您正在对字符串大小的数组进行洗牌。但实际上你没有移动任何东西,只是记录每个阶段将被交换的元素的索引。

完成此操作后,请浏览您的交换列表相反,将它们应用到打乱的字符串上。结果是原始字符串。

例如,假设我们使用以下交换对字符串“hello”进行了洗牌(我在这里没有使用 PRNG,我掷骰子,但 PRNG 的要点是,它给你相同的数字序列,给定相同的数字序列)。种子):

(4,0): "hello" -> "oellh"
(3,3): "oellh" -> "oellh"
(2,1): "oellh" -> "olelh"
(1,0): "olelh" -> "loelh"

所以,打乱后的字符串是“loelh”。

为了进行洗牌,我生成相同系列的“随机”数字 0、3、1、0。然后以相反的顺序应用交换:

(1,0): "loelh" -> "olelh"
(2,1): "olelh" -> "oellh"
(3,3): "oellh" -> "oellh"
(4,0): "oellh" -> "hello"

Success!

当然,这样做的缺点是它会使用大量内存进行洗牌:索引数组与原始字符数组一样长。因此,对于真正巨大的数组,您可能需要选择一个 PRNG(或者无论如何一个序列生成函数),它可以向前或向后步进,而无需存储所有输出。这排除了基于散列的加密安全 PRNG,但 LFSR 是可逆的。

顺便说一句,你为什么要这样做?

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

使用密钥的可逆洗牌算法 的相关文章

随机推荐