Chaos Corp.のまったりゲーム生活

主にプレイしているゲームの感想や攻略情報をのんびり記事にしていきます。

暗号化プログラム第二弾!!~Lunar_Language~

🌓🌕🌕🌑🌓🌑🌑🌑🌓🌗🌑🌑🌕🌕🌗🌓🌑🌗🌗🌓🌓🌕🌗🌕🌓🌑🌗🌗🌕🌕🌗🌗


改めまして、どうも、fです。
最近記事を書いてませんでしたね。すみません。
今回は、vbsで文字列を暗号化することができるプログラムを作ってみました。
chaos-melt-down.hatenablog.com
実は以前にも、vbsを使用した文字列暗号化/解読プログラムを公開しています。
上のリンクのプログラムはシーザー暗号というもので、予め規定された文字列上での順番を任意の数だけずらすというものなのですが、
このプログラムは少し違います。
その辺の解説はあとで。   
ちょっと面倒ですが、ソースコードの解説もしていきたいと思います!!



~~~ソースコード↓~~~
Option Explicit
Dim chara,sentence,code,i,mode,a,b,c,d
chara="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijkrmnopqrstuvwxyzあいうえおかきくけこさしすせそたちつてとなにぬねのはひふへほまみむめもやゐゆゑよらりるれろわをんがぎぐげござじずぜぞだぢづでどばびぶべぼぱぴぷぺぽぁぃぅぇぉっゃゅょアイウエオカキクケコサシスセソタチツテトナニヌネノハヒフヘホマミムメモヤヰユヱヨラリルレロワヲンガギグゲゴザジズゼゾダヂヅデドバビブベボパピプペポァィゥェォッャュョ,./:~-=_@!?#%&ー~'+-()<>、。!?「」"
mode=InputBox ("モード選択"&VBCr&"1:暗号化モード"&VBCr&"2:解読モード")
If mode=1 then
sentence="/対応する文字"
Do While sentence="/対応する文字"
sentence=InputBox ("暗号化したい文字列を入力してください。"&VBCr&"/対応する文字と入力することで、"&VBCr&"暗号化に対応している文字列を見ることができます。")
If sentence="/対応する文字" then
MsgBox chara
End If
Loop
i=0
Do Until i=Len(sentence)
i=i+1
a=InStr(chara,Mid(sentence,i,1))
a=a-1
code=code&a\64
a=a-(a\64)*64
code=code&a\16
a=a-(a\16)*16
code=code&a\4
a=a-(a\4)*4
code=code&a
Loop
i=0
Do Until i=Len(code)
i=i+1
b=Mid(code,i,1)
If b="0" then
code=Left(code,i-1)&"🌑"&Right(code,Len(code)-i)
ElseIf b="1" then
code=Left(code,i-1)&"🌓"&Right(code,Len(code)-i)
ElseIf b="2" then
code=Left(code,i-1)&"🌗"&Right(code,Len(code)-i)
ElseIf b="3" then
code=Left(code,i-1)&"🌕"&Right(code,Len(code)-i)
End If
Loop
InputBox "暗号化が完了しました。"&VBCr&"暗号が青文字になった状態でコピーしてください。",,code
ElseIf mode=2 then
code=InputBox("暗号を入力してください。")
i=-1
Do Until i=Len(code)-1
i=i+2
a=Right(Left(code,i+1),2)
If a="🌑" then
code=Left(code,i-1)&"0"&Right(code,Len(code)-i)
ElseIf a="🌓" then
code=Left(code,i-1)&"1"&Right(code,Len(code)-i)
ElseIf a="🌗" then
code=Left(code,i-1)&"2"&Right(code,Len(code)-i)
ElseIf a="🌕" then
code=Left(code,i-1)&"3"&Right(code,Len(code)-i)
End If
Loop
i=-1
Do Until i=Len(code)-1
i=i+2
d=d&Mid(code,i,1)
Loop
i=-3
Do Until i=Len(d)-3
i=i+4
b=Mid(d,i,4)
c=(Mid(b,1,1)*64)+(Mid(b,2,1)*16)+(Mid(b,3,1)*4)+Mid(b,4,1)+1
sentence=sentence&Mid(chara,c,1)
Loop
MsgBox sentence
End If
~~~ここまで~~~

それでは、ソースコードの解説をしていきたいと思います。
行数で示すので分かりづらいと思いますが、メモ帳にコピペするなどしていただければわかるかと思います。

~~~ソースコード解説↓~~~
1行目  おまじない的な(構文の厳格化、変数の宣言を強制するなどの役割があります)
2行目  プログラムで使用する変数の宣言
3行目  暗号化対応文字を変数"chara"に格納(後述する理由で256文字です)
4行目  暗号化モードと解読モードの分岐
5行目  変数"mode"が1(暗号化モード)の時の分岐処理
6行目  変数"sentence"を"/対応する文字"にしておく
7行目  変数"sentence"が"/対応する文字"ではなくなるまで
~    暗号化したい文章の入力用InputBoxを繰り返し出現させ、
12行目  暗号化したい文章を取得する
13行目  変数"i"(読み込み中の文字の文字数)をリセット
14行目  ループ処理準備
15行目  読み込み中の文字を1文字ずつ変える
16行目  読み込み中の文字がchara内の何番目にあたるのか調べる(返り値は"a"に代入)
17行目  "a"の範囲は1~256なので、1引いて範囲を0~255にする
18行目  "a"(0~255の数字)を10進数から4進数に変換する

