滝の音

滝の音

名こそ流れてなお聞こえけれ

VBAで暗号を実装しよう その3 ポリュビオス暗号

  • はじめに

さてさて。 「暗号を実装しよう」の第3段です。
記事のストックがないので大急ぎで書いています笑

今回はポリュビオス暗号。
全く聞いたことない笑

  • さっくと歴史

紀元前2世紀に古代ギリシアポリュビオスが発明。

5*5の25マス目にアルファベットを入れて
各アルファベットを記入する代わりに
そのマス目の行列番号を記述していく
タイプのものです。

行列 1 2 3 4 5
1 a b c d e
2 f g h I,j k
3 l m n o p
4 q r s t u
5 v w x y z

この表がフォーマルタイプ。

Go home を伝達したい場合は

書き手は 22 34 23 34 32 15
のように変換して

読み手は
表を見ながら Gohome と復元します。

これももっと詳しく知りたい方はググってきてください笑

  • とりあえず暗号化

96 93 13 35 21  48 45 17 46 76 54 56 93 43 81 28 54  72 24 93 43 21 56 36 39 75 32 92 57 57 63 51 92 99  26 64 54 81 51 76 76 35 19 28  87 35 76 81 14 91 81 73 27 44 36 19 72 26  14 57 44 67 81

わー。
きーもーちーわーるーいー。
ほんとにぞわぞわする。
自分は暗号に触れる適性がないのかな笑

これがポリュビオス暗号です。
本来は全角の空行は入らないでしょうが
原文の見やすさのために取り入れました。

  • 暗号について

またまた能書き。
この手のものは換字式暗号といいます。
「かんじ」じゃなくて「かえじ」って読むらしいです。

文字を何かに置き換えるってやつですね。
今回は文字を数字に置き換えています。

文字と数字が一対一対応になっているので
換字表を知っている人同士では簡単に読み書きできます。

じゃあ換字表を知らない人が解読するにはどうすればいいのか。

これって無理ゲーっぽいですよね。。 だって対応の起こりうるパターン数が多すぎるのだもの。
スキュタレー暗号のように物量作戦はむりですね。

じゃあ最強の暗号だ!!
と思いきや

これも現代ではすでにザルの暗号になっています。
頻度分析と呼ばれる手法によって。

これは
文字の出現頻度と暗号文での換字の出現頻度を対応付けて復元していくやり方です。

9世紀にすでに解読法が記録されているみたいですね。

でもポリュビオス暗号が生まれた時期が紀元前1世紀であることを考えると
記録上では800~900年くらいは解読不能(正確には難しい?)なツールだったのかもしれませんね。

  • 暗号化のコード

今回はまず換字表を用意する必要があるので
それを作成するコードから

Function pattern_make()
 
 Dim trgt As Range
 Dim t As Integer
 Dim list() As Variant
 Dim d(0 To 1) As Integer
 Dim rp As Range
 Dim div As Integer
'----------------------
'作業用シートで並び替えて
'listに書き込む
'----------------------
 Sheets.Add
 
 For i = 1 To 83
    Cells(i, 1) = Chr(-32097 + (i - 1))
    Cells(i, 2) = Rnd()
 Next
 
 t = Cells(1, 1).End(xlDown).Row
 
 Set trgt = Range(Cells(1, 1), Cells(t, 2))
 trgt.Sort Cells(1, 2), xlAscending
 
 list = trgt
 
 Application.DisplayAlerts = False
 ActiveSheet.Delete
 Application.DisplayAlerts = True
'----------------------------
'換字表を作成する
'----------------------------
 Set rp = Cells(11, 1)
 div = 9
 For i = 1 To UBound(list, 1)
    d(0) = (i - 1) \ div + 1
    d(1) = (i - 1) Mod div + 1
    rp.Offset(d(0), d(1)) = list(i, 1)
 Next
 
End Function

コードの中のdivという変数も結構だいじです。
だたこれは根性さえあれば暗号文から読み取れますが。

次にメインの関数

Sub polybius_coding()

 Dim str As String
 Dim str2 As String
