ヴィジュネル暗号 簡単な作成と解析
1年目の早岐です。
前回のブログではGASの簡単な使い方を紹介しました。
前回の記事で広く浅く書いてしまったので、今回は別の記事にしようと思います。
今回はタイトルにもあるように、簡単に暗号に触れてみようと思います。
暗号と言えば、順番を置き換えた「シーザー暗号」や文字を別の文字で置き換える「単一換字暗号」、ナチスドイツの「エニグマ」、詳しい人だと「楕円曲線暗号」等が挙がると思います。
今回は暗号の中でもヴィジュネル暗号について取り扱ってみます。シーザーのように簡単すぎず、エニグマのように難しくない程度なので選びました。
今回紹介する暗号はpythonを使います。
GoogleColaboratoryやPyWebで動くと思いますので、ぜひ試してみてください。
ヴィジュネル暗号の簡単な歴史
ビジュネル暗号は単一換字暗号の脆弱性を克服するために生まれたものです。平方換字式暗号とも呼ばれることがあります。この暗号はフランスの外交官であるブレーズ・ド・ヴィジュネルが考案し、1586 年に『秘密の書記法について』で発表されたものになります。ヴィジュネルが暗号を発表した時代では、ユグノー戦争 (1562~1598) が起こっていました[1]。
単一文字置換暗号に関してはabcd…にそれぞれ1字づつ対応しているので、鍵の空間が26!と小さいのでブルートフォースアタック(しらみつぶし)で人力で簡単に解けてしまいます。ヴィジュネル暗号は表に従って変換されます。1文字に対して26通り考えられます。なので頻度解析等を駆使すれば、簡単に解けてしまいます。
ヴィジュネル暗号の簡単な説明
ヴィジュネル暗号については、鍵とヴィジュネル方陣を使って暗号化を行います。
以下のコードでヴィジュネル方陣を出力してみましょう。
import string #ABCDEF...... ALPHABET = string.ascii_uppercase #abcdef...... alphabet = string.ascii_lowercase print( ' |'+ alphabet ) print( '-+--------------------------') for i in range(26): l = ALPHABET[i]+ '|' for j in range(26): l += alphabet[ (i + j ) % len(alphabet) ] print(l)
実行をすると以下の表が出来上がります。
例えば、
鍵が「B」という文字で平文(暗号化する前の文字)が「a」の時、暗号文は「b」になります。
鍵が「B」という文字で平文(暗号化する前の文字)が「m」の時、暗号文は「n」になります。
鍵の長さが1の時に単一換字暗号になります
簡単に実装をしてみよう
今回は「簡単」にするため「置換するのはアルファベットのみ」とします。そのため、空白や記号はそのままにします。
平文はお好きなもので試してみてください。
今回は私の好きな中勘助氏の「銀の匙」(この小説は著作権が切れています)のとある一部分を英訳し平文とします。
日本語の平文
お国さんの櫛は赤く塗つて菊の花の蒔絵がしてあつた。緋と水色の縮緬でこしらへた薬玉の簪ももつてゐた。お国さんはなにか新しいのを買つてもらふと自慢してみせておきながらよく見ようとすれば袂へかくしたりして人を焦らせる。私はそんなものを見るたんびに自分が女に生れなかつたことをくやみ、また男はなぜ女みたいに綺麗にしないのだらうと思つた。
Google翻訳した結果
Okuni’s comb was painted red and decorated with chrysanthemum flowers. She also had a hairpin made of scarlet and light blue crepe with a medicine ball and a kusudama pattern. Okuni would brag about having someone buy her something new, but when people tried to get a closer look, she would hide it in her sleeve, making people anxious. Whenever I saw things like that, I regretted not being born a woman, and wondered why men didn’t dress as beautifully as women.
鍵を「KANSUKE」としましょう。
鍵は平文の大きさだけ繰り返します(KANSUKEKANSUKEKAN…)。
暗号化の簡易的なコード
以下のコードで暗号化を行います
import string #ABCDEF...... ALPHABET = string.ascii_uppercase alphabet = string.ascii_lowercase def cipher( text, key ): key = key.upper() Ciphertext = "" #暗号文 line_tate = "" line_yoko = "" i = 0 for char in text: # 大文字の場合の処理 i %= len(key) if char in ALPHABET: line_yoko = ALPHABET.index(char) line_tate = ALPHABET.index(key[i]) Ciphertext += ALPHABET[ ( line_yoko + line_tate ) % len(alphabet) ] #小文字の場合 elif char in alphabet: line_yoko = alphabet.index(char) line_tate = ALPHABET.index(key[i]) Ciphertext += alphabet[ ( line_yoko + line_tate ) % len(alphabet) ] else: # それ以外の場合はそのまま追加 Ciphertext += char i +=1 return Ciphertext; # 平文 text ="Okuni's comb was painted red and decorated with chrysanthemum flowers. She also had a hairpin made of scarlet and light blue crepe with a medicine ball and a kusudama pattern. Okuni would brag about having someone buy her something new, but when people tried to get a closer look, she would hide it in her sleeve, making people anxious. Whenever I saw things like that, I regretted not being born a woman, and wondered why men didn't dress as beautifully as women." key = 'KANSUKE' cipher_text=cipher( text, key ) print( cipher_text )
上記を実行すると以下の暗号文が得られました。
Ykhfc’w cbev aks husrdeq loh aav nimoesnoh wvlb grrlkuxxrezmg jvojwlc. Suw kpco zun k uscbtsn euni os mmeblrl krn yaarx bymy gbecw gmdh s winipaho layd krn n eewedneu tktgwlx. Oxmhs gohdx fbat ulset zufmxg kiwiynr vec hrj cswegzcxk nro, fet obor prgjvi teayn do yyd k pdicib ygiu, suw gselq bsho vl sr hrj cpoeiw, qkkvfa toocdy exxvgoc. Wuwhozor A ceg gzcxkc yaeo dhnl, M rryloxdeq hyx brahq loef k gozsh, knq qyrneewx ary eyx niqf’d nrrkm ec owuexsfhdfi ks oiwix.
平:Okuni’s comb…
鍵:Kansykekans…
暗:Ykhfc’w cbev…
解読の歴史的経緯とカシスキー検査
ヴィジュネル暗号が解読されたのは、1863年に刊行されたカシスキーの『暗号文と解読技術』とされてますが、これはバベッジのスゥエーツとの書簡より10年近く遅いとされています。後者は国家から秘匿依頼があったとするものであるところから解読者はカシスキーと扱われています[1]。
カシスキー検査については調査不足で、いい論文が見つかりませんでした。いい論文があればコメントをお願いします。
カシスキー検査では「鍵が例えば短い場合は同じ文字が出現する可能性が高い」ことからその弱点を突いたものになります。なので、ある文字列が繰り返し使われているところをリストアップする。例えば、「ABS」が文章中に2回出てきたとすれば、(その文字、何文字以降にでたか)とリストアップする。N文字以降に出たとすれば鍵の長さkeyに対して、
N%key==0である可能性が高いです。そのリストから最頻の最大公約数をとれば、その数が鍵の大きさである可能性が高いとうかがえます。
解読のために鍵をみつけてみよう
実際は暗号文から繰り返し表示される文字の距離を取得すればうまくいきます。プログラムでもいいですが、コード量が大きくなるので手作業で解読してみましょう。
私たちが暗号文に対して持っている情報は以下の通りです。
- アルファベットしか暗号化されていない
- ヴィジュネル暗号だということ
鍵を見つけられれば暗号の解読ができます。今一度、暗号文を見てみましょう。
Ykhfc’w cbev aks husrdeq loh aav nimoesnoh wvlb grrlkuxxrezmg jvojwlc. Suw kpco zun k uscbtsn euni os mmeblrl krn yaarx bymy gbecw gmdh s winipaho layd krn n eewedneu tktgwlx. Oxmhs gohdx fbat ulset zufmxg kiwiynr vec hrj cswegzcxk nro, fet obor prgjvi teayn do yyd k pdicib ygiu, suw gselq bsho vl sr hrj cpoeiw, qkkvfa toocdy exxvgoc. Wuwhozor A ceg gzcxkc yaeo dhnl, M rryloxdeq hyx brahq loef k gozsh, knq qyrneewx ary eyx niqf’d nrrkm ec owuexsfhdfi ks oiwix.
ここから鍵の大きさを調べていきます。
鍵の大きさの推測
繰り返し使われている文字を見ていきます。
前置詞のaは「k」として2回登場しています。文字数は空白と記号を込みで182(約数1,2,7,13,14,26,91,182)文字です。2回目との距離は131(約数1,131)文字です。
最大公約数が1なので、鍵の大きさが1である可能性が浮上しました。しかし、今回は「単一換字ではないだろう」という推測をしましょう(この時、同じ文字が2回以上鍵に含まれているといえます)。
次に「Suw」が連続しています。210文字離れていて182との公約数が1,7,14と分かりました。
鍵の大きさは7か14の可能性が出てきました。
このように鍵の大きさを推測していきます。
今回は先に進みたいので、鍵の大きさは7であるとして進めます。
鍵の推測その1
前置詞の「a」が置換されていることがわかっているので、最初の前置詞まで85です。85%7=1文字目が「a」を「k」と置換していることがわかりました。すなわち鍵の1文字目「K」と分かりました。また最初と2回目の前置詞aとの距離が131文字なので131%7=5となり、6(=5+1)文字目が「a」を「k」と置換していることがわかりました。すなわち鍵の6文字目も「K」と分かりました。
鍵の推測その2
「Ykhfc’w」という文字列に着眼します。これは「個数名詞’s」の可能性が極めて高いです。
「s」が「w」に置換されているとすると7文字目は「E」と推測できます。
鍵の推測その3
次にわかりやすいのは一人称の「I」です。暗号文中で「A」と「M」が登場します。「A」は文頭から347文字離れているので、347%7=4文字目が「I」を「A」と置換していることがわかります。すなわち、鍵の4文字目は「S」と分かりました。「M」はAから24文字離れており24%7=3で7文字目がわかります。しかし、7文字目は解読していますね。
鍵の推測その4
ここまでで、鍵が「K**S*KE」となっています。
分かっている鍵を適用させると、暗号文が以下のようになりました。
Okhnc’s cbmv was puinteq led aad decoeaned wvtb chrlsunthezug flojels. Sue also hud a uacrpin mude os mcarlrt and yiaht byuy crece with a medipihe bayl and n eusudnmu patgeln. Oxuhi wohlx brat ubout huving simeonr vuy hrr someghcng nrw, but wben projle teiyd to gyt a pliser yoik, sue woulq bide vt in hrr sleeie, makvna peocly anxvoos. Wuehever I saw ghcngs yiee thnt, I rrgletteq hot brihg boen a wozah, anq qondeeex why myn diqn’t drrsm as oeuutifhlfy as wimen.
ここからさらに推測をしていきます。
文末の「wimen」は「women」っぽいと推測できます。そのため、460文字離れており460%7=5文字目が「o」を「i」に置換しているとわかります。そのため、5文字目は「U」
「diqn’t」は「didn’t」の可能性が高いので、430文字離れており、430%7=3文字目が「d」を「q」に置換しているとわかります。そのため、3文字目が「N」と分かります。
鍵の推測その5
鍵が「K*NSUKE」までわかりました。
分かっている鍵を適用させると、暗号文が以下のようになりました。
Okuni’s comb was painted red and decorated with chrysanthemum flowers. She also had a hairpin made of scarlet and light blue crepe with a medicine ball and a kusudama pattern. Okuni would brag about having someone buy her something new, but when people tried to get a closer look, she would hide it in her sleeve, making people anxious. Whenever I saw things like that, I regretted not being born a woman, and wondered why men didn’t dress as beautifully as women.
だいぶわかりやすくなってきました。文章として成り立っているように見えます。すなわち、2文字目は「A」と分かります。
ここまでの推測で鍵が「KANSUKE」と分かりました。
まとめ
今回は簡易的なルールのもとでヴィジュネル暗号の解読を行ってみました。実際にはヴィジュネル方陣の情報もない中で解読をしたことでしょう。空白や文字コードをいじった暗号化も面白いかもしれませんね。あまり触れませんでしたが、勘助の銀の匙は素晴らしい文学です。幼い心をあそこまで文学的に描けるのは素晴らしいです。一冊でいいのですが、岩波文庫で見つけるたびに何冊も買い足してます。
最後にですが、以前のブログでは上司をプリキュアの映画に誘うと書きました。実はプリキュアの映画に部長2人を含む先輩社員たちと同僚のみんなで行きました。今度は先輩社員の好きな映画に行きたいです。
参考
[1] 野村 恒彦 チャールズ・バベッジ “Cypher Writing” について 数理解析研究所講究録 第 1625 巻 2009 年 120-130