神のミソ汁のセカイ

大学生活のことや技術的な備忘録を残してます

Pragyan CTF 2015: Rubies on Rails Write-up

問題

Pragyan CTF 2015: Rubies on Rails

チャレンジ中のリストはこちCrypto Challenges List(2015)

解答

問題ファイルcrypted.txtの中身は次のような数字の列であった。

777
33
33
7777
8
88
444
7777
777
8
666
9
33
22
2
666
33

携帯電話のキーボード入力ぽいのでプログラムを書いて確かめてみる。

ten_key = {2 : 'abc', 3 : 'def', 4 : 'ghi', 5 : 'jkl', 6 : 'mno', 7 : 'pqrs', 8 : 'tuv', 9 : 'wxyz'}

text = ''
with open('crypted.txt', 'r') as f:
    for line in f:
        n = int(line.strip()[0])
        text += ten_key[n][len(line.strip())-1]
print(text)

結果はreestuisrtowebaoe。これも何かの暗号文になっているようだ。

色々調べてみるとRail fence cipher - Wikipediaという暗号を見つけた。

平文を1文字ずつ$n$段になるようギザギザに並べ、それを1段目から順に結合して暗号化する方式のようだ。(詳細は上のWikipediaの記事や別のサイトに譲る)

http://www.dcode.fr/rail-fence-cipherに復号の仕方が載っていたので、これを参考にして復号プログラムを書いた。

#solver.py
#! /usr/bin/env python3
# coding: utf-8

def decrypt_rail_fence(text, level):
    l = len(text)
    arr = [[] for _ in range(level)]
    ans = ''

    i = 0
    up = True
    for _ in range(l):
        if up:
            arr[i].append('0')
            if i == (level - 1):
                up = False
                i -= 1
            else:
                i += 1
        else:
            arr[i].append('0')
            if i == 0:
                up = True
                i += 1
            else:
                i -= 1

    for i in range(len(arr)):
        arr[i] = [text[j] for j in range(len(arr[i]))]
        text = text[len(arr[i]):]

    i = 0
    up = True
    for _ in range(l):
        if up:
            ans += arr[i].pop(0)
            if i == (level - 1):
                up = False
                i -= 1
            else:
                i += 1
        else:
            ans += arr[i].pop(0)
            if i == 0:
                up = True
                i += 1
            else:
                i -= 1
    return ans

ten_key = {2 : 'abc', 3 : 'def', 4 : 'ghi', 5 : 'jkl', 6 : 'mno', 7 : 'pqrs', 8 : 'tuv', 9 : 'wxyz'}

text = ''
with open('crypted.txt', 'r') as f:
    for line in f:
        n = int(line.strip()[0])
        text += ten_key[n][len(line.strip())-1]

print('Cryptogram of rail fence (Decryption of original):',text)
ans = decrypt_rail_fence(text, 3)
print('Decryption of rail fence:', ans)

実行結果は

$ ./solver.py
Cryptogram of rail fence (Decryption of original): reestuisrtowebaoe
Decryption of rail fence: rubiesaretoosweet

よってflagはrubiesaretoosweet

感想

問題名(Rubies on Rails)が暗号方式のヒントになっていた。 復号プログラムはもう少しきれいに書けそう。