输入同一段文字、同样的栏数,用「栅栏密码」加密,在两个不同的工具里得到了完全不同的结果。这不是哪个工具算错了,而是「栅栏密码」这个名字对应两种不同的算法:分组栅栏和之字形栅栏。中文语境里说的「栅栏密码」通常指前者,英文的 rail fence 指后者。
分组栅栏:横排竖读
分组栅栏的做法是把文本摆成表格,然后按列读出。
以 HELLOWORLD(10 个字符)、3 栏为例,先按从左到右、从上到下的顺序把字符填进表格:
H E L
L O W
O R L
D
注意最后一行的 D 只填了一格,因为字符用完了。
然后按列从上到下读出:第一列是 H L O D,第二列是 E O R,第三列是 L W L。
拼接得到密文:HLODEORLWL。
解密就是反过来:把密文按列切分(前 4 个字符是第一列,接下来 3 个是第二列,最后 3 个是第三列),填回表格,再按行读出。
之字形栅栏:沿折线摆放
之字形栅栏的摆放方式不同。字符沿 1 → N → 1 的折线路径依次写到各栏上。
以同样的 HELLOWORLD、3 栏为例,摆放的路径是:第 1 栏、第 2 栏、第 3 栏、第 2 栏、第 1 栏、第 2 栏、第 3 栏……依次循环。
栏 1: H . . . O . . . L . .
栏 2: . E . L . W . R . D .
栏 3: . . L . . . O . . . .
每个字符按路径落到对应的栏里,同一栏里的字符保持先后顺序。
然后按栏读出:第 1 栏是 H O L,第 2 栏是 E L W R D,第 3 栏是 L O。
拼接得到密文:HOLELWRDLO。
可以看到,同样的输入和栏数,两种算法得到的密文完全不同。
名字的来历
「栅栏」这个名字来自传统的实现方式:把一条纸条斜着绕在一排栅栏柱上写字,展开纸条后就得到了打乱顺序的密文。栏数对应栅栏柱的数量。
这个物理过程更接近之字形——因为纸条在柱子之间来回缠绕,字符的落点自然形成折线路径。
而分组栅栏的「表格」形式,更像是后来为了便于教学和编程实现而做的抽象。两种形式都被归到「栅栏密码」名下,造成了命名的重叠。
怎么判断该用哪个
如果是中文语境(比如中文的 CTF 题目、中文教程),说「栅栏密码」通常指分组栅栏。中文教材里常见的例子是「把文本按 N 列排列再按行读出」或者「按列读出」,这与分组栅栏一致。
如果是英文语境(rail fence cipher),指的是之字形栅栏。这是英语世界里的标准形式,英文密码学教材和维基百科条目描述的都是这个。
如果是解谜场景,最稳妥的做法是两种都试一遍。因为栏数通常也需要穷举,把两种算法和多个栏数组合起来试,工作量并不大——栏数一般只需要试 2 到 10,两种算法合计不到 20 种组合。
一个共同点
两种栅栏都属于换位密码:只改变字符的顺序,不改变字符本身。
这意味着一个重要的性质——字母的出现频率完全不变。原文里有几个 E,密文里就有几个 E,只是位置变了。
所以频率分析对栅栏密码依然有效。虽然换位打乱了顺序,但攻击者可以统计频率、猜测可能的排列方式,逐步还原。这也是栅栏密码不能用于真实加密的原因之一。
另一个共同点是密钥空间小。栏数就是密钥,通常只需要试十几种可能。所以穷举攻击对两者都很容易。
检查清单
- 分组栅栏是「横排竖读」:按行填入表格,按列读出
- 之字形栅栏是「沿折线摆放」:字符按 1→N→1 的路径落到各栏,再按栏读出
- 同样的输入和栏数,两种算法得到的密文完全不同
- 中文语境的「栅栏密码」通常指分组栅栏,英文 rail fence 指之字形栅栏
- 解谜时最稳妥的做法是两种算法、多个栏数都试一遍
- 两者都属于换位密码,字母频率不变,且密钥空间都很小