Q6.[Crypto] Classical Cipher
CpawCTFレベル1の二問目。暗号文をシーザー暗号のルールに従って解読するもの。アルファベットをN文字分ずらせばいいだけ。
シーザー暗号とは
アルファベットを一定の数ずらして文字列を変換する暗号。例えば、シフト数が1で順方向にずらすなら、AはBになり、BはCになる。具体的には、ABCD→BCDEという風に。暗号の中でもとてもメジャーなもので、CryptoHackというCTFでは、アカウント登録にシーザー暗号を解く必要がある。

Solve this Roman emperor’s cipher: YBILT KLYIB QOLRYIB ZEROK
CryptoHackアカウント登録画面から引用
解法
暗号文を手動でずらすことも可能だが、手間がかかるのでPCもスマホもないとき以外は文字をずらすコードを書くか、そういうサイトを利用しよう。
①Pythonでの解読
def caesar_decrypt(text, shift):
result = ""
for char in text:
if 'a' <= char <= 'z':
result += chr((ord(char) - ord('a') - shift) % 26 + ord('a'))
elif 'A' <= char <= 'Z':
result += chr((ord(char) - ord('A') - shift) % 26 + ord('A'))
else:
result += char
return result
cipher_text = "fsdz{Fdhvdu_flskhu_lv_fodvvlfdo_flskhu}"
print(caesar_decrypt(cipher_text, 3))
print(caesar_decrypt(cipher_text, 3))の最初の引数cipher_textは最初に名付けた関数名で、暗号化された文字列を受け取る。その次の数字がスライドさせる数。
この問題はスライドする数が3なので、print(caesar_decrypt(cipher_text, 3))としている。スライド数を切り替えたいときは、数値を変更すればいい。
アルファベットは大文字と小文字があるので、if文3つ書くことになる。一つ目が小文字、二つ目が大文字、三つ目がアルファベット以外の記号。
Pythonでは、Uniコードの大小関係が比較できるので、if ‘a’ <= char <= ‘z’:では、Uniコードの大小を比較している。AのUniコードは65、Zは90、aは97、zは122という風に、段々大きくなっていく。ここでやっていることは、if ord(‘a’) <= ord(char) <= ord(‘z’)と同じ。
ord(char) – ord(‘a’) – shiftは、aを基準にして、(char)に入る文字が何番目かを算出する。それをshiftに入れた数字分差し引けば、その分ずらせる。
※ord()は括弧内の文字をUniコードに変換する関数。
※char()は、ord()とは逆に、数値を文字に変換できる。
②シーザー暗号を解読用のサイトを使う
「シーザー暗号 変換サイト」と検索するだけで沢山出てくる。以下はそのリンク。

コメント