현황 해독 9 · 부분 3 · 미해결 10
목록 항목은 “메시지 22통, 복호화 9, 부분 복호화 3, 미해결 10”이라고 적어야 하며, Lasry가 댓글 스레드에서 복원한 키는 발표된 열네 개의 키 옆에 함께 놓여야 한다. 알려진 키에 대해 최대 다섯 글자짜리 블록 편집을 두 번 하는 Norbert의 2017년 방법을 여기서 독일어 언어 모델로 다시 구현했으며, 이는 평문에 대한 아무런 힌트 없이 해독된 페이지들을 다시 도출한다. 미해결 메시지 열 통에 대해서는 열다섯 개의 키 어느 것으로도 아무것도 찾지 못하며, 키 없는 공격은 이 길이에서는 심어 둔 대조 실험에서조차 전치를 복원하지 못한다. 미해결인 열 통에는 Childs의 원본이나, 코퍼스에 한 번도 들어간 적 없는 키가 필요하다.
01 목록은 무엇인가
1918년 프랑스군에 배속된 미국 암호 분석가 James Rives Childs는 동부 전선에서 가로챈 독일 ADFGVX 통신의 사본을 보관했다. 2017년 George Lasry, Ingo Niebel, Nils Kopal, Arno Wacker는 전치에 대한 언덕 오르기 공격으로 이 코퍼스를 해독하여, 1918년 9월부터 12월까지 열네 개의 3일 단위 키로 암호화된 암호문 618개를 복원했다. 이어서 Lasry는 그 키들 어느 것으로도 복호화되지 않는 메시지 목록을 Klaus Schmeh에게 건넸고, Schmeh는 이를 키와 함께 “Unsolved ADFGVX messages from World War I”로 발표했으며, 나중에 자신의 Top 50에 no. 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자를 제시하면서, 자신의 프로그램이 길이 16의 키를 복원하는 데 암호문 글자 356개 전부가 필요했다고 적었다. 치환 정사각형은 발표되지 않았다. 여기서는 두 암호문의 전치되지 않은 이중자를 그의 평문(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 (“missing 10 letters”) | 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만 글자로 만든 독일어 4-그램 모델로 채점한다 (lm_de.py). 숫자나 복원되지 않은 칸을 포함한 창은 하한 점수를 받고, X 구분자를 가로지르는 창은 쓰레기 문자열보다는 덜, 본문보다는 더 많은 비용을 치른다. 이 모델에서 독일어 산문은 창당 약 −3.3 nats, 무작위 글자는 약 −7을 얻는다.
평문에 대한 아무런 힌트도 주지 않았는데, 탐색은 105, 109, 146, 171페이지, 176페이지의 “missing 10 letters” 메시지, 그리고 두 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년의 독자들이 도달하여 멈춘 경계다. 숫자가 많은 출력은 대개 틀린 키의 징후다. 이곳의 실제 통신은 대부분 글자이며, 틀린 정사각형은 이중자를 숫자 칸들에 흩뿌린다.
153페이지의 두 메시지에 대한 CHI 키
2017년 9월 Norbert는 153페이지의 두 메시지가 같은 시기의 것이므로 CHI 키에 속할 수도 있다고, 시험해 보지 않은 채 제안했다. 홀짝 보정을 곁들인 직접 복호화와 블록 탐색 모두 두 메시지에 대해 잡음만 반환한다. 원인은 목록에 없는 또 다른 키이거나, 블록 두 개보다 심한 손실이다.
키 없는 공격, 그리고 그것이 실패하는 이유
미해결 메시지 일부가 코퍼스에 없는 키로 암호화되었다면, 그 키는 암호문만으로 복원해야 할 것이다. keyless.py 가 시도하는 방법은 이렇다. 올바른 역전치는 단일 문자 치환의 이중자를 짝지어 주므로, 후보 길이마다 역전치가 만들어 내는 글자 쌍의 일치 지수를 목표로 열 순서를 담금질한 다음, 독일어 모델로 36기호 치환을 푼다. 미해결 메시지에 돌리기 전에, 심어 둔 대조 실험에 먼저 돌렸다. 같은 설계의 길이 19 키로 암호화한 독일어 224글자다.
| 후보 길이 | 15 | 16 | 17 | 18 | 19 (실제) | 20 | 21 | 22 | 23 |
|---|---|---|---|---|---|---|---|---|---|
| 담금질 후 쌍 IC | 0.055 | 0.048 | 0.060 | 0.053 | 0.064 | 0.058 | 0.066 | 0.063 | 0.073 |
실제 길이는 두드러지지 않는다. 19에서의 정점은 21, 22, 23에 밀리며, 치환 단계는 어떤 길이에서도 수렴하지 않는다. 대조 실험은 복원되지 않는다. 바로 이 목적으로 만든 Lasry 자신의 프로그램도 길이 16의 키를 복원하는 데 356글자가 필요했다. 미해결 메시지 열 통의 길이는 84에서 240글자다. 따라서 이 길이에서 키 없는 복원은 손이 닿지 않는다. 예외가 하나 있는데, 알려지지 않은 키를 공유하는 미해결 메시지가 둘 이상이라면, 두 CHI 메시지처럼 함께 풀 수 있다. 암호문에는 그것이 어느 것인지 표시가 없으며, 가장 자연스러운 후보인 153페이지의 두 메시지는 함께 시도해도 아무것도 나오지 않는다.
06 현황, 그리고 무엇이 그것을 바꿀 수 있는가
아홉 통은 복호화되었고, 세 통은 부분적으로, 열 통은 미해결이다. 열 통은 2026년 9월에 검사했으며, 블록 편집 최대 두 번으로 알려진 모든 키에서 실패한다. 세 가지가 이를 바꿀 수 있다.
| 무엇 | 왜 중요한가 |
|---|---|
| Childs의 원본 | 열 통 가운데 몇몇에는 인쇄된 전사에 명시적인 빈칸 표시가 있고, 하나에는 “missing 10 letters”라는 표시가 붙어 있다. 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 | 독일어 4-그램 모델, Gutenberg 독일어 텍스트 360만 글자 |
targets/adfgvx/keyless.py | 키 없는 전치 공격; 대조 실험 출력은 kl_control224.txt |
research/top50/arts/46_comments.txt | 2017년 스레드의 댓글 70개, 텍스트 |
targets/adfgvx/NOTES.md | 작업 노트, 두 세션 모두 |