24行目
25行目  ループ処理終了
26行目  "i"の値をリセット
27行目  ループ処理準備
28行目  読み込み中の文字を1ずつ変える
29行目  読み込み中の文字を変数"b"に代入
30行目  文字列(0,1,2,3)をそれぞれ月に置き換える(0→🌑,1→🌓,2→🌗,3→🌕)

38行目
39行目  ループ処理終了
40行目  完成した暗号を出力(msgboxではなくinputboxの初期入力状態で出力することでコピーを可能としている)
41行目  "mode"=2(解読モード)の時の分岐処理
42行目  暗号の入力
43行目  "i"のリセット
44行目  ループ処理準備
45行目  読み込み中の文字を2ずつ変える
46行目  読み込む文字をとりだす
47行目  月を数字(0,1,2,3)に置き換える(🌑→0,🌓→1,🌗→2,🌕→3)

55行目
56行目  ループ処理終了
57行目  "i"をリセット
58行目  ループ処理準備
59行目  読み込み中の文字を2ずつ変える
60行目  1文字おきに文字を抽出(理由は後述)
61行目  ループ処理終了
62行目  "i"をリセット
63行目  ループ処理準備
64行目  読み込み中の文字を4ずつ変える
65行目  "b"に4進数の数字4桁を格納
66行目  "b"の4進数4桁を10進数に変換し、(範囲0~255)1を足して範囲を1~256にする(変数"c"に代入)
67行目  "chara"内のc番目の文字を"sentence"に追加する
68行目  ループ処理終了
69行目  完成した原文を出力
70行目  モード別の分岐処理終了
~~~ここまで~~~

疲れましたwww
簡単な仕組みとしては、
〇暗号化
①入力された原文を1文字ずつchara(変数)と照らし合わせ、何文字目なのかを取得する(この時の値は1~256だが、処理の都合上1を引いて0~255にしてある)
②得られた数を4進数の4桁に変換する(0,1,2,3)
③0~3の数字(4種の状態を持つ)を月(4種の状態を持つ)(🌑,🌓,🌗,🌕)に変換し出力
〇解読
①暗号を数字に変換(0,1,2,3)
②4桁ずつに区切り、それぞれ10進数に変換(0~255だが、処理の都合上1を足して1~256にしてある)
③②で出した数字番目のcharaの文字を繋いでいき、出力
といった感じです。
〇欠点について
私もこのプログラムで長文を扱おうとして初めて知ったのですが、どうやらInputBox関数の返り値は255文字以内らしく、それ以上入力すると切り捨てられます。
更に、切り捨てられてしまうとエラーを吐くので、切り捨てられない文字数でなければなりません。
その文字数というのは、254÷2÷4=31(余りは考慮しません)文字。
つまり、32文字以上の文章を暗号化すると、このプログラムでは復元することができないということになります。
これはInputBox関数での仕様なので、一度メモ帳に入力した内容を読み込んで解読というのはできます。
ただそうするとvbs1つで完結しなくなるので、今回は不採用です。
それと、ソースコードをコピペする場合、文字コードUTF-8以外かつUnicodeの文字を使用可能なものを使ってください。
私はUTF-16(LE)を採用しました。
〇苦労した点
月4種は全て特殊文字で、1文字で2文字分のデータ(?)を持ちます。
私もこの仕様を知らず、苦労しました。
途中で1文字おきに文字を抽出しているのには、この仕様が深く関係しています。
また、これのせいで文字数制限が半分になります。
InputBox関数での上限は255文字ですが、この仕様により見た目上127文字分のデータしか入力できません。
そして、暗号の桁数が4の倍数でないとエラーを吐くので、暗号の最大文字数は124文字、原文の文字数制限が31文字までとなるわけです。
〇4進数について
これは、完全に私独自の考えた仕組みです。
4桁を1セットとし、左から64の位,16の位,4の位,1の位となっています。
(例:0=0000,1=0001,5=0010,15=0033,16=0100,256=3333など)
charaの上限が256文字なのは、4進数4桁で表せる数の組み合わせが4の4条で256となるからです。



最後に
このプログラムは、思い立ってすぐ作り始め、約1日で完成させることができました。
わざわざ特殊文字である月を暗号に使った理由は...ロマンですね。はい。
因みに、タイトルにも書いてありますが、この暗号の名前は「Lunar_Language」です。
直訳すると「月面の言語」って意味ですが、私は「月語」的な感じで名付けました。かっこいいですよねww
冒頭の暗号は、月語で「どうも、fです。」と書いてありました。
それでは!!

にほんブログ村 ゲームブログ Minecraftへ
にほんブログ村