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言語」も使えるようになりませんか。