1. ホーム
  2. コース一覧
  3. セキュリティ基礎コース
  4. シーザー暗号で暗号化するプログラムを作成しよう!

セキュリティ基礎コース1/8

シーザー暗号で暗号化するプログラムを作成しよう!

こちらでは、暗号化方式のひとつであるシーザー暗号について解説します。

シーザー暗号とは?

シーザー暗号は、シンプルな暗号化方式であり、世界的にも広く知られている暗号です。

名前の由来とカエサル式暗号

シーザー暗号は、紀元前から使われている暗号で、古代ローマの軍事的指導者だったガイウス・ユリウス・カエサル(Gaius Julius Caesar)も使用していました。

彼の名であるカエサル(Ceasar)は、英語では「シーザー」と読むことから、シーザー暗号という名前がつけられました。

そのためシーザー暗号は、別名「カエサル式暗号」と呼ばれることもあります。

シフト暗号

また、シーザー暗号は、平文の文字を決められた文字数分だけずらす(以降、シフトする) 単一換字式暗号 という暗号化の方式をとることから、「シフト暗号」とも呼ばれています。

アルファベットに限らず、日本語やハングル文字のような文字であれば、なんでも利用可能です。

シーザー暗号の仕組み

シーザー暗号の仕組みは、文字をアルファベット順に応じて文字をシフトすることです。

向きとしては、右にシフトする方が一般的とされています。そして、何文字シフトするかを「シフト数」と呼びます。シフト数は、必ずしも特定の数に決まっているわけではなく、暗号化する人によって区々です。

ただし、アルファベットに対して使用するという前提で作られているため、基本的に0~26のいずれかになります。

ROT Nとは?

ROT{シフト数}とすることで、何文字ずらすシーザー暗号なのかを表します。読み方はロット・{シフト数}です。たとえば、シフト数7であれば、ROT7(ロット・セブン)です。

有名なもので言うと、ROT13があります。

以下の対応表では、シフト数が5(ROT5)であるときの暗号化されたアルファベットを示しています。

通常のアルファベット : 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
暗号化アルファベット : F G H I J K L M N O P Q R S T U V W X Y Z A B C D E

5文字分ずれていることが分かりますね。平文のAは暗号文ではFに置き換わり、GはLに置き換わるといった状態です。 (平文とは、暗号化されていない生の文章やデータのことです。)

それでは、実際にカエサルの名前をシーザー暗号(シフト数=5)で暗号化してみましょう。

平文 : Gaius Julius Caesar
暗号 : Lfnzx Ozqnzx Hfjxfw

次は、文章を暗号化してみましょう。

平文 : Can you decipher this code?
暗号 : Hfs dtz ijhnumjw ymnx htij?

シーザー暗号で暗号化したものを復号する(もとの平文に戻す)場合には、対応表を作成して解読することも可能です。

しかし、それでは暗号が非常に長い場合には長い時間と多大な労力が必要となります。これはとても骨の折れる作業です。

現代では、シーザー暗号における暗号化・復号を簡単に行える便利なツールやサイトがあるため、そちらを利用されることをオススメします。

暗号化と復号

第三者から平文の内容を知られないために、何らかの暗号化方式(どのように暗号化するかというルール)に従って別の形に変えることを暗号化と言います。暗号化された文字列は暗号文と呼びます。

また、暗号文をもとの状態(平文)に戻すことを復号と言います。これらの暗号化や復号には、「鍵」が必要となります。今回のシーザー暗号の場合であれば、シフト数が鍵にあたります。

シーザー暗号における暗号化は、シフト数に従って行われます。それでは、復号はどのように行うのでしょうか。

こちらも単純です。アルファベットの場合であれば、全26文字ですから、26-{シフト数}をした数を復号のシフト数として復号を行います。

以下のように、ROT3であれば、復号のシフト数は23(26-3)と言うことになります。

This is ROT3 cipher.
[↓ ROT3で暗号化します]
Wklv lv URW3 flskhu.
[↓ ROT23で復号します]
This is ROT3 cipher.

ROT13とは

シフト数が13のシーザー暗号のことです。ROT13という名前は、”Rotate by 13 places”の略とされています。ROT13では、右に13文字シフトするというルールになっています。

12や15ではないのは、英語のアルファベットが全26文字であり、そのちょうど真ん中が13だからです。そのため、ROT13はシーザー暗号の中でもっとも広く知られています。

対応表は以下のようになります。

