お知らせ

ただいま、シンタックスハイライターの設定を見直しております。
プログラムが見にくくなっているページがありますが、ご容赦ください。

シーザー暗号を実装してみる

情報セキュリティ

こんにちは。前回に続いて暗号を実装してみたいと思います。今回はシーザー暗号です。あわせてほとんど同じアルゴリズムのシフト暗号も実装します。

シーザー暗号・シフト暗号とは

紀元前1世紀に登場したとても由緒正しい(?)暗号だそうです。ジュリアス・シーザー(Julius Caesar:ユリウス・カエサル)が頻繁に利用していたことでこの名前が付いたそうです。お約束としてアルファベットを3文字分ずらすと決めておくことにより、送り手は暗号化し、受け手は復号ができます。文字をずらす(シフトする)ことからシフト暗号ともよばれています。シフトした文字数がわかるように、3文字シフトした場合ROT3、13文字シフトした場合ROT13と表記することにします。

参考としたリンクを貼っておきます。

暗号化するプログラム(1)

それでは、相変わらずのPythonで実装してみます。

def encrypt( text, original, encode ):
  result = ''
  for letter in text:
    index = original.index( letter )
    result += encode[index]
  return result


if __name__ == '__main__':
  plain_alphabet  = 'abcdefghijklmnopqrstuvwxyz'
  cipher_alphabet = 'defghijklmnopqrstuvwxyzabc'

  plain_text  = 'practicemakesperfect'
  cipher_text = encrypt( plain_text, plain_alphabet, cipher_alphabet )
  decode_text = encrypt( cipher_text, cipher_alphabet, plain_alphabet )
  print( plain_text )
  print( cipher_text )
  print( decode_text )
  print()


  plain_text  = 'thepenismightierthanthesword'
  cipher_text = encrypt( plain_text, plain_alphabet, cipher_alphabet )
  decode_text = encrypt( cipher_text, cipher_alphabet, plain_alphabet )
  print( plain_text )
  print( cipher_text )
  print( decode_text )

なんということでしょう!デジャブです。これは既視感というものです。前回のプログラムを使い回したといわないでください。ちゃんとシーザー暗号のために書き直しています。11行目だけですけれど・・・単一換字式暗号の一種で、換字の規則がランダムではなくて、ここでは3文字分シフトしているので、単一換字式暗号のプログラムが使えてしまいます。一応実行結果を載せておきます。

practicemakesperfect
sudfwlfhpdnhvshuihfw
practicemakesperfect

thepenismightierthanthesword
wkhshqlvpljkwlhuwkdqwkhvzrug
thepenismightierthanthesword

暗号化するプログラム(2)

先ほどのプログラムは、3文字分シフトすることで固定されていました。それではシフト暗号としては不十分なので、シフトする文字数を自由に変更できるようにします。プログラム中のnは、左方向にシフトした文字数です。

def encrypt( text, n ):
    result = ''
    for letter in text:
         result += chr( ( ord(letter) - ord('a') - n ) % 26 + ord('a') )
    return result

def decrypt( text, n ):
    return encrypt( text, -n )


if __name__ == '__main__':
  plain_text  = 'practicemakesperfect'
  print( plain_text )

  for n in range(26):
    cipher_text = encrypt( plain_text, n )
    decode_text = decrypt( cipher_text, n )
    print( '--- ROT' + str(n) + ' ---' )
    print( 'encrypt : ' + cipher_text )
    print( 'decrypt : ' + decode_text )

