カエサル暗号

こんにちわ。私は、理工系の大学院生で、数学や技術等の面白さをお伝えできればと思います。
今回は、カエサル暗号の簡単な紹介とPythonで簡単に実装してみようと思います。文理問わず気軽に見てもらえるように、必要な知識の仮定は必要としません。
プログラミング言語Pythonの実行環境はgoogle colaboratoryを利用します


カエサル暗号とは?

カエサル暗号(またはシーザー暗号)とは、古代ローマの皇帝ユリウス・カエサルが使用していたといわれている歴史ある暗号です。
カエサル暗号は、複雑な処理が特になく非常にシンプルで分かりやすいのが大きな特徴です。
そのため、多くの暗号理論や暗号技術に関する書籍に登場しています。

カエサル暗号の原理と暗号化手順

まず、暗号化を行うためにベースとなる文(平文といいます)を準備します。
今回は、次の文を用意しました。

Hello World

カエサル暗号では、この分に対して、$${\underline{\text{あるルールと情報}}}$$をもとに暗号化を実行します。
では、先ほどの文章を、あるルールと情報をもとにカエサル暗号で暗号化してみましょう。暗号文は次のようになります。

Khoor Zruog

ここで、暗号化するために用いたあるルールと情報とは何でしょうか?
勘のいい方はお気づきかと思いますが、正解は、

  • ルール:注目しているアルファベットを後ろにずらす

  • 情報:移動はつ後ろのアルファベット

です。では、このルールと情報をもとにして、きちんと暗号化されているのか、実際に確かめてみましょう。AからZまでのアルファベットの順番は,

A B C D E F G H I J K L M N O P Q R S T U V W X Y Z

です。このアルファベットの順番をもとにして、「Hello World」を変換してみましょう。注意として、後ろに3つ移動したときに、Zを超えたら、Aに戻ってくるようにします。
実際に行うと、各アルファベットは、次のように変換されます。

$$
H \to I\to J\to K\\
e\to f\to g\to h\\
l\to n\to m\to o\\
o\to p\to q\to r\\
W\to X\to Y\to Z\\
r\to s\to t\to u\\
d\to e\to f\to g\\
$$

この変換結果に従うと「Hello World」は、「Khoor Zruog」となりました!

暗号化方法がわかってしまうと、あっけなく感じるのではないでしょうか。しかし、何も知らない人が「Khoor Zruog」をみたとして、初見で「Hello World」だとわかる人は少ないでしょう。
暗号を用いて秘密の情報を共有するには、暗号化に用いた情報(ここでは、後ろに3つずらす)を秘密裏に保持することが重要だとわかります。

ところで、この暗号文に対して3つ前に戻せば、もとの「Hello World」に戻すことができます。この作業を復号といいます。

カエサル暗号と数学の関係

Pythonでカエサル暗号を実装するにあたって、ずらす(シフト)という作業について一回整理したいと思います。そのために、小学生の頃にやる余り(剰余)を思い出しましょう。

さて、A~Zまでのアルファベットは全部で26個あります。
このアルファベットに「Aには0」、「Bには1」、…、「Zには25」という風に0~25の数字を割り振ってみます。

A B C D E F G H I J K L M N O P Q R S T U V W X Y Z
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25

実はカエサル暗号で行った右にずらすという行為は、余りの計算で表すことができます。
注目しているアルファベットに対応した番号をxと、秘密の情報(移動させる数)をnと表すとします。そして、eを暗号化されたアルファベットに対応する数字を表すとします。この時、暗号化と復号化は数式で書くと

$$
暗号化された文字Encode(x) = (x + n) mod 26\\
復号された文字Decode(e) = (e - n) mod 26
$$

と表せます。modは余りを表しています。よりわかりやすく書くと

$$
Encode(x) = (x+n)\div 26の余り\\
Decode(x) = (x-n)\div 26の余り
$$

ということです。

例を通して、一緒に対応していることを確認しましょう。

(例1)
文字「H」に対応している数字は「7」でした。「7」に移動させる数字「3」を足すと「10」になります。「10÷26 = 0 余り 10」です。
そして、余り「10」に対応する文字は「K」です。
HからKに暗号化できた事がわかると思います。

(例2)
他にも,「Z」に対応する数値は、「25」で「25 + 3 = 28」になります。なので、「28÷26 = 1 余り 2」です。よって、「C」に変換されます。
文字で考えても「Z→A→B→C」ですので、きちんと変換されていることが確認できます。