通常のアルファベット(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
N O P Q R S T U V W X Y Z A B C D E F G H I J K L M
ROT13で暗号化したアルファベット(N~M)

Unix系のOSには、文字列を置き換えるtrコマンドがあります。こちらを使うことで、ROT13による暗号化を行うことができます。

実際にtrコマンドを使って確認してみましょう!

# 'rot13 translator'をROT13で暗号化します。
echo 'rot13 translator' | tr A-Za-z N-ZA-Mn-za-m
ebg13 genafyngbe
# 暗号文を復号します。
echo 'ebg13 genafyngbe' | tr A-Za-z N-ZA-Mn-za-m
rot13 translator

それでは、標準入力を受け取った文字列をtrコマンドを使ってROT13で暗号化するシェルスクリプトを作成してみましょう。

# rot13.shというシェルスクリプトを作成します。
vi rot13.sh
========================================================================================
#!/usr/bin/zsh    #こちらはshebang(シバン)という大切なおまじないです。
echo -n INPUT:    #こちらで入力(文字列)を受け付けます。
read str          #readによって受け取った文字列をstrという変数に代入しています。
echo $str | tr A-Za-z N-ZA-Mn-za-m    #strに格納された文字列をROT13で暗号化して出力します。
========================================================================================
# rot13.shを実行してみましょう。
./rot13.sh
INPUT:hello
uryyb
# 暗号文を復号します。
./rot13.sh
INPUT:uryyb
hello

他にも、FreeBSD(Unix系のOSのひとつ)には、標準でrot13コマンドが用意されていたりします。

trコマンドについては、別ページにて紹介しています。

https://envader.plus/course/16/scenario/1019

シーザー暗号が必ずしも解読できないケースとは

これまで見てきてお気づきになられたかもしれませんが、シーザー暗号のような単一換字式暗号はシフト数が決まっています。そのため、シフト数が分かってしまえば簡単に暗号を解読できてしまいます。つまり、暗号としてはシンプルすぎてあまり意味がありません。

カエサルが使用したかつての古代ローマでは十分に有効な暗号として機能していましたが、今日ではシーザー暗号そのものは有効であるとは言えません。

しかし、シーザー暗号には解読できないケースが存在します。それはどのような場合でしょうか。

(※ここでは「解読する=復号によって一意の平文を突き止める」こととします。)

答えは、平文が極端に短い場合です。

実際に第三者が暗号を解読しようとするときを考えてみましょう。

初めに暗号を見たとき、シフト数が分かっていない状態から解読がスタートします。

(※本来は、そもそもどういった暗号方式で暗号化されているのかすらわからない状態からですが、ここでは省略しています。)

たとえば、”MPQY”という暗号があったとします。このとき、以下の候補が考えられます。

  • シフト数=2:”KNOW”
  • シフト数=12:”ADEM”(急性散在性脳脊髄膜炎)
  • シフト数=24:”ORSA”(ラテン語で女性単数形を表す単語。英語の”she”にあたります。)

同じように、”ALIIP”という暗号があったとすると、以下の候補があげられます。

  • シフト数=4:”WHEEL”
  • シフト数=9:”JURRY”(主に男性につけられる名前)
  • シフト数=23:”DOLLS”

このように、あまりにも短い暗号の場合には、複数の候補が可能性としてあげられることが分かります。

ただし、これ自体で実用的であるかどうかという観点から言えば、なかなか厳しいでしょう。いくつかの候補に絞り込んだ時点で、それらを1つずつ試していけばセキュリティは突破されてしまいますから、相変わらず有効であるとは言えません。

Pythonでシーザー暗号のプログラムを作成しよう!

上記では、文字列を渡すとROT13で暗号化してくれるシェルスクリプトを作成しました。

これと同様なものを、Pythonで実装することができます。ソースコードは以下になります。 (もちろん、C言語などでも実装は可能です。)

# ceasar.pyという名前のPythonスクリプトを作成します。
import string

def ceasar(text, shift, alphabets):

  def shift_alphabet(alphabet):
    return alphabet[shift:] + alphabet[:shift]
  
  shifted_alphabets = tuple(map(shift_alphabet, alphabets))
  final_alphabet = ''.join(alphabets)
  final_shifted_alphabet = ''.join(shifted_alphabets)
  table = str.maketrans(final_alphabet, final_shifted_alphabet)
  return text.translate(table)

plain_text = input('>>')
print(ceasar(plain_text, 13, [string.ascii_lowercase, string.ascii_uppercase, string.punctuation]))

ターミナルで実行してみます。

python ceasar.py
>>rot13 cipher
ebg13 pvcure

無事、暗号化できましたね!

上の例ではROT13で作成しましたが、スクリプト最終行の“13”を他の数字に置き換えれば、他のシフト数のシーザー暗号で暗号化することができます。他の数字でも試してみてください。

Pythonについては、次の解説記事をご参照ください。

https://envader.plus/course/8/scenario/1071

シーザー暗号のまとめ

今回は、シーザー暗号について解説しました。シェルスクリプトやPythonスクリプトを実際にご自身で作成してみると、楽しみながら学習できると思います。

暗号技術はわたしたちの身の回りのさまざまなところで機能しており、情報セキュリティにおいて非常に重要な役割を担っています。シーザー暗号以外にも様々な方式がありますので、是非挑戦してみましょう。

問題を解くためには、十分な画面サイズのPC環境をご利用下さい。