Q6.Classical Cipher 【CpawCTF】
軽い気持ちで挑戦し始めた「CpawCTF」ですが、「Classical Cipher」で早々に躓いてしまいました。
紙とペンを使えば解ける問題なのですが、やはりここはプログラムで解決したい!ということでやっていきます。
前回の記事はこちら
Classical Cipherとは?
そもそも「Classical Cipher(クラシカル・サイファー)」っていったい何?
ということで、調べてみると
「Classical(古典的な)」と「Cipher(暗号)」のようです
実際に解いていきましょう
はい。ということで問題はこちら。

さっき調べた古典暗号について説明が親切にありましたね
(ガイウスさん、ユリウスさん、カエサルさん、どの方もゲームのキャラクターとして名前が使われていそうな感じ。)
そして解き方も書いてあります
暗号文: fsdz{Fdhvdu_flskhu_lv_fodvvlfdo_flskhu} のアルファベット1文字1文字をそれぞれ3文字分ずらせば良いだけです。とても面倒くさいですね。
ということでアルファベットを任意の数分ずらしてくれるプログラムを作っていきましょう
Pythonを使ってプログラムを作成してみよう
最初に作りたいプログラムの動きを考えてみます。
- 暗号文を1文字ずつに分ける
- アルファベット1文字ずつを数字に変換する
- 変換した数字に任意の数を足す
- 足した数字をアルファベットに変換する
もっと配慮すべき点はありますが、まずはざっくりこのような流れで作ってみようと思います。
ちなみに「CpawCTF」のルールに解き方は乗せちゃダメ!とありますので、あくまでシーザー暗号の解き方を書いていきますね。

1.暗号文を1文字ずつに分ける
仮に暗号文が「>KA{_ild\mvqelk}」だったと想定し1文字ずつに分けます
これは「for ~ in ~」を使えば作れそうですね
Cipher = ">KA{_ild\mvqelk}"
for a in Cipher:
print(a)
「Cipher」という箱を作り、暗号文を入れてあげます
「for ~ in ~」を使って「a」に暗号文を1文字ずつ格納してみると・・・

1文字ずつ出力されました
次にこの文字たちを数字に変換していきましょう
2.アルファベット1文字ずつを数字に変換する
「アルファベットを数字に変換する」で調べるとヒットする「ord関数」というものを使っていきます
Cipher = ">KA{_ild\mvqelk}"
for a in Cipher:
print(a)
---[1.暗号文を1文字ずつに分ける]の続き---
print(ord(a))
先ほどの続きに「print(ord(a))」を加えて結果を見てみましょう

このように数字で出力されるようになりました。
続いてこの数字に今回は3を足していきましょう。
3.変換した数字に任意の数を足す
Cipher = ">KA{_ild\mvqelk}"
for a in Cipher:
print(a)
---[1.暗号文を1文字ずつに分ける]の続き---
print(ord(a))
---[2.アルファベット1文字ずつを数字に変換する]の続き---
print(ord(a)+3)

単純に3を足すだけですね
4.3を足した数字をアルファベットに変換する
アルファベットを数字に変換した「ord関数」とは反対に
数字をアルファベットに変換する「chr関数」というものを使っていきます
Cipher = ">KA{_ild\mvqelk}"
for a in Cipher:
print(a)
---[1.暗号文を1文字ずつに分ける]の続き---
print(ord(a))
---[2.アルファベット1文字ずつを数字に変換する]の続き---
print(ord(a)+3)
---[3.変換した数字に3を足す]の続き---
print(chr(ord(a)+3))

これで答えといきたいのですが、ちょっと一工夫
「 { 」と「 }」は3を足す対象から外していきます
Cipher = ">KA{_ild\mvqelk}"
x = "{"
y = "}"
for a in Cipher:
if chr(ord(a)) == x or chr(ord(a)) == y:
print(chr(ord(a)))
else:
print(chr(ord(a)+3))
if文を使って「もし文字が “{” か “}” なら」そのままの文字を出力してあげます

アルファベットだけを見たい場合は「z」に3を足したら一周回って「z」→「a」→「b」→「c」と戻ってこないといけないなど配慮すべきことはまだあると思います
ぜひシーザー暗号の解き方を参考に問題にチャレンジしてみてください
それではまた

