CTFで出題される古典的な暗号技術「シーザー暗号」をPythonで作る

ペネトレーションテスト&バグバウンティシーザー暗号

CTFの一番最初に出題される問題として「シーザー暗号」があります。
 
たとえば・・・
暗号文「dssoh」は、どんな果物でしょうか。
ヒント:3文字ずらす
 
クイズで出されたような記憶がありませんか?

シーザー暗号とは

古代ローマの軍人でかつ政治家であった「ジュリアス・シーザー」さんが作成した暗号文と言われています。
このシーザー暗号を戦争で、敵に知られることなく味方同士で通信していたそうです。
 
 

シーザー暗号を解いてみよう

暗号文「dssoh」
冒頭の暗号文は「ヒント:3文字ずらす」でした。
 
「ずらす」とは「文字の順番をずらす」と言うことで
以下の暗号テーブルが参考になると思います。
平文文字を3文字ずらす(復号化)と
※復号化とは暗号文を解読することです。
(平文に戻すともいいます。)
 
平文文字 → 復号文字
(黄色背景) (薄茶背景)
 「d」 → 「a」
 「s」 → 「p」
 「s」 → 「p」
 「o」 → 「l」
 「h」 → 「e」
 
果物の名前は「apple」になりました。
 
それでは、今のと反対で「暗号」を作成しましょう。
 
「hacker」を暗号化すると
平文文字 → 暗号文字
(黄色背景) (薄緑背景)
 「h」 → 「k」
 「a」 → 「d」
 「c」 → 「f」
 「k」 → 「n」
 「e」 → 「h」
 「r」 → 「u」
 
暗号文「kdfnhu」になります。
 
比較的簡単に解析できるのが「シーザー暗号」なのですが・・・
 
Wkh wudlq fdph rxw ri wkh orqj wxqqho lqwr wkh vqrz frxqwub Wkh hduwk odb zklwh xqghu wkh qljkw vnb Wkh wudlq sxoohg xs dw d vljqdo vwrs
(※英文です。ピリオドは無視しました。)
 
こんな暗号文だと・・・ちょっとしんどいですね。
 
解析すると
The train came out of the long tunnel into the snow country The earth lay white under the night sky The train pulled up at a signal stop
 
ちなみに、訳は「国境の長いトンネルを抜けると雪国であった。夜の底が白くなった。信号所に汽車が止まった。」 川端康成さんの「雪国」でした。
 
簡単に変換するには次の2の方法があります。
  • 入力した文章をシーザー暗号で暗号化/復号化するサイトを探す。
  • プログラムを作成して実行する。
CTFにチャレンジされるのであれば、シーザー暗号のプログラムをPythonで作成してみませんか。
 
 

シーザー暗号をPython言語で作成

シーザー暗号をPython言語で作成すると以下のようになります。
# ********************
# シーザー暗号(001)
# ********************

# 暗号化/複合化する文字テーブル
MOJI_TABLE = 'abcdefghijklmnopqrstuvwxyz'

# 暗号化/復号化する文字列の設定
moji_retu = 'dssoh'

# ずらす文字数
zurasu = 3

# 暗号化にする(暗号鍵):1
# 復号化にする(復号鍵):2
key = '2'

# 暗号化/複合化解析結果
answer = ''

for moji in moji_retu:
    # 暗号化/復号化する文字列に格納されている文字を1つずつ取り出しmojiにいれる
    # 「d」→「s」→「s」→「o」→「h」の順に

    # 暗号化/復号化する文字が暗号化/複合化する文字テーブルにあるか判定
    if moji in MOJI_TABLE:
        # 暗号化/復号化する文字が暗号化/複合化する文字テーブルにある場合変換する

        # 取り出した文字が文字テーブルの何番目にあるか確認する
        moji_point = MOJI_TABLE.find(moji)

        # 暗号化/複合化の判定により文字の位置をずらす
        if key == '1':
            # 暗号化の場合、文字の位置をプラス方向にずらす
            point = moji_point + zurasu
        elif key == '2':
            # 復号化の場合、文字の位置をマイナス方向にずらす
            point = moji_point - zurasu

        # 文字の位置をずらした結果、文字テーブル以上の長さになったり
        # マイナスの長さになった場合は調整します。
        if point >= len(MOJI_TABLE):
            # ずらし位置が文字テーブル以上の長さになった場合
            point = point - len(MOJI_TABLE)
        elif point < 0:
            # ずらし位置がマイナスの長さになった場合
            point = point + len(MOJI_TABLE)

        # ずらした文字を設定します。
        answer = answer + MOJI_TABLE[point]
    else:
        # 暗号化/化復号する文字が暗号/複合する文字テーブルにない場合は変換しない
        answer = answer + moji

# 暗号化/復号化後した文字列を表示
print(answer)
開発環境は「Google Colaboratory」を利用しました。
詳しくは
を見ていただければ、簡単にテストができますよ。
 
上記のシーザー暗号のプログラムをGoogle Colaboratoryにコピペするだけです。
 
Google Colaboratoryで実行ができれば、
CTFの問題に合わせて、定数や処理が変更できます。
たとえば、暗号化/複合化する文字テーブルで
 
簡単に英文字の小文字にしましたが
MOJI_TABLE = 'abcdefghijklmnopqrstuvwxyz'
 
英文字の大文字/小文字にしたければ
MOJI_TABLE = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXZY'
 
ひらがなにしたげば
MOJI_TABLE = 'あいうえおかきくけこ・・・わをん'
 
などいろいろできます。
 
いろいろ楽しんでくださいね。
 
 

CTFで出題される古典的な暗号技術「シーザー暗号」をPythonで作るのまとめ

いろいろな暗号があるのですが、今回古典的な暗号である「シーザー暗号」をご紹介しました。
実際に暗号は難しいですが、面白いところもあります。
また、違う暗号技術を紹介したいと思います。
 
CTFの問題を回答するときに利用するツールはいろいろありますが、私は「プログラム言語」もツールではないかと考えました。
本当は「C言語」「C++」が機械語に近いので良いのですが、機械語に近いため少し難しいです。
よって、比較的簡単な「Python言語」で分かりやすく作成して、カスタマイズしやすいようにしたいと考えています。
 
これを機会に「Python言語」も使えるようになりませんか。