シーザー暗号はどの暗号学の教科書でも最初のほうに出てくる簡単で有名な暗号です。これをpython3で実装してみたので紹介します。
目次
シーザー暗号とは
アルファベットを暗号化する場合、アルファベットを任意の数だけずらします。例えば3つずらすとしましょう。「a」を暗号化する場合、abcde…におけるaの3つ先の文字である「d」が暗号となります。こんな感じで「apple」を暗号化すると「dssoh」が暗号文となりますね。なおzの次はaに戻るものと考えます。
復号化は逆の作業をします。つまり暗号文を3つ戻せば平文に戻ります。簡単ですね!
「ずらす数」をいくつに設定するかが、暗号化鍵であると考えることができます。文章の送信者と受信者でいくつずらすのかを共有しておけば、それ以外の人間に暗号を解読されることはない、という理屈です。
しかし、実際には簡単に解読できてしまいます。アルファベットは26文字しかないので、ずらせるパターンも26通りだけ。26パターン全部試すことは容易です。そんなわけで、暗号としての強度はとても低く、実際に使われることはありません。
シーザー暗号の暗号化プログラム例
シーザー暗号による文字の暗号化プログラムはこんな感じになります。
def CC_encryption( text, key ):
result = ''
for char in list(text):
code = ord(char)
if 97 <= code and code <= 122: #小文字の場合
n = code - 97
n = (n + key) % 26
code = n + 97
result += chr(code)
if 65 <= code and code <= 90: #大文字の場合
n = code - 65
n = (n + key) % 26
code = n + 65
result += chr(code)
return result
このプログラムでは、暗号化したいテキストと、アルファベットを何文字分ずらすか(key)を入力します。そうすると暗号化されたテキストが出力されます。
ちなみに「CC_encryption」のCCは「Caesar cipher(シーザー暗号)」の略です。「encryption」は暗号化という意味。
ord()関数とChar()関数について
このプログラムではord()関数とchar()関数を使っているので、これに関する解説をします。
ord()関数は引数として文字を一つだけ入力すると、それに対応する整数を返してくれます。char()関数は引数として数字を入力すると、それに対応する文字を返してくれます。ord()関数で入手した数字をそのままchar関数に入れると元に戻ります。
例えば、小文字のaをord()に入力すると97が帰ってきます。
bなら98、cなら99 ,,, zなら122 という感じで、アルファベットが一つ進むと数字も1大きくなります。
また、大文字のAをord()関数に入れると、65が帰ってきます。こちらもB,C,D … とアルファベットが進むごとに数字が一つずつ大きくなり、Zを入力すると90が帰ってきます。
プログラムの解説
まず、3行目の「for char in list(text): 」で、平文textの文字を一つずつ変数charに入れていきます。そして4行目の「code = ord(char)」では、一文字ずつord()関数で整数を入手し、変数codeに代入します。
codeの値は、charに入っている文字が小文字であれば97以上122以下、大文字であれば65以上90以下になっているので、これを条件にして場合分けを行います。
小文字の場合について解説すると、codeの値は97から122までの数字になっているのですが、これでは扱いにくいので、97をマイナスします。
すると、「a → 0, b →1, c → 2 ,,, z → 25」とという対応に変更することができます。これが6行目「n = code – 97」の作業です。
そうしたら、ずらす値keyをnにプラスします。7行目の (n + key)の操作がこれにあたります。さらに (n + key)の値を26で割った余りを出します。そうすると25以下の値ならそのままの値がでますし、keyを足した結果26を上回ってしまった場合に、0~25の値に戻すことができます。これが7行目「n = (n + key) % 26」の処理です。
26以上の値に関しては「26 → a, 27 → b, 28 → c …」となりますが、26で割った余りを出すと「a → 0, b →1, c → 2 ,,, 」となり、もともとの対応と同じようになります。
keyの分だけ数字をずらしたら、またchar()関数を使って正しく「数字 → 文字」に戻すために、6行目で一度引いた97を再び足します。これが8行目「 code = n + 97」の処理です。
そして得られた暗号分を一つずつ「result = “”」 に足していきます(9行目「result += chr(code)」の処理)。全文字分終了すれば、めでたく暗号文の完成です。
大文字の場合も、小文字の場合の処理とほぼ同じです。97の部分を65に、122の部分を90に替えるだけです。
暗号化プログラムの実行例
平文”Apple”を key=3 で暗号化してみます。
【入力】print(CC_encryption(“Apple”, 3 ))
【出力】Dssoh
ちゃんと暗号化できています。
シーザー暗号の復号化プログラム例
暗号化だけでなく、復号化のプログラムも必要です。たとえばこんな感じになります。decryuptionは復号化という意味です。
def CC_decryuption( text, key ):
result = ''
for char in list(text):
code = ord(char)
if 97 <= code and code <= 122:
n = code - 97
n = (n - key) % 26
code = n + 97
result += chr(code)
if 65 <= code and code <= 90:
n = code - 65
n = (n - key) % 26
code = n + 65
result += chr(code)
return result
暗号化とほとんどやっていることが同じなので詳しい解説は割愛します。違いは暗号化で「+ key」になっていた部分が復号化では「- key」になっているだけ。これは進めた分のアルファベットを同じ分だけ戻すことで元の平文に戻しています。
復号化プログラムの実行例
【入力】print(CC_decryuption(CC_encryption(“Apple”, 3 ),3))
【出力】Apple
青字の部分は「apple」を暗号化する処理です。先ほどの「Dssoh」が入力されているはずです。それがちゃんと元の「Apple」に戻っています。復号化成功ですね。
まとめ
python3でシーザー暗号の暗号化と復号化を行いました。「アルファベットを進めて暗号s化し、復号化は同じだけ戻す」というのは簡単にイメージできますが、プログラムに書こうと思うと、結構頭を使いますね。教科書に出てくる暗号をひとつひとつ実装してみるのはいい学習になると思います。
【関連記事】シーザー暗号への攻撃プログラムも書きました!
シーザー暗号への攻撃プログラムに関する記事も書きました。よろしければこちらもどうぞ!