4行目が変換している箇所です。ord(letter) – ord('a’)により、a=0、b=1、…、y=24、z=25としています。左方向にn文字分シフトさせるので、文字と対応している値からnを引いています。単に引くだけでは、特にはじめの方のアルファベットは値がマイナスになってしまいます。そこで、26で割った余りを求めることにより、0~25の範囲に収まるようにしています。そのうち書くと思いますが、ぐるぐる回転するものを扱うには剰余を使うととても便利です。(ぐるぐると書いたときに、「ぐるぐるカーテン」と「ぐるぐる大帝国入間店」が予測変換に出てきた衝撃が大きくて、つい脱線して書いてしまいました。ぐるぐる大帝国入間店はリサイクルショップなのかな…?)

復号するには、逆方向にシフトすればよいので、8行目では、ーn文字シフトする暗号化として関数encryptを呼び出しています。

実行結果は次になります。

practicemakesperfect
--- ROT0 ---
encrypt : practicemakesperfect
decrypt : practicemakesperfect
--- ROT1 ---
encrypt : oqzbshbdlzjdrodqedbs
decrypt : practicemakesperfect
--- ROT2 ---
encrypt : npyargackyicqncpdcar
decrypt : practicemakesperfect
--- ROT3 ---
encrypt : moxzqfzbjxhbpmbocbzq
decrypt : practicemakesperfect
--- ROT4 ---
encrypt : lnwypeyaiwgaolanbayp
decrypt : practicemakesperfect
--- ROT5 ---
encrypt : kmvxodxzhvfznkzmazxo
decrypt : practicemakesperfect
--- ROT6 ---
encrypt : jluwncwygueymjylzywn
decrypt : practicemakesperfect
--- ROT7 ---
encrypt : iktvmbvxftdxlixkyxvm
decrypt : practicemakesperfect
--- ROT8 ---
encrypt : hjsulauwescwkhwjxwul
decrypt : practicemakesperfect
--- ROT9 ---
encrypt : girtkztvdrbvjgviwvtk
decrypt : practicemakesperfect
--- ROT10 ---
encrypt : fhqsjysucqauifuhvusj
decrypt : practicemakesperfect
--- ROT11 ---
encrypt : egprixrtbpzthetgutri
decrypt : practicemakesperfect
--- ROT12 ---
encrypt : dfoqhwqsaoysgdsftsqh
decrypt : practicemakesperfect
--- ROT13 ---
encrypt : cenpgvprznxrfcresrpg
decrypt : practicemakesperfect
--- ROT14 ---
encrypt : bdmofuoqymwqebqdrqof
decrypt : practicemakesperfect
--- ROT15 ---
encrypt : aclnetnpxlvpdapcqpne
decrypt : practicemakesperfect
--- ROT16 ---
encrypt : zbkmdsmowkuoczobpomd
decrypt : practicemakesperfect
--- ROT17 ---
encrypt : yajlcrlnvjtnbynaonlc
decrypt : practicemakesperfect
--- ROT18 ---
encrypt : xzikbqkmuismaxmznmkb
decrypt : practicemakesperfect
--- ROT19 ---
encrypt : wyhjapjlthrlzwlymlja
decrypt : practicemakesperfect
--- ROT20 ---
encrypt : vxgizoiksgqkyvkxlkiz
decrypt : practicemakesperfect
--- ROT21 ---
encrypt : uwfhynhjrfpjxujwkjhy
decrypt : practicemakesperfect
--- ROT22 ---
encrypt : tvegxmgiqeoiwtivjigx
decrypt : practicemakesperfect
--- ROT23 ---
encrypt : sudfwlfhpdnhvshuihfw
decrypt : practicemakesperfect
--- ROT24 ---
encrypt : rtcevkegocmgurgthgev
decrypt : practicemakesperfect
--- ROT25 ---
encrypt : qsbdujdfnblftqfsgfdu
decrypt : practicemakesperfect

シーザー暗号の弱点

シーザー暗号は単一換字式暗号の一種なので、単一換字式暗号と同じ弱点を抱えています。さらに、単に文字をシフトしているだけなので、総当たりで調べて文が読めるようになったものが平文であると考えられます。アルファベット小文字だけに限定されていれば、たったの25パターン(ROT0は暗号化されていないので)調べるだけで済んでしまいます。

最後に1つ暗号を書いておきます。有名な曲の歌詞の一部を暗号化しました。(スペースを除き、すべて小文字で表記してから暗号化しています)

qeqttiteigatwdmgwc

それでは、今回はこれでおしまい。それではまた。

この記事を書いた人
春日井 優

高校で情報科という教科を担当しています。以前は数学科も担当していました。(今でも数学科の教員免許状は有効です。)プログラムを覚えたのは、「ゲームセンターあらし」という漫画のキャラクターがBASICを解説する「こんにちはマイコン」を読んだことがきっかけでした。

Posted by kasugai