【问题标题】:Multi-character substitution cipher algorithm多字符替换密码算法
【发布时间】:2015-06-20 11:34:50
【问题描述】:

我的问题如下。我有一个替换列表,包括对字母表中每个字母的替换,还有对多个字母组的替换。例如,在我的密码中,p 变为 b,l 变为 w,e 变为 i,但 le 变为 by,ple 变为 memi。

所以,虽然我可以想到一些简单/幼稚的方法来实现这个密码,但它不是很有效,我想知道最有效的方法是什么。答案不必是任何特定的语言,通用的结构化英语算法就可以了,但如果它必须是某种语言,我更喜欢 C++ 或 Java 或类似的语言。

编辑:我不需要这个密码是可破译的,一种将所有单个字母映射到字母“w”但将字符串“had”映射到字符串“jon”的算法也应该没问题(然后字符串“Mary had a little lamb.”将变为“Wwww jon w wwww wwww.”)。

我希望算法是完全通用的。

【问题讨论】:

  • 我假设您已确保字母表是唯一且明确的?你在某个地方有整个字母表吗,即。所有的替换规则?
  • 独特和明确是什么意思?我不需要这个密码是可破译的,将所有单个字母映射到字母 w 但将字符串“had”映射到字符串“jon”的算法也应该是可行的。我希望算法是完全通用的。
  • 嗯,什么?为什么你不需要这个密码是可破译的?这对我来说毫无意义。 “密码”这个词几乎总是与加密结合使用,它以解密为对应物,因此是可破译的。你在构建一个类似哈希的算法吗?
  • 不,我正在第二人生中构建一种角色扮演“语言”。翻译已经秘密发送到预定的目标,我只需要它在外人听来很酷。
  • 啊,那我明白了。我想“kek”是这里的适当回应:)

标签: algorithm encryption substring substitution string-substitution


【解决方案1】:

一种可能的方法是使用确定性自动机。最接近您的问题和常用示例是Aho–Corasick string matching algorithm。不同之处在于,您希望在某个转换时发出密码,而不是匹配。通常在每次转换时,您都会发出或不发出密码。 在你的例子中

p -> b
l -> w
e -> i
le -> by
ple -> memi

自动机(在 Erlang 中类似伪代码)

start(p) -> p(next());
start(l) -> l(next());
start(e) -> e(next());
...

p(l) -> pl(next);
p(X) -> emit(b), start(X).

l(e) -> emit(by), start(next());
l(X) -> emit(w), start(X).

e(X) -> emit(i), start(X).

pl(e) -> emit(memi), start(next());
pl(X) -> emit(b), l(X).

如果您不熟悉 Erlang,start()p() 是每个状态的函数。带有-> 的每一行都是一个转换,动作遵循->emit() 是发出密码的函数,next() 是返回下一个字符的函数。 X 对于任何其他字符都是可变的。

【讨论】:

  • 那不需要我硬编码转换规则吗?这个自动机看起来非常具体到我给出的那个例子。我想要将替换规则作为输入的东西,而不是代码的一部分。
  • 存在一种算法,可以按照您在问题中描述的方式为您定义的任何密码生成自动机。制作此算法是解决方案的难点,但您可以从用于生成 Aho-Corasic 的算法中获得启发。
  • 它的时间和空间复杂度是多少,作为转换次数和要加密的字符串大小的函数?我已经有一个算法可以做我想要的,但是它花费的时间太长(两行句子大约 0.25~0.5s)。另外,我不认为我所使用的语言 (en.wikipedia.org/wiki/Linden_Scripting_Language) 足够强大,无法构建一个算法来有效地根据输入生成这个自动机。
  • 如果你阅读链接的*文章你会知道如果预先知道模式字典(例如计算机病毒数据库),则可以离线执行自动机的构建并且编译后的自动机存储以备后用。在这种情况下,它的运行时间与输入长度加上匹配条目的数量成线性关系。 这回答了您的两个问题。您可以生成不同语言的自动机并生成 LSL 代码。
  • 我读到了,关键是模式字典是事先不知道的,它是输入的一部分,我不能使用不同的语言,因为输入也来自 SL 内部。用户给程序一个任意模式字典作为输入,然后给它一个字符串以使用该模式进行加密。