'------------------
'strを読み込む
'------------------
  str = txt_input
'------------------
'strを暗号化
'------------------
 str2 = coding(str)
'------------------
'str2を記述
'------------------
 Call txt_output(str2)
 
End Sub

形式は前回のスタキュレー暗号とほとんど一緒ですね。
というか一緒になるようにしています。

このコードの肝は関数codingなのですが
それはもちろんスタキュレーとは違う仕様です。

以下詳細。

Function coding(str) As String

 Dim pattern() As Integer
 Dim char As String
 Dim num As Integer
 Dim ans As String
 ReDim pattern(1 To 83)
'------------------------
'換字表を読み込む
'------------------------
 pattern = pattern_input
'------------------------
'strを暗号化
'------------------------
 For i = 1 To Len(str)
    char = Mid(str, i, 1)

    num = Asc(char) + 32098
    If num < 1 Or 83 < num Then
        ans = ans & char
    Else
        ans = ans & pattern(num) & " "
    End If
 Next
 
 coding = ans
End Function

この中にもさらに関数pattern_inputが入っています。
それで換字表を認識して
それに沿った変換をそれ以降で行っています。

その中でも特にいい感じのコードはこれ。

If num < 1 Or 83 < num Then
    ans = ans & char
Else
    ans = ans & pattern(num) & " "
End If

これによって換字表に入っていない文字はそのままの形で暗号文に組み込まれます。
全角のスペースとか
“―”これとか “。”これとか
がそのまま読み込まれます。
やりたい人は
上の記号たちも換字表に入れちゃえばいいのかなと思います。
多分簡単にできると思いますよー。

  • 復元のコード

換字表を持っていない状態での復元には頻度分析を使うと思いますが
頻度分析のプログラミングは難しそうなので
今回はスルーします。

今回は換字表を持っている人が復元する方法だけで。

ちなみに換字表は以下の通り。

行列 1 2 3 4 5 6 7 8 9
1
2
3
4
5
6
7
8
9
10

まずはメイン

Sub polybius_restoration()
Sheets("ポリュビオス").Activate
 Dim str As String
 Dim str2 As String
'------------------
'strを読み込む
'------------------
  str = txt_input
'------------------
'strを復元
'------------------
 str2 = restoration(str)
'------------------
'str2を記述
'------------------
 Call txt_output(str2)

End Sub

次は関数coding

Function restoration(str) As String

 Dim pattern() As Integer
 Dim box As Variant
 Dim kaeji As Variant
 Dim d(0 To 1) As Integer
 Dim ans As String
 
 ReDim pattern(1 To 83)
'------------------------
'換字表を読み込む
'------------------------
 pattern = pattern_input
'------------------------
'strを復元
'------------------------
 box = Split(str, " ")
 kaeji = Range(Cells(12, 2), Cells(21, 10))
 
 For i = LBound(box) To UBound(box)
    If Val(box(i)) = 0 Then
        ans = ans & box(i)
    Else
        d(0) = Mid(box(i), 1, Len(box(i)) - 1)
        d(1) = Right(box(i), 1)
        ans = ans & kaeji(d(0), d(1))
    End If
 Next
 
 restoration = ans
End Function

復元した結果はこちらー。

こんかいは ぽりゅぴおすあんごうです にほんごはあるふぁべっととちがって もじすうがおおいので たいおうひょうをつくるのにも ひとくろう

またしてもやる価値のない暗号化でした笑

あ。
そういえば換字表はシート上に出力しているので
そのセル番号がこのコードで考慮されていないものになってしまうと
正しく変換されなくなってしまいます。
これはちょっとシステムとして脆弱かも。。

どうやって解決しようかなー。
たぶんメモ帳に出力することになるんだろうけど。
今回はパスで。。

  • まとめ

換字式の暗号は
換字表をどうやって共有するのかが肝ですね。
これを奪い取ることが一番楽な解読法な気がするもの笑

次回はまたちょっと「形式の修正」を行います。
関数の「txt_input」と「txt_output」に不満な部分があるので。。

具体的には
読み込み先、書き込み先のテキストファイルを選択できるようにします。

おわり。