はじめに
シーザー暗号:入力されたアルファベットを3つシフトさせて暗号化する方法。
(例)art → duw
実装
caesar_cipher
# asciiの文字を使えるようにする
import string
# 文字列を暗号化する関数
def caesar_cipher(text: str, shift: int) -> str:
# シフト後の文字を入れる変数
result = ""
# 一つ一つの文字を取ってくる
for char in text:
# 大文字の場合
if char.isupper():
# 大文字のアルファベット26文字を表示
alphabet = string.ascii_uppercase
# 小文字の場合
elif char.islower():
# 小文字のアルファベット26文字を表示
alphabet = string.ascii_lowercase
# アルファベットでない場合
else:
# 取り出した1文字をresultに加える
result += char
# 次のループに行く
continue
# 取り出したアルファベットを3つ分シフトした時の文字のインデックスを取得(x,y,zの時にエラーにならないように、全体のアルファベット数(26)で割った時の余りをインデックスとする)
index = (alphabet.index(char) + shift) % len(alphabet)
# 取得したインデックスに対応するアルファベットをresultに追加
result += alphabet[index]
# 結果を返す
return result
# テスト
if __name__ == "__main__":
print(caesar_cipher("animal", 3))
stringモジュールを使わない場合の実装だと以下のように実装できる。
総当りで文字列をシフトさせたパターンを表示させる関数(caesar_cipher_hack)についても追記。
caesar_cipher(not_use_stringModule)
# 文字列を暗号化する関数(stringモジュールを使わない場合)
from typing import Generator, Tuple
def caesar_cipher(text: str, shift: int) -> str:
result = ""
len_alphabet = ord("Z") - ord("A") + 1
for char in text:
if char.isupper():
result += chr((ord(char) + shift - ord("A")) %
len_alphabet + ord("A"))
elif char.islower():
result += chr((ord(char) + shift - ord("a")) %
len_alphabet + ord("a"))
else:
result += char
return result
# 解読用の関数(すべてのシフトしたパターンを表示させる)
def caesar_cipher_hack(text: str) -> Generator[Tuple[int: str], None, None]:
# アルファベットの長さを取得する(stringモジュールが使えない場合)
len_alphabet = ord("Z") - ord("A") + 1
for candidate_shift in range(1, len_alphabet + 1):
reverted = ""
for char in text:
if char.isupper():
index = ord(char) - candidate_shift
if index < ord("A"):
index += len_alphabet
reverted += chr(index)
elif char.islower():
index = ord(char) - candidate_shift
if index < ord("a"):
index += len_alphabet
reverted += chr(index)
else:
reverted += char
yield candidate_shift, reverted
# テスト
if __name__ == "__main__":
print("暗号化したもの:" + caesar_cipher("Programming practice", 3))
# デクリプト(復号化)
e = caesar_cipher("Programming practice", 3)
print("復号化したもの:" + caesar_cipher(e, -3))
# 総当たりでパターンを表示させる。
for shift_num, decrypted in caesar_cipher_hack(e):
print(f"{shift_num:2d}", decrypted)
参考