现状 9 已解 · 3 部分 · 10 未解
清单条目应写作“22条电报,9条已解密,3条部分解密,10条未解”,而 Lasry 在评论帖中复原的那把密钥应与已公布的十四把并列。Norbert 2017年的方法——针对已知密钥做两处至多五个字母的块编辑——在此用一个德语语言模型重新实现,在不提供任何明文线索的情况下重新推出了已解的各页。对十条未解电报,它用十五把密钥中的任何一把都一无所获;而在这样的长度下,不依赖密钥的攻击即便在人为植入的对照上也无法复原换位。这十条未解电报需要 Childs 的原件,或者一把从未出现在语料中的密钥。
01 这份清单是什么
James Rives Childs 是1918年派驻法军的美国密码分析员,他保存了一份在东线截获的德军 ADFGVX 通信的抄本。2017年,George Lasry、Ingo Niebel、Nils Kopal 和 Arno Wacker 用针对换位的爬山法攻破了这批语料,在1918年9月至12月的十四把三日密钥下复原了618份密码电报。随后 Lasry 把在这些密钥下都无法解密的电报列成清单交给 Klaus Schmeh,Schmeh 以“Unsolved ADFGVX messages from World War I”为题发表,附上了密钥,后来又将其列为他的五十强第46号。
Lasry 在那个页面上的附注点明了问题所在:这些密钥“most certainly all the keys used during the period”,所以“the challenge is to understand how the cryptograms were mutilated”。ADFGVX 对长度毫不宽容。列换位按密钥长度切分字母流,所以丢失或多出一个字母,就会让其后的每个列边界都移位,把电报的其余部分变成噪声。一条有两处乱码的电报,即使密钥已知,也无法再用该密钥解密。
2017年2月至9月间,该帖下的评论区完成了大部分工作。Norbert Biermann、Armin、Thomas、Max Baertl 和 Lasry 本人一条接一条地解密了电报。Schmeh 宣布要写一篇汇总文章,却始终没写,所以这些解密结果只零散地存在于评论中,无论印本还是网上都找不到结果汇总表。本报告做的第一件事就是发布这张表。
02 密钥,转成机器可读格式
Lasry 的清单把每把密钥给成一个换位排列和一个36字符的替换方阵,各单元按 A D F G V X 的行序排列。十四个方阵中有三个含有成串的连字符,表示从未复原的单元,而 PDF 的文本层把这些连字符串压缩成了短破折号和长破折号,使方阵只剩34或35个字符。把每个破折号还原成能凑足36个字符的连字符串长度,三个方阵就都修复了。全部十四把都在 keys.json.
密钥数字有两种解释。要么 perm[i] 是第 i 个输出的列,要么是第 i 列被输出的位置。两种解释都能自洽地往返,所以加密–解密测试无法区分它们。解密一条真实电报则可以。答案是第二种。
不在清单上的密钥
2017年5月3日,Lasry 在评论帖中报告:一条分成两部分的电报——11月13日的 FFVXV 密码电报及其后续的 AFAFF 残片——在一把不属于十四个时段中任何一个的密钥下合并解密成功:换位词 CMBLAKOHIDENFJGP,长度16。他给出了合并后的明文,共173个字母,并指出他的程序需要全部356个密文字母才能复原一把长度为16的密钥。替换方阵没有公布。这里把两份密码电报中未换位的双字母组与他的明文(已采用 Norbert 的修正)对齐,重建了方阵:36个单元中复原了24个,数字和字母 M、Q、Y 未能复原,因为这条电报从未用到它们。它是以下文件中的第十五个条目: keys.json 仓库的笔记称之为 CHI 密钥,名称取自它所加密的那条电报的报头。
03 2017年的成果汇成一表
评论帖的全部70条评论都逐一看过。页码是 Schmeh 所印的 Childs 抄本页码;清单上有两条电报没有页码。字母数是收到的密文字母数,印本转录中标出的缺口另行计数。每项解密都归功于最先贴出它的人。
| Childs 页码 | 字母数 | 状态 | 密钥 | 读解 |
|---|---|---|---|---|
| 73 | 176 + 2处缺口 | 未解 | 无一相符 | — |
| 100 | 122 | 已解 | 11月1–3日 | KEINE STOERUNG DURCH FEIND X MITTAGS 2 FEINDL X DIV X IM MARSCH AUF BELGRAD X(Armin) |
| 105 | 290 | 已解 | 11月1–3日 | GERMANIA ETAPPE KONSTANTINOPEL XX FUER MITTELMEER DIVISION ZU X TEL X NR X 62 X DIV X TELEGR X NR X 58 X ERSTELLT … VOM X 4 X NOVEMBER ERLEDIGT X ADMIRALSTAB(Norbert) |
| 109 | 258 | 已解 | 11月1–3日 | O X K X M X ABENDMELDUNG … UNTERBRINGUNG LETZTER TEILE BEENDET X 1 WEITERER DU X DIV 5 IM MARSCH AUF BELGRADER KAVV X 2 X SONST KEINE EREIGNISSE(Norbert) |
| 132 | 153 + 缺口 | 已解 | 11月4–6日 | FUER EILVESE X WIEDERHOLE TELEGR X VON VIERTER PERIODE IN FUENFTER X GEBETSORDER 5 MIN X VVV。加密者把 VV 写成了 VVV,因此长度是奇数(Norbert) |
| 146 | 244 | 已解 | 11月4–6日 | FUNKSTELLE KERTSCH ER HAT BETRIEB X 1F X RUFNAMEN RICHARD EMIL KARL X FUNKSTELLEN DORTIGEN BEREICHS BENACHRICHTIGEN X NACHRICHTENCHEF 4B X 7834 X(Norbert) |
| 152 | 104 | 未解 | 无一相符 | — |
| 153(VFVAX) | 132 | 未解 | 无一相符,包括 CHI 密钥 | — |
| 153(AXVAA) | 93 + 15处缺口 | 未解 | 无一相符,包括 CHI 密钥 | — |
| 158 | 240 + 2处缺口 | 未解 | 无一相符 | — |
| 164 (F-G-X) | 158 + 44处缺口 | 部分 | 11月7–9日 | … X 9 X 11 X TEMESVAR X … DIE VON X MIRCO NACH WESTEN UND SUEDEN WEG X LEIDER WEGE VOM GEGNER BESETZT X(Norbert) |
| 164(VFGAG) | 136 + 44处缺口 | 部分 | 11月7–9日 | EL X DIE HOEHE X 828 X O X H X L X MIRCO X SONST KEINE EREIGNISSE VON BEDEUTUNG XX(Norbert) |
| 170 | 106 | 未解 | 无一相符 | — |
| 171 | 310 + 4处缺口 | 已解 | 11月7–9日 | IN UKRAINE UND POLEN RUBELKURSE STARK STEIGEND INFOLGE BRUCHES ZWISCHEN DEUTSCHLAND UND SOWJETREGIERUNG UND ERWARTUNG DER WIEDERHERSTELLUNG RUSSLANDS DURCH DEUTSCHLAND UND ENTENTE(Norbert) |
| 176(“缺10个字母”) | 214 | 已解 | 11月10–12日 | DURCHBRUCH VORBEREITET X DURCHBRUCHSRICHTUNG NACH NORDEN ODER NORDOSTEN ERFOLGEN WIRD X KANN JETZT NOCH NICHT BEURTEILT WERDEN X(Norbert) |
| 176(GGDAA) | 220 | 未解 | 无一相符 | — |
| 无页码(VGADA;Childs p. 215,11月22日) | 237 + 11处缺口 | 部分 | 11月22–24日 | ABS X MIDIV 5 X EILMELDG … ARMADA KERTSCH X BRINGT ENTENTE FLOTTE ZWO DIVISIONEN X NEUSEELAENDER X ENGL X U X FRANZO X MIT X … OHL X KORPS …(Norbert、Baertl) |
| 187(FFVXV;Childs p. 191,11月13日,第1部分) | 212 | 已解 | CHI,11月13日 | RUSSISCHEN UND POLN HEERESVERKEHR VOLL ERFASSEN X WICHTIGES BESONDERS AUS POLN VERKEHR UEBER OHL STATION VERZIFFERT FUNKEN(Lasry、Norbert) |
| 无页码(AFAFF;第2部分) | 142 | 已解 | CHI,11月13日 | SOWEIT FERNSCHREIBERVERBDG NICHT ARBEITET X REST SCHRIFTLICH X NACH CHEF(Lasry、Norbert) |
| 189 | 84 + 6处缺口 | 未解 | 无一相符 | — |
| 198 | 165 | 未解 | 无一相符 | — |
| 217 | 170 | 未解 | 无一相符 | — |
九条已解密,三条部分解密,十条在任何地方都找不到解密结果。另有一页抄本,即印本中的187(SELLV…,“Stellv. Gen. Kom. 9 AK Breslau”),是卡塞尔团队早已解出的电报,不应列入清单;Lasry 在评论帖中已指出这一点。两条 CHI 电报被列为在已公布密钥下无法解密,这没错;它们是在 Lasry 复原了一把未公布的密钥之后才解密的。
04 重新实现 Norbert 的方法
Norbert 用一句话说明了他的方法:在两个不同位置添加或删除至多五个字符,穷举搜索,用 n 元组评价函数为结果排序。 blocks.py 做的正是这件事。对十五把密钥中的每一把,以及每一种至多两处、每处一到五个字母的块编辑(在抄本的五字母组边界处插入或删除),它都进行解密,并用一个德语四元组模型为结果打分;该模型由 Gutenberg 德语文本中的360万个字母构建(lm_de.py)。含有数字或未复原单元的窗口记最低分;跨越 X 分隔符的窗口,代价低于乱码、高于正文。在这个模型上,德语散文每个窗口的得分约为 −3.3 nats,随机字母约为 −7。
在不提供任何明文线索的情况下,搜索重新推出了第105、109、146、171页,第176页那条“缺10个字母”的电报,以及两条 CHI 电报。在第146页上,Norbert 在第10组之前插入的那个五字母块得出为 (45, 5)。在第176页的电报上,两个五字母块得出为 (10, 5), (130, 5)。第100页用同样的搜索、只插入一个双字母块就解开了。搜索还找到了无页码的 VGADA 电报在11月22–24日密钥下的部分解。在印本转录标出缺口之处, gaps.py 把缺口还原到各自的组里,再用模拟退火处理剩余的单字母丢失;在第132页上,它在没有任何提示的情况下得出了 Norbert 的文本。
重新推出的各页得分(取自运行日志),与未解电报所能达到的最佳得分对比:
| 页码 | 密钥长度 | 最佳得分,nats/窗口 | 搜索返回的解密结果 |
|---|---|---|---|
| 187(CHI 第1部分) | 16 | −4.45 | RUSSISCHETUNDPOLNHEERESVERKEHRVOLLERFASSENXWICHTIGESBESONDERS… |
| 146 | 17 | −5.25 | FUNKSTELLEKERTSCHERHAE.TAB12X1.XRUFNAME.RICHARD.MILKARLX… |
| AFAFF(CHI 第2部分) | 16 | −5.28 | SOWEITFERNSCHREIBERVERBDGNITHTARBEICETXRESTSCHRIFTLICHXNACHCHEF… |
| 100 | 19 | −5.39 | KEI.ESTOERFNGDURCHFEINDXMITTAGS2FEINDLXDIVXIMMARSCHAUFBELGRAD. |
| 171 | 20 | −5.50 | INUKRAI.EUNDPOLEN.UBELKURSETARKSIEIGENDINFOLGEBRUCHEEZWISCHEN… |
| 105 | 19 | −6.02 | GERMANIAATAPPEKONSTANTINOPELX6FUERMITTJLMEERDIVISIVNZUXTELXNRX62… |
| 109 | 19 | −6.02 | OXFXMXABECDMELUNGXS4VCXUMBJRGABGLETZTEVTEILEBEEVUKTX1WEITEDE… |
| 最佳的未解电报(158,170) | 20, 19 | −6.89 | 噪声 |
已解的各页即便块编辑不完全准确,也一眼就能认出是德语,剩下的乱码是第二轮能修复的单字母丢失。第105页和第109页两行得分比其他的低,因为两块搜索只能近似其损坏情况;但两段文本在原始输出中都清晰可读,也都与 Norbert 2017年的解密一致。
05 检验十条未解电报
两处块编辑,十五把密钥
十条电报中的每一条都用全部十五把密钥、至多两处块编辑跑过一遍。每条的最佳结果,取自 blocks_out.txt:
| 页码 | 字母数 | 最佳结果的密钥长度 | 最佳得分 | 输出 |
|---|---|---|---|---|
| 73 | 176 | 22 | −7.12 | DWR5C10WAXWBI.GWBXD1QGRA.R7OCW3Q… |
| 152 | 104 | 22 | −6.76 | YPVXKTHJ7EM46PGPQ3RONDSEEUHXKTAX… |
| 153(两条) | 132, 93 | 20 | −6.99 | XWH2XBB3WATECOIFLUKTXMHK17SSY2ME… |
| 158 | 240 | 20 | −6.89 | ZF2B0GEKJXII32RXRCO4LRS2DXA2RBDO… |
| 170 | 106 | 19 | −6.89 | N5ADB08EKYND918UFEED92H3ELZEJ0UA… |
| 176(GGDAA) | 220 | 22 | −7.10 | RGXCXXPPUN6RAXZK2YD8PMRX4NVX4ZYT… |
| 189 | 84 | 22 | −7.08 | 1AA1SLUOXO.VGXWUXUWH6LXXNHLV.9WW… |
| 198 | 165 | 20 | −6.97 | LTDUUKWRA28KK61UITPUU31LEPXSIP42… |
| 217 | 170 | 18 | −7.04 | YBEIEU84543EOTXT45R8K6XXGCSF4PWI… |
没有一条超过 −6.7。同一次运行中,已解电报的得分在 −4.4 到 −6.0 之间,随机字母约为 −7.3。所以这十条中没有一条是用十五把密钥之一加密、且只有两处或更少块损坏的,这恰恰是2017年的读者们到达并止步的边界。输出中数字很多,通常是密钥不对的迹象:这里的真实通信大多是字母,错误的方阵会把双字母组散布到数字单元上。
用 CHI 密钥试第153页的两条电报
2017年9月,Norbert 提出(但未测试)第153页的两条电报可能属于 CHI 密钥,因为它们出自同一时期。用奇偶修复直接解密,以及块搜索,对两条电报返回的都是噪声。原因要么是还有另一把未列出的密钥,要么是损坏超过了两块。
不依赖密钥的攻击,以及它为何失败
如果某些未解电报是用语料之外的密钥加密的,那么这把密钥就只能仅凭密文来复原。 keyless.py 的做法是:在每个候选长度上,以逆换位产生的字母对的重合指数为目标,对列序做模拟退火(因为正确的逆换位会把单表替换的双字母组配成对),然后用德语模型求解36符号的替换。在用于未解电报之前,先在一个人为植入的对照上运行:224个德语字母,用同样设计的长度为19的密钥加密。
| 候选长度 | 15 | 16 | 17 | 18 | 19(真实) | 20 | 21 | 22 | 23 |
|---|---|---|---|---|---|---|---|---|---|
| 退火后的字母对重合指数 | 0.055 | 0.048 | 0.060 | 0.053 | 0.064 | 0.058 | 0.066 | 0.063 | 0.073 |
真实长度并不突出:19处的峰值被21、22和23超过,替换阶段在任何长度上都不收敛。对照没有被复原。Lasry 专为此目的编写的程序,需要356个字母才能复原一把长度为16的密钥。十条未解电报的长度在84到240个字母之间。因此在这样的长度下,不依赖密钥的复原是做不到的,只有一个例外:两条或更多共用同一把未知密钥的未解电报可以合并求解,就像那两条 CHI 电报一样。密文中没有任何东西表明哪些电报属于这种情况;而最自然的候选——第153页的两条电报——放在一起试,也一无所获。
06 现状,以及什么能改变它
九条电报已解密,三条部分解密,十条未解。这十条于2026年9月经过检验,在每一把已知密钥、至多两处块编辑之下都失败了。有三件事能改变这一点。
| 什么 | 为何重要 |
|---|---|
| Childs 的原件 | 这十条中有几条在印本转录中带有明确的缺口标记,其中一条标着“缺10个字母”。Schmeh 印出的转录是抄本的抄本;截获原件上可能保留着搜索不得不去猜的那些字母。 |
| 另一把密钥 | CHI 电报证明了公布的清单并不完整。一把从其他来源、或从同一时期某条从未列入本清单的较长电报中复原的密钥,几秒钟内就能对全部十条进行测试。 |
| 超过两处编辑的搜索 | 在十五把密钥上做三处块编辑,计算量是够得着的,也是自然的下一步;这里没有运行,是因为两处编辑这一标准已经解出了2017年读者们解出的一切,而且得分没有显示任何未解电报接近解开。 |
在其中任何一项出现之前,有用的成果是:上面的表格,十五把机器可读格式的密钥(三个受损方阵已修复,CHI 方阵已重建),以及一个无需提供明文就能重现2017年解密结果的解码器。
07 文件
| 文件 | 内容 |
|---|---|
targets/adfgvx/msgs.txt | Schmeh 所印的二十二份密码电报,保留缺口标记 |
targets/adfgvx/keys.json | 十五把密钥:Lasry 的十四把(三个受损方阵已修复),以及11月13日的 CHI 密钥 |
targets/adfgvx/key16.py | 根据两部分明文重建 CHI 替换方阵 |
targets/adfgvx/repair.py | 解码器; validate 重现第100页, solve 对所有电报运行插入搜索 |
targets/adfgvx/blocks.py | Norbert 的两处块编辑搜索,针对所有密钥;输出在 blocks_out.txt |
targets/adfgvx/gaps.py | 识别缺口的解析器,以及处理剩余单字母丢失的退火程序 |
targets/adfgvx/lm_de.py | 德语四元组模型,Gutenberg 德语文本中的360万个字母 |
targets/adfgvx/keyless.py | 不依赖密钥的换位攻击;对照输出在 kl_control224.txt |
research/top50/arts/46_comments.txt | 2017年评论帖的70条评论,文本 |
targets/adfgvx/NOTES.md | 工作笔记,两次会话 |