では、この余りと暗号化の関係を使ってカエサル暗号で暗号化するプログラムを書いてみたいと思います。

Pythonで実装する

では、実際にカエサル暗号を実装するプログラムを書いてみます。
仮定として、「」 (空白)と「.」(コロン)以外の特殊な文字は平文に入っていないとします。また、文章は改行で区切られているとさせていただきます。
プログラムの処理は、特段気にしなくていいので、下に示すコードをColaboratoryのセルにコピーペーストして実行してみてください。

注意:筆者はプログラミング等に関してまだまだ勉強中なので、処理や変数名等におかしいところがあってもご自愛いただければ幸いです。

Part1. 暗号化・復号部分

まず、アルファベット1文字に対する暗号化部分を以下に示します。英文を考えると、単語の最初の文字が大文字である可能性もあるので、それに応じて暗号化します。

#暗号化関数
def enc_dec_c(c, sift_num, mode):#1文字ずらす
  alf = ["a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o","p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z"]
  N = len(alf)
  numbers = [i for i in range(N)]

  flag = -1 #init flag
  if c.isupper():#大文字ならば
    flag = 1
    c_after = c.lower()#小文字に変換
  else:#小文字ならば
    flag = 0
    c_after = c#そのまま

  x = alf.index(c_after)#対象の文字が入っているところの番号を取得
  if(mode == 0):
    enc_index = (x + sift_num) % N #エンコード
  else:
    enc_index = (x - sift_num) % N #デコード

  if flag == 1:
    return alf[enc_index].upper()#大文字に戻す
  else:
    return alf[enc_index] #小文字に戻す

Part2. カエサル暗号の部分

文字を読み込み、リスト化したデータから1文字だけ取り出して、暗号化します。

 #カエサル暗号 def caecer(l, key, mode):
  enc_list = []
  for i in l:
    list_string = []
    for j in i:
      string = ""
      for k in j:
        #文字の暗号化
        string = string + enc_dec_c(k, key, mode)
      list_string.append(string)
    enc_list.append(list_string)
  return enc_list

Part2. 表示の部分

暗号化された文章の表示を行う関数です。

#文を出力する関数
def show(l):
  enc_sentence = ""
  for i in l:
    enc_sentence = (" ").join(i)
    enc_sentence = enc_sentence + "."
    print(enc_sentence) #暗号文の表示

Part3. データ加工をする部分

文章を読み込むために、データを加工して扱いやすくします。

#データを読み込むために加工
def data_processing(s):
  sample_list = s.split("\n")

  count = 0
  for i in sample_list:
    sample_list[count] = i.replace(".", "")
    count += 1
  
  split_list = []
  for i in sample_list:
    split_list.append(i.split(" "))
  return split_list

Part4. 平文を指定する部分と暗号化・復号を行う部分

先ほどのデータ加工用の関数で、データを加工します。

#平文
sample_text = """Nice to meet you.
My name is A.
I am from Japan and am currently working as a graduate student at B University."""


split_list = data_processing(sample_text)

続いて暗号化してみましょう。

# 暗号化
key = 3
mode = 0 #エンコード
enc_list = caecer(split_list, key, mode)
show(enc_list)

復号の時は、modeを0以外にすれば大丈夫です。

#復号
mode = 1 #デコード
dec_list = caecer(enc_list, key, mode)
show(dec_list)

実行してもらえば、次のような文章が出力されます。

Qlfh wr phhw brx.
Pb qdph lv D.
L dp iurp Mdsdq dqg dp fxuuhqwob zrunlqj dv d judgxdwh vwxghqw dw E Xqlyhuvlwb.

ちゃんとカエサル暗号が実装できました!

おまけ
このカエサル暗号は、後ろに3つずらしています。「後ろにn個ずらす」に対応している変数がkeyとなっています。
この変数keyの部分を変えて遊んでみてください。(例えば、key = 13など)

まとめ

カエサル暗号は、アルファベットをずらして暗号化を行うとてもシンプルな暗号方式でした。

今回、初投稿の題材として、カエサル暗号について記事を書いてみましたが、どうだったでしょうか?
単純でありつつも、数理の要素(シフトと余りとの関係)も含まれており、個人的にとても好きな暗号です。
この記事を読んでおられるの方にも、「面白い」や「興味深い」と感じていただけたら幸いです。

これからも、数理、技術等に関する記事を書いていこうかなと思いますので、よろしくお願いいたします。

この記事が気に入ったらサポートをしてみませんか?