Cipherモジュールは、暗号化・復号する関数をまとめたモジュールです。
シーザー暗号・ROT13・ヴィジュネル暗号・XOR暗号の4種類です。
- 構文
- UString = Cipher.Caesar.encode( str, num )
- UString = Cipher.Caesar.decode( str, num )
- UString = Cipher.ROT13.encode( str )
- UString = Cipher.ROT13.encode( str )
- UString = Cipher.Vigenere.encode( str, key )
- UString = Cipher.Vigenere.decode( str, key )
- UString = Cipher.XOR.encode( str, key )
- UString = Cipher.XOR.decode( str, key )
- 引数
- str
- 暗号化または復号する文字列
- num
- シーザー暗号で文字をシフトさせる数
- key
- 鍵
- 戻値
- 暗号化または復号した文字列
プログラム
//////////////////////////////////////////////////
// 【引数】
// str : 暗号化または復号する文字列
// num : シーザー暗号で文字をシフトさせる数
// key : 鍵
// 【戻値】
// 暗号化または復号した文字列
//////////////////////////////////////////////////
MODULE Cipher
FUNCTION Caesar.encode(str, num = 3)
DIM res = ""
FOR n = 1 TO LENGTH(str)
DIM s = COPY(str, n, 1)
DIM ofs = ""
DIM normalizedNumber = IIF(num >= 0, num MOD 26, INT(ABS(num / 26) + 1) * 26 + num)
SELECT TRUE
CASE ASC(s) >= ASC("A") AND ASC(s) <= ASC("Z")
ofs = (ASC(s) - ASC("A") + normalizedNumber) MOD 26
res = res + CHR(ofs + ASC("A"))
CASE ASC(s) >= ASC("a") AND ASC(s) <= ASC("z")
ofs = (ASC(s) - ASC("a") + normalizedNumber) MOD 26
res = res + CHR(ofs + ASC("a"))
DEFAULT
res = res + s
SELEND
NEXT
RESULT = res
FEND
FUNCTION Caesar.decode(str, num = 3)
DIM res = ""
FOR n = 1 TO LENGTH(str)
DIM s = COPY(str, n, 1)
DIM ofs = ""
DIM normalizedNumber = IIF(num >= 0, num MOD 26, INT(ABS(num / 26) + 1) * 26 + num)
SELECT TRUE
CASE ASC(s) >= ASC("A") AND ASC(s) <= ASC("Z")
ofs = (ASC(s) - ASC("A") - normalizedNumber + 26) MOD 26
res = res + CHR(ofs + ASC("A"))
CASE ASC(s) >= ASC("a") AND ASC(s) <= ASC("z")
ofs = (ASC(s) - ASC("a") - normalizedNumber + 26) MOD 26
res = res + CHR(ofs + ASC("a"))
DEFAULT
res = res + s
SELEND
NEXT
RESULT = res
FEND
FUNCTION ROT13.encode(str)
RESULT = Cipher.Caesar.encode(str, 13)
FEND
FUNCTION ROT13.decode(str)
RESULT = Cipher.ROT13.encode(str)
FEND
FUNCTION Vigenere.encode(str, key)
str = STRCONV(str, SC_LOWERCASE)
key = STRCONV(key, SC_LOWERCASE)
DIM res = ""
DIM ofs = ""
FOR n = 1 TO LENGTH(str)
DIM s = COPY(str, n, 1)
SELECT TRUE
CASE ASC(s) >= ASC("a") AND ASC(s) <= ASC("z")
DIM num = (n - 1) MOD LENGTH(key) + 1
ofs = ((ASC(s) - ASC("a")) + (ASC(COPY(key, num, 1)) - ASC("a")) + 26) MOD 26
res = res + CHR(ofs + ASC("a"))
DEFAULT
res = res + s
SELEND
NEXT
RESULT = res
FEND
FUNCTION Vigenere.decode(str, key)
str = STRCONV(str, SC_LOWERCASE)
key = STRCONV(key, SC_LOWERCASE)
DIM res = ""
DIM ofs = ""
FOR n = 1 TO LENGTH(str)
DIM s = COPY(str, n, 1)
SELECT TRUE
CASE ASC(s) >= ASC("a") AND ASC(s) <= ASC("z")
DIM num = (n - 1) MOD LENGTH(key) + 1
ofs = ((ASC(s) - ASC("a")) - (ASC(COPY(key, num, 1)) - ASC("a")) + 26) MOD 26
res = res + CHR(ofs + ASC("a"))
DEFAULT
res = res + s
SELEND
NEXT
RESULT = res
FEND
FUNCTION XOR.encode(str, key)
DIM res = ""
FOR n = 1 TO LENGTH(str)
DIM num = (n - 1) MOD LENGTH(key) + 1
DIM a = ASC(COPY(str, n, 1))
DIM b = ASC(COPY(key, num, 1))
res = res + "" + REPLACE(FORMAT(VARTYPE(decToBin(a XOR b), VAR_INTEGER), 8), " ", "0")
NEXT
RESULT = res
FEND
FUNCTION XOR.decode(str, key)
DIM res = ""
FOR n = 1 TO LENGTH(str) / 8
DIM num = (n - 1) MOD LENGTH(key) + 1
DIM a = binToDec(COPY(str, n * 8 - 7, 8))
DIM b = ASC(COPY(key, num, 1))
res = res + CHR(a XOR b)
NEXT
RESULT = res
FEND
ENDMODULE
//////////////////////////////////////////////////
// 【引数】
// bin : 2進数
// 【戻値】
// 10進数に変換した値
//////////////////////////////////////////////////
FUNCTION binToDec(bin)
dec = 0
FOR n = 1 TO LENGTH(bin)
dec = dec + COPY(bin, n, 1) * POWER(2, LENGTH(bin) - n)
NEXT
RESULT = dec
FEND
//////////////////////////////////////////////////
// 【引数】
// dec : 10進数
// 【戻値】
// 2進数に変換した値
//////////////////////////////////////////////////
FUNCTION decToBin(dec)
bin = ""
REPEAT
bin = (dec MOD 2) + bin
dec = INT(dec/2)
UNTIL dec = 0
RESULT = bin
FEND
//////////////////////////////////////////////////
// 【引数】
// expr : 評価する式
// truepart : 評価した式がTrueのときに返す値
// falsepart : 評価した式がFalseのときに返す値
// 【戻値】
// truepart : 評価した式がTrueのとき、falsepart : 評価した式がFalseのとき
//////////////////////////////////////////////////
FUNCTION IIF(expr, truepart, falsepart)
IFB EVAL(expr) THEN
RESULT = truepart
ELSE
RESULT = falsepart
ENDIF
FEND
解説
- 2-20行目
FUNCTION Caesar.encode(str, num = 3) DIM res = "" FOR n = 1 TO LENGTH(str) DIM s = COPY(str, n, 1) DIM ofs = "" DIM normalizedNumber = IIF(num >= 0, num MOD 26, INT(ABS(num / 26) + 1) * 26 + num) SELECT TRUE CASE ASC(s) >= ASC("A") AND ASC(s) <= ASC("Z") ofs = (ASC(s) - ASC("A") + normalizedNumber) MOD 26 res = res + CHR(ofs + ASC("A")) CASE ASC(s) >= ASC("a") AND ASC(s) <= ASC("z") ofs = (ASC(s) - ASC("a") + normalizedNumber) MOD 26 res = res + CHR(ofs + ASC("a")) DEFAULT res = res + s SELEND NEXT RESULT = res FEND
- Cipher.Caesar.encode
- シーザー暗号でエンコードします。シフトする文字数のデフォルトは3文字です。
エンコードした結果を代入する変数resを宣言。変数normalizedNumberにシフトさせる数を0~25の範囲に正規化した数値を代入。
- ASC(s) >= ASC("A") AND ASC(s) <= ASC("Z")(変数sの文字が大文字ならば)
- ASC(s) >= ASC("a") AND ASC(s) <= ASC("z")(変数sの文字が小文字ならば)
- アルファベット以外の文字
- そのまま代入
- 21-39行目
FUNCTION Caesar.decode(str, num = 3) DIM res = "" FOR n = 1 TO LENGTH(str) DIM s = COPY(str, n, 1) DIM ofs = "" DIM normalizedNumber = IIF(num >= 0, num MOD 26, INT(ABS(num / 26) + 1) * 26 + num) SELECT TRUE CASE ASC(s) >= ASC("A") AND ASC(s) <= ASC("Z") ofs = (ASC(s) - ASC("A") - normalizedNumber + 26) MOD 26 res = res + CHR(ofs + ASC("A")) CASE ASC(s) >= ASC("a") AND ASC(s) <= ASC("z") ofs = (ASC(s) - ASC("a") - normalizedNumber + 26) MOD 26 res = res + CHR(ofs + ASC("a")) DEFAULT res = res + s SELEND NEXT RESULT = res FEND
- Cipher.Caesar.decode
- シーザー暗号でデコードします。
変数sにデコードする文字列から1文字を代入。
変数normalizedNumberにシフトさせる数を0~25の範囲に正規化した数値を代入。
- ASC(s) >= ASC("A") AND ASC(s) <= ASC("Z")
- マイナスにならないように「+26」する。
AのASCIIコードにシフトする数を加算してから文字に戻す。
- ASC(s) >= ASC("a") AND ASC(s) <= ASC("z")
- マイナスにならないように「+26」する。
AのASCIIコードにシフトする数を加算してから文字に戻す。
- アルファベット以外の文字
- そのまま代入
- 40-42行目
FUNCTION ROT13.encode(str) RESULT = Cipher.Caesar.encode(str, 13) FEND
- Cipher.ROT13.encode
- ROT13でエンコードします。
シーザー暗号で13文字シフトします。
- 43-45行目
FUNCTION ROT13.decode(str) RESULT = Cipher.ROT13.encode(str) FEND
- Cipher.ROT13.decode
- ROT13でデコードします。
- 46-63行目
FUNCTION Vigenere.encode(str, key) str = STRCONV(str, SC_LOWERCASE) key = STRCONV(key, SC_LOWERCASE) DIM res = "" DIM ofs = "" FOR n = 1 TO LENGTH(str) DIM s = COPY(str, n, 1) SELECT TRUE CASE ASC(s) >= ASC("a") AND ASC(s) <= ASC("z") DIM num = (n - 1) MOD LENGTH(key) + 1 ofs = ((ASC(s) - ASC("a")) + (ASC(COPY(key, num, 1)) - ASC("a")) + 26) MOD 26 res = res + CHR(ofs + ASC("a")) DEFAULT res = res + s SELEND NEXT RESULT = res FEND
- Cipher.Vigenere.encode
- ヴィジュネル暗号でエンコードします。
- 64-81行目
FUNCTION Vigenere.decode(str, key) str = STRCONV(str, SC_LOWERCASE) key = STRCONV(key, SC_LOWERCASE) DIM res = "" DIM ofs = "" FOR n = 1 TO LENGTH(str) DIM s = COPY(str, n, 1) SELECT TRUE CASE ASC(s) >= ASC("a") AND ASC(s) <= ASC("z") DIM num = (n - 1) MOD LENGTH(key) + 1 ofs = ((ASC(s) - ASC("a")) - (ASC(COPY(key, num, 1)) - ASC("a")) + 26) MOD 26 res = res + CHR(ofs + ASC("a")) DEFAULT res = res + s SELEND NEXT RESULT = res FEND
- Cipher.Vigenere.decode
- ヴィジュネル暗号でデコードします。
- 82-91行目
FUNCTION XOR.encode(str, key) DIM res = "" FOR n = 1 TO LENGTH(str) DIM num = (n - 1) MOD LENGTH(key) + 1 DIM a = ASC(COPY(str, n, 1)) DIM b = ASC(COPY(key, num, 1)) res = res + "" + REPLACE(FORMAT(VARTYPE(decToBin(a XOR b), VAR_INTEGER), 8), " ", "0") NEXT RESULT = res FEND
- Cipher.XOR.encode
- XOR暗号でエンコードします。
- 92-101行目
FUNCTION XOR.decode(str, key) DIM res = "" FOR n = 1 TO LENGTH(str) / 8 DIM num = (n - 1) MOD LENGTH(key) + 1 DIM a = binToDec(COPY(str, n * 8 - 7, 8)) DIM b = ASC(COPY(key, num, 1)) res = res + CHR(a XOR b) NEXT RESULT = res FEND
- Cipher.XOR.decode
- XOR暗号でデコードします。
プログラム実行例
シーザー暗号
DIM str = "info@example.com"
DIM Caesar = Cipher.Caesar.encode(str)
PRINT "暗号化<#TAB>" + Caesar
PRINT "復号<#TAB>" + Cipher.Caesar.decode(Caesar)
//////////////////////////////////////////////////
// 【引数】
// bin : 2進数
// 【戻値】
// 10進数に変換した値
//////////////////////////////////////////////////
FUNCTION binToDec(bin)
dec = 0
FOR n = 1 TO LENGTH(bin)
dec = dec + COPY(bin, n, 1) * POWER(2, LENGTH(bin) - n)
NEXT
RESULT = dec
FEND
//////////////////////////////////////////////////
// 【引数】
// str : 暗号化または復号する文字列
// num : シーザー暗号で文字をシフトさせる数
// key : 鍵
// 【戻値】
// 暗号化または復号した文字列
//////////////////////////////////////////////////
MODULE Cipher
FUNCTION Caesar.encode(str, num = 3)
DIM res = ""
FOR n = 1 TO LENGTH(str)
DIM s = COPY(str, n, 1)
DIM ofs = ""
DIM normalizedNumber = IIF(num >= 0, num MOD 26, INT(ABS(num / 26) + 1) * 26 + num)
SELECT TRUE
CASE ASC(s) >= ASC("A") AND ASC(s) <= ASC("Z")
ofs = (ASC(s) - ASC("A") + normalizedNumber) MOD 26
res = res + CHR(ofs + ASC("A"))
CASE ASC(s) >= ASC("a") AND ASC(s) <= ASC("z")
ofs = (ASC(s) - ASC("a") + normalizedNumber) MOD 26
res = res + CHR(ofs + ASC("a"))
DEFAULT
res = res + s
SELEND
NEXT
RESULT = res
FEND
FUNCTION Caesar.decode(str, num = 3)
DIM res = ""
FOR n = 1 TO LENGTH(str)
DIM s = COPY(str, n, 1)
DIM ofs = ""
DIM normalizedNumber = IIF(num >= 0, num MOD 26, INT(ABS(num / 26) + 1) * 26 + num)
SELECT TRUE
CASE ASC(s) >= ASC("A") AND ASC(s) <= ASC("Z")
ofs = (ASC(s) - ASC("A") - normalizedNumber + 26) MOD 26
res = res + CHR(ofs + ASC("A"))
CASE ASC(s) >= ASC("a") AND ASC(s) <= ASC("z")
ofs = (ASC(s) - ASC("a") - normalizedNumber + 26) MOD 26
res = res + CHR(ofs + ASC("a"))
DEFAULT
res = res + s
SELEND
NEXT
RESULT = res
FEND
FUNCTION ROT13.encode(str)
RESULT = Cipher.Caesar.encode(str, 13)
FEND
FUNCTION ROT13.decode(str)
RESULT = Cipher.ROT13.encode(str)
FEND
FUNCTION Vigenere.encode(str, key)
str = STRCONV(str, SC_LOWERCASE)
key = STRCONV(key, SC_LOWERCASE)
DIM res = ""
DIM ofs = ""
FOR n = 1 TO LENGTH(str)
DIM s = COPY(str, n, 1)
SELECT TRUE
CASE ASC(s) >= ASC("a") AND ASC(s) <= ASC("z")
DIM num = (n - 1) MOD LENGTH(key) + 1
ofs = ((ASC(s) - ASC("a")) + (ASC(COPY(key, num, 1)) - ASC("a")) + 26) MOD 26
res = res + CHR(ofs + ASC("a"))
DEFAULT
res = res + s
SELEND
NEXT
RESULT = res
FEND
FUNCTION Vigenere.decode(str, key)
str = STRCONV(str, SC_LOWERCASE)
key = STRCONV(key, SC_LOWERCASE)
DIM res = ""
DIM ofs = ""
FOR n = 1 TO LENGTH(str)
DIM s = COPY(str, n, 1)
SELECT TRUE
CASE ASC(s) >= ASC("a") AND ASC(s) <= ASC("z")
DIM num = (n - 1) MOD LENGTH(key) + 1
ofs = ((ASC(s) - ASC("a")) - (ASC(COPY(key, num, 1)) - ASC("a")) + 26) MOD 26
res = res + CHR(ofs + ASC("a"))
DEFAULT
res = res + s
SELEND
NEXT
RESULT = res
FEND
FUNCTION XOR.encode(str, key)
DIM res = ""
FOR n = 1 TO LENGTH(str)
DIM num = (n - 1) MOD LENGTH(key) + 1
DIM a = ASC(COPY(str, n, 1))
DIM b = ASC(COPY(key, num, 1))
res = res + "" + REPLACE(FORMAT(VARTYPE(decToBin(a XOR b), VAR_INTEGER), 8), " ", "0")
NEXT
RESULT = res
FEND
FUNCTION XOR.decode(str, key)
DIM res = ""
FOR n = 1 TO LENGTH(str) / 8
DIM num = (n - 1) MOD LENGTH(key) + 1
DIM a = binToDec(COPY(str, n * 8 - 7, 8))
DIM b = ASC(COPY(key, num, 1))
res = res + CHR(a XOR b)
NEXT
RESULT = res
FEND
ENDMODULE
//////////////////////////////////////////////////
// 【引数】
// dec : 10進数
// 【戻値】
// 2進数に変換した値
//////////////////////////////////////////////////
FUNCTION decToBin(dec)
bin = ""
REPEAT
bin = (dec MOD 2) + bin
dec = INT(dec/2)
UNTIL dec = 0
RESULT = bin
FEND
//////////////////////////////////////////////////
// 【引数】
// expr : 評価する式
// truepart : 評価した式がTrueのときに返す値
// falsepart : 評価した式がFalseのときに返す値
// 【戻値】
// truepart : 評価した式がTrueのとき、falsepart : 評価した式がFalseのとき
//////////////////////////////////////////////////
FUNCTION IIF(expr, truepart, falsepart)
IFB EVAL(expr) THEN
RESULT = truepart
ELSE
RESULT = falsepart
ENDIF
FEND
- 結果
- 暗号化 lqir@hadpsoh.frp
復号 info@example.com
解説
- 1行目
暗号化する文字列をstrに代入します。DIM str = "info@example.com"
- 2行目
シーザー暗号でエンコード(暗号化)します。DIM Caesar = Cipher.Caesar.encode(str)
- 3行目
暗号化した文字列を出力します。PRINT "暗号化<#TAB>" + Caesar
- 4行目
復号した文字列を出力します。PRINT "復号<#TAB>" + Cipher.Caesar.decode(Caesar)
シーザー暗号
シーザー暗号は単一換字式暗号の一種で、平文の各文字を3字分シフトして作る暗号のことです。例えば「A」を「D」、「B」を「E」に置換します。文字のシフト数は固定だが、3である必要はありません。
シフト数が26の倍数の場合、平文と同じになります。
シフトする数がすべての文字で同じなので、アルファベットで構成された文は26通りすべて総当りすることで簡単に破られます。
\[E_{n}(x)=(x+n) \quad \rm{mod} \quad 26\] \[D_{n}(x)=(x-n) \quad \rm{mod} \quad 26\]ROT13
ROT13は単一換字式暗号(シーザー暗号)の一種で、平文の各文字を13字分シフトして作る暗号のことです。例えば「A」を「N」、「B」を「O」に置換します。”ROTate by 13 places”の略。暗号化と復号が同じ処理でとても単純なのもこの暗号の特徴。アルファベットが26文字であるのに対し、暗号化は13文字シフトするので2回処理をすると元の文に戻る。
\[{\rm{ROT}}_{13}({\rm{ROT}}_{13}(x))={\rm{ROT}}_{26}(x)=x\]ヴィジュネル暗号
アルファベットを0~25(a~z)の数値としてみれば、次の式が成り立ちます。ただし、\(P_{i}\)は平文の\(i\)文字目、\(K_{i}\)は鍵の\(i\)文字目、\(C_{i}\)は暗号文の\(i\)文字目です。
以下が、ヴィジュネル暗号は多表式の換字式暗号です。
\[C_{i}=(P_{i}+K_{i}) \quad \rm{mod} \quad 26\] \[P_{i}=(C_{i}-K_{i}) \quad \rm{mod} \quad 26\]
XOR暗号
XOR暗号とは、平文をバイナリデータと考えて、2進数の鍵とXORをとって暗号化する手法のことです。
XOR(排他的論理和)には、以下の特徴があります。
- 与えられた2つの入力のうち片方が真・片方が偽のとき真を出力し、両方とも真もしくは偽のときは偽を出力する。
- ビットごとの排他的論理和は特定ビットの反転操作なので、2回繰り返せばもとに戻る。