シーザー暗号とBFAによる簡単な解読

2年目の早岐です。

 

前回のブログではヴィジュネル暗号の簡単な実装と解読を行いました。
今回は前回よりは簡単になりますが、シーザー暗号の実装とBFA(Brute-Force Attack = 力任せな攻撃)での解読をしてみます。

 

余談ですが、暗号は大学生の頃に集中講義で勉強しました。
正月前に2日で座学と実験含めて3単位だった気がします。
楕円曲線暗号の実装が大変だったのを覚えています。

 

シーザー暗号とは

シーザー暗号は、古代ローマのユリウス・カイサル(ジュリアス・シーザー)が使用したと伝えられています。[1]
シーザー暗号の基本は、文字を一定数ずらすことにあります

 

鍵が「3」だとすると、元の文字(平文)を、この辞書上で3つ後ろにシフト(移動)させます。
その移動先の文字が暗号文になります。

 

例:平文「あいうえお」の暗号化

平文の文字元の位置シフト(+3)暗号文の文字
1番目番目
2番目番目
3番目番目
4番目番目
5番目番目

 

暗号を作ってみよう

平文:”Day before yesterday I saw a rabbit , and yesterday a deer , and today , you”
(Robert F. youngの”The Dandelion girl”から引用をしています。とても好きなフレーズです。)

鍵:6

 

今回もpythonを使います。
GoogleColaboratoryやPyWebで動くと思いますので、ぜひ試してみてください。

import string 

#ABCDEF...... 
ALPHABET = string.ascii_uppercase 
#abcdef...... 
alphabet = string.ascii_lowercase

#平文
text = "Day before yesterday I saw a rabbit , and yesterday a deer , and today , you" 
#鍵
key = 6  
#暗号文
ciphertext = "" 
ciphertext_index = "" 

for char in text: 
  # 大文字の場合の処理 
  if char in ALPHABET: 
    ciphertext_index = ALPHABET.find(char) 
    ciphertext_index = (ciphertext_index + key) % len(ALPHABET) 
    ciphertext += ALPHABET[ciphertext_index ] 

  #小文字の場合 
  elif char in alphabet: 
    ciphertext_index = alphabet.find(char) 
    ciphertext_index = (ciphertext_index + key) % len(alphabet) 
    ciphertext += alphabet[ciphertext_index ] 

  #それ以外の場合はそのまま追加 
  else:  Ciphertext += char 

#暗号文の出力
print(Ciphertext) 

 

出来た暗号文は以下の通りです。

Jge hkluxk ekyzkxjge O ygc g xghhoz , gtj ekyzkxjge g jkkx , gtj zujge , eua

 

解読をしてみよう

今回は簡単な暗号なので、BFA(Brute-Force Attack = 力任せな攻撃)で解読をしてみましょう。

 

BFAとは?

文字通り、力任せな攻撃です。
「下手な鉄砲も数撃ちゃ当たる」戦法です

 

例えば、スマホのロック画面を想像してください。
パスワードが4桁で、数字の認証なら、10^4=10000通り試せば解除ができてしまいます。

 

BFAで暗号文を解読しよう

今回はアルファベットなので、26回試して意味の分かる文章ができたら終わりです。

import string

ALPHABET = string.ascii_uppercase
alphabet = string.ascii_lowercase

text = "" 
text_index ="" 
ciphertext = "Jge hkluxk ekyzkxjge O ygc g xghhoz , gtj ekyzkxjge g jkkx , gtj zujge , eua" 

for i in range(len(alphabet)): 
  text = "" 
    for j in range(len(ciphertext)): 
      char = ciphertext[j] 

      if char in alphabet: 
        text_index = alphabet.find(char) 
        text_index = (text_index + (len(alphabet)-i) ) % len(alphabet) 
        text += alphabet[text_index]
      elif char in ALPHABET:
        text_index = ALPHABET.find(char) 
        text_index = (text_index + (len(ALPHABET)-i) ) % len(ALPHABET) 
        text += ALPHABET[text_index]
      else: 
        text += char 

  print("鍵:"+str(i)) 
  print("平文:" + text +"\n")

 

実行をすると以下のように出力されます。

鍵:0
平文:Jge hkluxk ekyzkxjge O ygc g xghhoz , gtj ekyzkxjge g jkkx , gtj zujge , eua

鍵:1
平文:Ifd gjktwj djxyjwifd N xfb f wfggny , fsi djxyjwifd f ijjw , fsi ytifd , dtz

鍵:2
平文:Hec fijsvi ciwxivhec M wea e veffmx , erh ciwxivhec e hiiv , erh xshec , csy

鍵:3
平文:Gdb ehiruh bhvwhugdb L vdz d udeelw , dqg bhvwhugdb d ghhu , dqg wrgdb , brx

鍵:4
平文:Fca dghqtg aguvgtfca K ucy c tcddkv , cpf aguvgtfca c fggt , cpf vqfca , aqw

鍵:5
平文:Ebz cfgpsf zftufsebz J tbx b sbccju , boe zftufsebz b effs , boe upebz , zpv

鍵:6
平文:Day before yesterday I saw a rabbit , and yesterday a deer , and today , you

鍵:7
平文:Czx adenqd xdrsdqczx H rzv z qzaahs , zmc xdrsdqczx z cddq , zmc snczx , xnt


....

鍵:24
平文:Lig jmnwzm gmabmzlig Q aie i zijjqb , ivl gmabmzlig i lmmz , ivl bwlig , gwc

鍵:25
平文:Khf ilmvyl flzalykhf P zhd h yhiipa , huk flzalykhf h klly , huk avkhf , fvb

 

26個の出力をみると、意味が分かるのが鍵が6の平文です。
よって、鍵は6だ!といえます。

 

まとめ

今回はシーザー暗号とBFAによる解読を行いました。
BFAの説明で、スマホを例に挙げましたが人の手で作業をすると膨大な時間がかかってしまいます。
当たり前ですが、攻撃者はコンピュータを用いて攻撃をしてきます。

この機会にもう一度、ご自身のパスワードを見直してみてください。

 

参考

[1] 大澤 弘典 暗号の教材化についての一考察 日本数学教育学会誌 2001 年 83 巻 7 号 p. 10-17