✲゚。.ヾ(⌒(ノ'ω')ノ☆.。

変色系男子の日常。

シーザー暗号を Ruby で解読する

はじめに

暗号について勉強し始めた経緯

「暗号技術入門 秘密の国のアリス」というテキストを読み始めました。

新版暗号技術入門 秘密の国のアリス

新版暗号技術入門 秘密の国のアリス

なぜこのテキストを読み始めたかというと、

とつぶやいたら、結城浩さんご本人から

というリプライを頂いたので、急遽 AmazonKindle ストアで結城さんの著書を漁り、最近セキュリティに関心があるのでこのテキストを購入してみたというわけです。本当は 数学ガール シリーズをまず読もうと思っていたんですけどね。

おかげさまで「『読みたい読みたい詐欺』脱却詐欺」から脱することができました。

以下、テキスト内にあったクイズ (序盤の章の簡単なものですが) を解いてみようと思います。

シーザー暗号の解読

シーザー暗号とは

シーザー暗号 (Caesar cipher) とは、ジュリアス・シーザー (ガイウス・ユリウス・カサエル) が使っていたといわれている暗号です。ちなみにシーザーとは紀元前 100 年に生まれたローマの政治家・軍人です。

暗号といってもシーザー暗号での暗号化の仕組みは非常に単純です。平文で使われているアルファベットをそれぞれ一定数 (基本的には 3 文字) ずらすだけです。そして、暗号文のアルファベットをそれぞれ逆方向に同じ文字数だけずらせば復号できます。

Ruby で解読する

テキスト内に「シーザー暗号で暗号化された PELCGBTENCUL という暗号文を解読せよ」というクイズがありました。これを Ruby を使って ブルート・フォース・アタック で解いてみます。

ブルート・フォース・アタックとは、考えうるすべての組み合わせ試す暗号解読方法です。つまりはゴリ押しです。シーザー暗号の場合、アルファベットは 26 種類なので、ずらしうる文字数も 0 〜 25 個の 26 通りです。人間が手動で試すことのできるレベルの数なので、コンピュータで解けば一瞬ですね。

def decrypt_with_caesar(ciphertext, key_number)
  alphabets = Array('A'..'Z')

  ciphertext.each_char.inject('') do |decrypted_string, char|
    index = (alphabets.index(char) - key_number) % alphabets.length
    decrypted_string << alphabets[index]
  end
end

def brute_force_attack(ciphertext)
  (0..26).map { |n| decrypt_with_caesar(ciphertext, n) }
end

この brute_force_attack というメソッドを実行してみます。(Awesome Print という Gem の ap メソッドを利用して結果を整形して出力しています。)

ap brute_force_attack('PELCGBTENCUL')
[
    [ 0] "PELCGBTENCUL",
    [ 1] "ODKBFASDMBTK",
    [ 2] "NCJAEZRCLASJ",
    [ 3] "MBIZDYQBKZRI",
    [ 4] "LAHYCXPAJYQH",
    [ 5] "KZGXBWOZIXPG",
    [ 6] "JYFWAVNYHWOF",
    [ 7] "IXEVZUMXGVNE",
    [ 8] "HWDUYTLWFUMD",
    [ 9] "GVCTXSKVETLC",
    [10] "FUBSWRJUDSKB",
    [11] "ETARVQITCRJA",
    [12] "DSZQUPHSBQIZ",
    [13] "CRYPTOGRAPHY",
    [14] "BQXOSNFQZOGX",
    [15] "APWNRMEPYNFW",
    [16] "ZOVMQLDOXMEV",
    [17] "YNULPKCNWLDU",
    [18] "XMTKOJBMVKCT",
    [19] "WLSJNIALUJBS",
    [20] "VKRIMHZKTIAR",
    [21] "UJQHLGYJSHZQ",
    [22] "TIPGKFXIRGYP",
    [23] "SHOFJEWHQFXO",
    [24] "RGNEIDVGPEWN",
    [25] "QFMDHCUFODVM",
    [26] "PELCGBTENCUL"
]

ちなみに配列のインデックスが暗号化時にずらした文字数に相当します。

この結果を見ると 13 番目が CRYPTOGRAPHY という意味のある単語 (英語で「暗号」という意味) なので、これが解答ですね。