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進数
// signFlg : 符号付きならばTrue
// 【戻り値】
// 10進数に変換した値
//////////////////////////////////////////////////
FUNCTION binToDec(bin, signFlg = TRUE)
DIM dec = 0
DIM decimalFlg = IIF(POS(".", bin), TRUE, FALSE)
IFB COPY(bin, 1, 1) = "1" AND signFlg THEN
DIM msb = IIF(decimalFlg, POS(".", bin) - 1, LENGTH(bin))
DIM lsb = IIF(decimalFlg, POS(".", bin) - LENGTH(bin), 0)
DIM dec2 = POWER(2, msb) - 1
FOR i = -1 TO lsb STEP -1
dec2 = dec2 + POWER(2, i)
NEXT
DIM a = binToDec(bin, FALSE)
DIM b = dec2
dec = -1 * (bitXor(a, b) + POWER(2, lsb))
ELSE
IFB decimalFlg THEN
DIM integer = COPY(bin, 1, POS(".", bin) - 1)
DIM decimal = COPY(bin, POS(".", bin) + 1)
FOR i = 1 TO LENGTH(decimal)
dec = dec + COPY(decimal, i, 1) * POWER(2, -1 * i)
NEXT
ELSE
integer = bin
ENDIF
FOR i = 1 TO LENGTH(integer)
dec = dec + COPY(integer, i, 1) * POWER(2, LENGTH(integer) - i)
NEXT
ENDIF
RESULT = dec
FEND
//////////////////////////////////////////////////
// 【引数】
// num : 10進数もしくは2進数の値
// bit : ビット
// 【戻り値】
// ビットを反転した値
//////////////////////////////////////////////////
FUNCTION bitNot(num, bit = EMPTY)
IFB isString(num) THEN
DIM res = ""
FOR i = 1 TO LENGTH(num)
DIM str = COPY(num, i, 1)
IFB str = "0" OR str = "1" THEN
res = res + (1 - VAL(str))
ELSE
res = res + str
ENDIF
NEXT
RESULT = res
ELSE
DIM exponent = IIF(bit = EMPTY, CEIL(LOGN(2, num + 1)), bit)
RESULT = POWER(2, exponent) - num - 1
ENDIF
FEND
//////////////////////////////////////////////////
// 【引数】
// arg1 : 数値1(10進数)
// arg2 : 数値2(10進数)
// 【戻り値】
// 2つの数値のビット毎の排他的論理和
//////////////////////////////////////////////////
FUNCTION bitXor(arg1, arg2)
DIM args[1] = arg1, arg2
DIM bins[1]
DIM decimals[1]
DIM integers[1]
DIM keta[1]
IFB ABS(arg1) <> arg1 OR ABS(arg2) <> arg2 THEN
RESULT = ERR_VALUE
EXIT
ENDIF
FOR i = 0 TO 1
bins[i] = decToBin(args[i])
decimals[i] = 0
IFB POS(".", bins[i]) <> 0 THEN
integers[i] = COPY(bins[i], 1, POS(".", bins[i]) - 1)
decimals[i] = COPY(bins[i], POS(".", bins[i]) + 1)
ELSE
integers[i] = bins[i]
ENDIF
NEXT
keta[0] = IIF(LENGTH(integers[0]) > LENGTH(integers[1]), LENGTH(integers[0]), LENGTH(integers[1]))
integers[0] = strPad(integers[0], keta[0], "0", LEFT)
integers[1] = strPad(integers[1], keta[0], "0", LEFT)
keta[1] = IIF(LENGTH(decimals[0]) > LENGTH(decimals[1]), LENGTH(decimals[0]), LENGTH(decimals[1]))
decimals[0] = strPad(decimals[0], keta[1], "0", RIGHT)
decimals[1] = strPad(decimals[1], keta[1], "0", RIGHT)
DIM bin = ""
FOR i = 1 TO keta[0]
bin = bin + (VAL(COPY(integers[0], i, 1)) XOR VAL(COPY(integers[1], i, 1)))
NEXT
bin = bin + "."
FOR i = 1 TO keta[1]
bin = bin + (VAL(COPY(decimals[0], i, 1)) XOR VAL(COPY(decimals[1], i, 1)))
NEXT
RESULT = binToDec(bin)
FEND
//////////////////////////////////////////////////
// 【引数】
// dec : 10進数
// signFlg : 符号付きならばTrueを指定
// digits : 変換した2進数の桁数合わせを自動で行うかを示すブール値、もしくは桁数を表す数値(8,16,24,32,64のいずれか)を指定
// 【戻り値】
// 2進数に変換した値
//////////////////////////////////////////////////
FUNCTION decToBin(dec, signFlg = FALSE, digits = FALSE)
// 負数で符号なしならばエラー値を返す
IFB dec < 0 AND signFlg = FALSE THEN
PRINT "負数の場合signFlgにTrueを指定してください"
RESULT = ERR_VALUE
EXIT
ENDIF
// digitsのビット数が足りなければエラー値を返す、負数なら1桁多く取る
IFB VARTYPE(digits) <> VAR_BOOLEAN AND digits < CEIL(LOGN(2, ABS(dec))) + IIF(dec < 0, 1, 0) THEN
PRINT "ビット数が足りません"
RESULT = ERR_VALUE
EXIT
ENDIF
// signFlgがTrueかつdigitsがFalseならばエラー値を返す
IFB signFlg AND !digits THEN
PRINT "signFlgがTrueのときdigitsはFalse以外を選択してください"
RESULT = ERR_VALUE
EXIT
ENDIF
// bin:2進数に変換した結果を代入する変数
DIM bin = ""
DIM decimalFlg = IIF(POS(".", dec) <> 0, TRUE, FALSE)
DIM negativeFlg = IIF(dec < 0, TRUE, FALSE)
dec = ABS(dec)
// (1) 10進数を整数部と小数部に分ける
DIM integer = IIF(decimalFlg, COPY(dec, 1, POS(".", dec) - 1), dec)
DIM decimal = IIF(decimalFlg, "0." + COPY(dec, POS(".", dec) + 1), 0)
// (2) 10進数(整数部)を2進数に変換する。
REPEAT
bin = (integer MOD 2) + bin
integer = INT(integer / 2)
UNTIL integer = 0
// (3) 10進数(小数部)を2進数に変換する。
IFB decimalFlg THEN
bin = bin + "."
DIM loop = 0
REPEAT
loop = loop + 1
decimal = decimal * 2
bin = bin + IIF(decimal >= 1, "1", "0")
IF decimal > 1 THEN decimal = decimal - 1
UNTIL decimal = 1 OR loop > 64
ENDIF
// digitsがFALSE以外なら
IFB digits THEN
// (4) 2進数の桁合わせを行う
DIM tmp = bin
DIM binInteger = TOKEN(".", tmp)
DIM binDecimal = TOKEN(".", tmp)
// 整数部、小数部を4bit単位になるまで拡張
// 整数部、4の倍数になるまで整数部の先頭に'0'を追加
IF LENGTH(binInteger) MOD 4 <> 0 THEN binInteger = strRepeat("0", 4 - LENGTH(binInteger) MOD 4) + binInteger
// 小数部、4の倍数になるまで小数部の末尾に'0'を追加
IF LENGTH(binDecimal) MOD 4 <> 0 THEN binDecimal = binDecimal + strRepeat("0", 4 - LENGTH(binDecimal) MOD 4)
DIM digit = LENGTH(binInteger + binDecimal)
// 10進数の場合、一旦自動調整を行う
integer = INT(dec)
IF signFlg AND COPY(binInteger, 1, 1) = "1" THEN binInteger = strRepeat("0", 4) + binInteger
IFB signFlg THEN
IFB integer >= -128 AND integer <= 127 THEN // -2^7〜2^7-1
binInteger = strRepeat("0", 8 - LENGTH(binInteger)) + binInteger
ELSEIF integer >= -32768 AND integer <= 32767 THEN // -2^15〜2^15-1
binInteger = strRepeat("0", 16 - LENGTH(binInteger)) + binInteger
ELSEIF integer >= -8388608 AND integer <= 8388607 THEN // -2^23〜2^23-1
binInteger = strRepeat("0", 24 - LENGTH(binInteger)) + binInteger
ELSEIF integer >= -2147783648 AND integer <= 2147483647 THEN // -2^31〜2^31-1
binInteger = strRepeat("0", 32 - LENGTH(binInteger)) + binInteger
ELSE
binInteger = strRepeat("0", 64 - LENGTH(binInteger)) + binInteger
ENDIF
ELSE
IFB integer <= 255 THEN // 2^8-1
binInteger = strRepeat("0", 8 - LENGTH(binInteger)) + binInteger
ELSEIF integer <= 65535 THEN // 2^16-1
binInteger = strRepeat("0", 16 - LENGTH(binInteger)) + binInteger
ELSEIF integer <= 16777215 THEN // 2^24-1
binInteger = strRepeat("0", 24 - LENGTH(binInteger)) + binInteger
ELSEIF integer <= 4294967295 THEN // 2^32-1
binInteger = strRepeat("0", 32 - LENGTH(binInteger)) + binInteger
ELSE
binInteger = strRepeat("0", 64 - LENGTH(binInteger)) + binInteger
ENDIF
ENDIF
totalDigits = LENGTH(binInteger + binDecimal)
IFB totalDigits > 64 THEN
DIM del32 = totalDigits - 32
DIM del64 = totalDigits - 64
IFB del32 = LENGTH(binDecimal) AND digits <> 64 THEN
binDecimal = ""
PRINT "32bitを超えたため、小数点以下を削除しました"
ELSEIF del32 < LENGTH(binDecimal) AND digits <> 64 THEN
binDecimal = COPY(binDecimal, 1, LENGTH(binDecimal) - del32)
PRINT "32bitを超えたため、小数点以下の一部を削除しました"
ELSEIF del64 = LENGTH(binDecimal) AND del64 <> 0 THEN
binDecimal = ""
PRINT "64bitを超えたため、小数点以下を削除しました"
ELSEIF del64 < LENGTH(binDecimal) THEN
binDecimal = COPY(binDecimal, 1, LENGTH(binDecimal) - del64)
PRINT "64bitを超えたため、小数点以下の一部を削除しました"
ELSE
RESULT = ERR_VALUE
PRINT "64bitを超えるため、変換できません"
EXIT
ENDIF
ENDIF
// 整数部、小数部の合計桁数を8,16,24,32,64bit単位になるまで拡張
digit = LENGTH(binInteger + binDecimal)
DIM array[] = 8, 16, 24, 32, 64
FOR item IN array
IFB digit <= item THEN
binInteger = strRepeat("0", item - digit) + binInteger
BREAK
ENDIF
NEXT
// 指定ビットに調整
// 合計桁数の再設定
totalDigits = LENGTH(binInteger + binDecimal)
IFB digits = TRUE THEN
// 桁合わせを自動調整
IFB totalDigits > 64 THEN
len = LENGTH(binInteger + binDecimal)
WHILE LENGTH(binInteger) > 8 AND len > digits
IFB COPY(binInteger, 1, 4) = "0000" THEN
binInteger = COPY(binInteger, 5)
len = len - 4
ELSE
BREAK
ENDIF
WEND
WHILE LENGTH(binDecimal) > 4 AND LENGTH(binInteger + binDecimal) > digits
IFB COPY(binDecimal, LENGTH(binDecimal) - 4) = "0000" THEN
binDecimal = COPY(binDecimal, 1, LENGTH(binDecimal) - 4)
ELSE
BREAK
ENDIF
WEND
tmp = binInteger + "." + binDecimal
binInteger = COPY(tmp, 1, POS(".", tmp) - 1)
binDecimal = COPY(tmp, POS(".", tmp) + 1)
totalDigits = LENGTH(binInteger + binDecimal)
IFB totalDigits > 64 THEN
RESULT = ERR_VALUE
PRINT "64bitを超えたため変換できません"
EXIT
ENDIF
ENDIF
ELSE
// 指定ビットに調整
IFB totalDigits <= digits THEN
binInteger = strPad(binInteger, digits - LENGTH(binDecimal), "0", LEFT)
ELSE
// 桁あふれ調整
totalDigits = LENGTH(binInteger + binDecimal)
len = LENGTH(binInteger + binDecimal)
WHILE LENGTH(binInteger) > 8 AND len > digits
IFB COPY(binInteger, 1, 4) = "0000" THEN
binInteger = COPY(binInteger, 5)
len = len - 4
ELSE
BREAK
ENDIF
WEND
WHILE LENGTH(binDecimal) > 4 AND LENGTH(binInteger + binDecimal) > digits
IFB COPY(binDecimal, LENGTH(binDecimal) - 4) = "0000" THEN
binDecimal = COPY(binDecimal, 1, LENGTH(binDecimal) - 4)
ELSE
BREAK
ENDIF
WEND
tmp = binInteger + "." + binDecimal
binInteger = COPY(tmp, 1, POS(".", tmp) - 1)
binDecimal = COPY(tmp, POS(".", tmp) + 1)
len = LENGTH(binInteger + binDecimal)
IFB len > digits THEN
DIM deleteLength = len - digits
IFB deleteLength = LENGTH(binDecimal) THEN
binDecimal = ""
PRINT "指定ビット数にするため小数点以下を削除しました"
ELSEIF deleteLength < LENGTH(binDecimal) THEN
binDecimal = COPY(binDecimal, 1, LENGTH(binDecimal) - deleteLength)
PRINT "指定ビット数にするため小数点以下の一部を削除しました"
ELSE
RESULT = ERR_VALUE
PRINT "指定ビット数では変換できません"
EXIT
ENDIF
ENDIF
ENDIF
ENDIF
bin = binInteger + IIF(binDecimal <> "", "." + binDecimal, "")
// (5) 入力値がマイナスのため、2進数をマイナス値に変換する
IFB negativeFlg THEN
// 1の補数
bin = bitNot(bin)
// 2の補数
DIM res = ""
DIM carry = "1"
FOR i = LENGTH(bin) TO 1 STEP -1
IFB carry = "1" THEN
SELECT COPY(bin, i, 1)
CASE "0"
res = "1" + res
carry = 0
CASE "1"
res = "0" + res
DEFAULT
res = COPY(bin, i, 1) + res
SELEND
ELSE
res = COPY(bin, i, 1) + res
ENDIF
NEXT
bin = res
ENDIF
ENDIF
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
//////////////////////////////////////////////////
// 【引数】
// variable : 型を調べる変数
// 【戻り値】
// : TRUE : 与えられた変数が文字列型である、
// FALSE : 与えられた変数が文字列型でない、 :
//////////////////////////////////////////////////
FUNCTION isString(variable)
RESULT = IIF(VARTYPE(variable) = VAR_ASTR OR VARTYPE(variable) = VAR_USTR, TRUE, FALSE)
FEND
//////////////////////////////////////////////////
// 【引数】
// num : 符号を求める数値
// 【戻り値】
// 1 : 正の数、0 : ゼロ、-1 : 負の数、ERR_VALUE : それ以外
//////////////////////////////////////////////////
FUNCTION sign(num)
SELECT TRUE
CASE !CHKNUM(num)
RESULT = ERR_VALUE
CASE num > 0
RESULT = 1
CASE num = 0
RESULT = 0
CASE num < 0
RESULT = -1
SELEND
FEND
//////////////////////////////////////////////////
// 【引数】
// input : 入力文字列
// length : 埋めたあとの長さ
// str : 埋める文字
// type : 埋める方向
// 【戻り値】
// 指定文字で埋めた文字列
//////////////////////////////////////////////////
FUNCTION strPad(input, length, str = " ", type = RIGHT)
DIM s = ""
SELECT type
CASE LEFT
FOR i = 1 TO CEIL((length - LENGTH(input)) / LENGTH(str))
s = s + str
NEXT
input = COPY(s, 1, length - LENGTH(input)) + input
CASE RIGHT
FOR i = 1 TO CEIL((length - LENGTH(input)) / LENGTH(str))
s = s + str
NEXT
input = input + COPY(s, 1, length - LENGTH(input))
SELEND
RESULT = input
FEND
//////////////////////////////////////////////////
// 【引数】
// inputs : 繰り返す文字列
// multiplier : inputsを繰り返す回数
// 【戻り値】
// inputsをmultiplier回を繰り返した文字列を返します
//////////////////////////////////////////////////
FUNCTION strRepeat(inputs, multiplier)
DIM res = ""
FOR n = 1 TO multiplier
res = res + inputs
NEXT
RESULT = res
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(s) >= ASC("a") AND ASC(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)
- マイナスにならないように「+26」する。
AのASCIIコードにシフトする数を加算してから文字に戻す。
- ASC(s) >= ASC("a") AND ASC(s)
- マイナスにならないように「+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 "暗号化︰" + Caesar
PRINT "復号︰" + Cipher.Caesar.decode(Caesar)
//////////////////////////////////////////////////
// 【引数】
// bin : 2進数
// signFlg : 符号付きならばTrue
// 【戻り値】
// 10進数に変換した値
//////////////////////////////////////////////////
FUNCTION binToDec(bin, signFlg = TRUE)
DIM dec = 0
DIM decimalFlg = IIF(POS(".", bin), TRUE, FALSE)
IFB COPY(bin, 1, 1) = "1" AND signFlg THEN
DIM msb = IIF(decimalFlg, POS(".", bin) - 1, LENGTH(bin))
DIM lsb = IIF(decimalFlg, POS(".", bin) - LENGTH(bin), 0)
DIM dec2 = POWER(2, msb) - 1
FOR i = -1 TO lsb STEP -1
dec2 = dec2 + POWER(2, i)
NEXT
DIM a = binToDec(bin, FALSE)
DIM b = dec2
dec = -1 * (bitXor(a, b) + POWER(2, lsb))
ELSE
IFB decimalFlg THEN
DIM integer = COPY(bin, 1, POS(".", bin) - 1)
DIM decimal = COPY(bin, POS(".", bin) + 1)
FOR i = 1 TO LENGTH(decimal)
dec = dec + COPY(decimal, i, 1) * POWER(2, -1 * i)
NEXT
ELSE
integer = bin
ENDIF
FOR i = 1 TO LENGTH(integer)
dec = dec + COPY(integer, i, 1) * POWER(2, LENGTH(integer) - i)
NEXT
ENDIF
RESULT = dec
FEND
//////////////////////////////////////////////////
// 【引数】
// num : 10進数もしくは2進数の値
// bit : ビット
// 【戻り値】
// ビットを反転した値
//////////////////////////////////////////////////
FUNCTION bitNot(num, bit = EMPTY)
IFB isString(num) THEN
DIM res = ""
FOR i = 1 TO LENGTH(num)
DIM str = COPY(num, i, 1)
IFB str = "0" OR str = "1" THEN
res = res + (1 - VAL(str))
ELSE
res = res + str
ENDIF
NEXT
RESULT = res
ELSE
DIM exponent = IIF(bit = EMPTY, CEIL(LOGN(2, num + 1)), bit)
RESULT = POWER(2, exponent) - num - 1
ENDIF
FEND
//////////////////////////////////////////////////
// 【引数】
// arg1 : 数値1(10進数)
// arg2 : 数値2(10進数)
// 【戻り値】
// 2つの数値のビット毎の排他的論理和
//////////////////////////////////////////////////
FUNCTION bitXor(arg1, arg2)
DIM args[1] = arg1, arg2
DIM bins[1]
DIM decimals[1]
DIM integers[1]
DIM keta[1]
IFB ABS(arg1) <> arg1 OR ABS(arg2) <> arg2 THEN
RESULT = ERR_VALUE
EXIT
ENDIF
FOR i = 0 TO 1
bins[i] = decToBin(args[i])
decimals[i] = 0
IFB POS(".", bins[i]) <> 0 THEN
integers[i] = COPY(bins[i], 1, POS(".", bins[i]) - 1)
decimals[i] = COPY(bins[i], POS(".", bins[i]) + 1)
ELSE
integers[i] = bins[i]
ENDIF
NEXT
keta[0] = IIF(LENGTH(integers[0]) > LENGTH(integers[1]), LENGTH(integers[0]), LENGTH(integers[1]))
integers[0] = strPad(integers[0], keta[0], "0", LEFT)
integers[1] = strPad(integers[1], keta[0], "0", LEFT)
keta[1] = IIF(LENGTH(decimals[0]) > LENGTH(decimals[1]), LENGTH(decimals[0]), LENGTH(decimals[1]))
decimals[0] = strPad(decimals[0], keta[1], "0", RIGHT)
decimals[1] = strPad(decimals[1], keta[1], "0", RIGHT)
DIM bin = ""
FOR i = 1 TO keta[0]
bin = bin + (VAL(COPY(integers[0], i, 1)) XOR VAL(COPY(integers[1], i, 1)))
NEXT
bin = bin + "."
FOR i = 1 TO keta[1]
bin = bin + (VAL(COPY(decimals[0], i, 1)) XOR VAL(COPY(decimals[1], i, 1)))
NEXT
RESULT = binToDec(bin)
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進数
// signFlg : 符号付きならばTrueを指定
// digits : 変換した2進数の桁数合わせを自動で行うかを示すブール値、もしくは桁数を表す数値(8,16,24,32,64のいずれか)を指定
// 【戻り値】
// 2進数に変換した値
//////////////////////////////////////////////////
FUNCTION decToBin(dec, signFlg = FALSE, digits = FALSE)
// 負数で符号なしならばエラー値を返す
IFB dec < 0 AND signFlg = FALSE THEN
PRINT "負数の場合signFlgにTrueを指定してください"
RESULT = ERR_VALUE
EXIT
ENDIF
// digitsのビット数が足りなければエラー値を返す、負数なら1桁多く取る
IFB VARTYPE(digits) <> VAR_BOOLEAN AND digits < CEIL(LOGN(2, ABS(dec))) + IIF(dec < 0, 1, 0) THEN
PRINT "ビット数が足りません"
RESULT = ERR_VALUE
EXIT
ENDIF
// signFlgがTrueかつdigitsがFalseならばエラー値を返す
IFB signFlg AND !digits THEN
PRINT "signFlgがTrueのときdigitsはFalse以外を選択してください"
RESULT = ERR_VALUE
EXIT
ENDIF
// bin:2進数に変換した結果を代入する変数
DIM bin = ""
DIM decimalFlg = IIF(POS(".", dec) <> 0, TRUE, FALSE)
DIM negativeFlg = IIF(dec < 0, TRUE, FALSE)
dec = ABS(dec)
// (1) 10進数を整数部と小数部に分ける
DIM integer = IIF(decimalFlg, COPY(dec, 1, POS(".", dec) - 1), dec)
DIM decimal = IIF(decimalFlg, "0." + COPY(dec, POS(".", dec) + 1), 0)
// (2) 10進数(整数部)を2進数に変換する。
REPEAT
bin = (integer MOD 2) + bin
integer = INT(integer / 2)
UNTIL integer = 0
// (3) 10進数(小数部)を2進数に変換する。
IFB decimalFlg THEN
bin = bin + "."
DIM loop = 0
REPEAT
loop = loop + 1
decimal = decimal * 2
bin = bin + IIF(decimal >= 1, "1", "0")
IF decimal > 1 THEN decimal = decimal - 1
UNTIL decimal = 1 OR loop > 64
ENDIF
// digitsがFALSE以外なら
IFB digits THEN
// (4) 2進数の桁合わせを行う
DIM tmp = bin
DIM binInteger = TOKEN(".", tmp)
DIM binDecimal = TOKEN(".", tmp)
// 整数部、小数部を4bit単位になるまで拡張
// 整数部、4の倍数になるまで整数部の先頭に'0'を追加
IF LENGTH(binInteger) MOD 4 <> 0 THEN binInteger = strRepeat("0", 4 - LENGTH(binInteger) MOD 4) + binInteger
// 小数部、4の倍数になるまで小数部の末尾に'0'を追加
IF LENGTH(binDecimal) MOD 4 <> 0 THEN binDecimal = binDecimal + strRepeat("0", 4 - LENGTH(binDecimal) MOD 4)
DIM digit = LENGTH(binInteger + binDecimal)
// 10進数の場合、一旦自動調整を行う
integer = INT(dec)
IF signFlg AND COPY(binInteger, 1, 1) = "1" THEN binInteger = strRepeat("0", 4) + binInteger
IFB signFlg THEN
IFB integer >= -128 AND integer <= 127 THEN // -2^7〜2^7-1
binInteger = strRepeat("0", 8 - LENGTH(binInteger)) + binInteger
ELSEIF integer >= -32768 AND integer <= 32767 THEN // -2^15〜2^15-1
binInteger = strRepeat("0", 16 - LENGTH(binInteger)) + binInteger
ELSEIF integer >= -8388608 AND integer <= 8388607 THEN // -2^23〜2^23-1
binInteger = strRepeat("0", 24 - LENGTH(binInteger)) + binInteger
ELSEIF integer >= -2147783648 AND integer <= 2147483647 THEN // -2^31〜2^31-1
binInteger = strRepeat("0", 32 - LENGTH(binInteger)) + binInteger
ELSE
binInteger = strRepeat("0", 64 - LENGTH(binInteger)) + binInteger
ENDIF
ELSE
IFB integer <= 255 THEN // 2^8-1
binInteger = strRepeat("0", 8 - LENGTH(binInteger)) + binInteger
ELSEIF integer <= 65535 THEN // 2^16-1
binInteger = strRepeat("0", 16 - LENGTH(binInteger)) + binInteger
ELSEIF integer <= 16777215 THEN // 2^24-1
binInteger = strRepeat("0", 24 - LENGTH(binInteger)) + binInteger
ELSEIF integer <= 4294967295 THEN // 2^32-1
binInteger = strRepeat("0", 32 - LENGTH(binInteger)) + binInteger
ELSE
binInteger = strRepeat("0", 64 - LENGTH(binInteger)) + binInteger
ENDIF
ENDIF
totalDigits = LENGTH(binInteger + binDecimal)
IFB totalDigits > 64 THEN
DIM del32 = totalDigits - 32
DIM del64 = totalDigits - 64
IFB del32 = LENGTH(binDecimal) AND digits <> 64 THEN
binDecimal = ""
PRINT "32bitを超えたため、小数点以下を削除しました"
ELSEIF del32 < LENGTH(binDecimal) AND digits <> 64 THEN
binDecimal = COPY(binDecimal, 1, LENGTH(binDecimal) - del32)
PRINT "32bitを超えたため、小数点以下の一部を削除しました"
ELSEIF del64 = LENGTH(binDecimal) AND del64 <> 0 THEN
binDecimal = ""
PRINT "64bitを超えたため、小数点以下を削除しました"
ELSEIF del64 < LENGTH(binDecimal) THEN
binDecimal = COPY(binDecimal, 1, LENGTH(binDecimal) - del64)
PRINT "64bitを超えたため、小数点以下の一部を削除しました"
ELSE
RESULT = ERR_VALUE
PRINT "64bitを超えるため、変換できません"
EXIT
ENDIF
ENDIF
// 整数部、小数部の合計桁数を8,16,24,32,64bit単位になるまで拡張
digit = LENGTH(binInteger + binDecimal)
DIM array[] = 8, 16, 24, 32, 64
FOR item IN array
IFB digit <= item THEN
binInteger = strRepeat("0", item - digit) + binInteger
BREAK
ENDIF
NEXT
// 指定ビットに調整
// 合計桁数の再設定
totalDigits = LENGTH(binInteger + binDecimal)
IFB digits = TRUE THEN
// 桁合わせを自動調整
IFB totalDigits > 64 THEN
len = LENGTH(binInteger + binDecimal)
WHILE LENGTH(binInteger) > 8 AND len > digits
IFB COPY(binInteger, 1, 4) = "0000" THEN
binInteger = COPY(binInteger, 5)
len = len - 4
ELSE
BREAK
ENDIF
WEND
WHILE LENGTH(binDecimal) > 4 AND LENGTH(binInteger + binDecimal) > digits
IFB COPY(binDecimal, LENGTH(binDecimal) - 4) = "0000" THEN
binDecimal = COPY(binDecimal, 1, LENGTH(binDecimal) - 4)
ELSE
BREAK
ENDIF
WEND
tmp = binInteger + "." + binDecimal
binInteger = COPY(tmp, 1, POS(".", tmp) - 1)
binDecimal = COPY(tmp, POS(".", tmp) + 1)
totalDigits = LENGTH(binInteger + binDecimal)
IFB totalDigits > 64 THEN
RESULT = ERR_VALUE
PRINT "64bitを超えたため変換できません"
EXIT
ENDIF
ENDIF
ELSE
// 指定ビットに調整
IFB totalDigits <= digits THEN
binInteger = strPad(binInteger, digits - LENGTH(binDecimal), "0", LEFT)
ELSE
// 桁あふれ調整
totalDigits = LENGTH(binInteger + binDecimal)
len = LENGTH(binInteger + binDecimal)
WHILE LENGTH(binInteger) > 8 AND len > digits
IFB COPY(binInteger, 1, 4) = "0000" THEN
binInteger = COPY(binInteger, 5)
len = len - 4
ELSE
BREAK
ENDIF
WEND
WHILE LENGTH(binDecimal) > 4 AND LENGTH(binInteger + binDecimal) > digits
IFB COPY(binDecimal, LENGTH(binDecimal) - 4) = "0000" THEN
binDecimal = COPY(binDecimal, 1, LENGTH(binDecimal) - 4)
ELSE
BREAK
ENDIF
WEND
tmp = binInteger + "." + binDecimal
binInteger = COPY(tmp, 1, POS(".", tmp) - 1)
binDecimal = COPY(tmp, POS(".", tmp) + 1)
len = LENGTH(binInteger + binDecimal)
IFB len > digits THEN
DIM deleteLength = len - digits
IFB deleteLength = LENGTH(binDecimal) THEN
binDecimal = ""
PRINT "指定ビット数にするため小数点以下を削除しました"
ELSEIF deleteLength < LENGTH(binDecimal) THEN
binDecimal = COPY(binDecimal, 1, LENGTH(binDecimal) - deleteLength)
PRINT "指定ビット数にするため小数点以下の一部を削除しました"
ELSE
RESULT = ERR_VALUE
PRINT "指定ビット数では変換できません"
EXIT
ENDIF
ENDIF
ENDIF
ENDIF
bin = binInteger + IIF(binDecimal <> "", "." + binDecimal, "")
// (5) 入力値がマイナスのため、2進数をマイナス値に変換する
IFB negativeFlg THEN
// 1の補数
bin = bitNot(bin)
// 2の補数
DIM res = ""
DIM carry = "1"
FOR i = LENGTH(bin) TO 1 STEP -1
IFB carry = "1" THEN
SELECT COPY(bin, i, 1)
CASE "0"
res = "1" + res
carry = 0
CASE "1"
res = "0" + res
DEFAULT
res = COPY(bin, i, 1) + res
SELEND
ELSE
res = COPY(bin, i, 1) + res
ENDIF
NEXT
bin = res
ENDIF
ENDIF
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
//////////////////////////////////////////////////
// 【引数】
// variable : 型を調べる変数
// 【戻り値】
// : TRUE : 与えられた変数が文字列型である、
// FALSE : 与えられた変数が文字列型でない、 :
//////////////////////////////////////////////////
FUNCTION isString(variable)
RESULT = IIF(VARTYPE(variable) = VAR_ASTR OR VARTYPE(variable) = VAR_USTR, TRUE, FALSE)
FEND
//////////////////////////////////////////////////
// 【引数】
// num : 符号を求める数値
// 【戻り値】
// 1 : 正の数、0 : ゼロ、-1 : 負の数、ERR_VALUE : それ以外
//////////////////////////////////////////////////
FUNCTION sign(num)
SELECT TRUE
CASE !CHKNUM(num)
RESULT = ERR_VALUE
CASE num > 0
RESULT = 1
CASE num = 0
RESULT = 0
CASE num < 0
RESULT = -1
SELEND
FEND
//////////////////////////////////////////////////
// 【引数】
// input : 入力文字列
// length : 埋めたあとの長さ
// str : 埋める文字
// type : 埋める方向
// 【戻り値】
// 指定文字で埋めた文字列
//////////////////////////////////////////////////
FUNCTION strPad(input, length, str = " ", type = RIGHT)
DIM s = ""
SELECT type
CASE LEFT
FOR i = 1 TO CEIL((length - LENGTH(input)) / LENGTH(str))
s = s + str
NEXT
input = COPY(s, 1, length - LENGTH(input)) + input
CASE RIGHT
FOR i = 1 TO CEIL((length - LENGTH(input)) / LENGTH(str))
s = s + str
NEXT
input = input + COPY(s, 1, length - LENGTH(input))
SELEND
RESULT = input
FEND
//////////////////////////////////////////////////
// 【引数】
// inputs : 繰り返す文字列
// multiplier : inputsを繰り返す回数
// 【戻り値】
// inputsをmultiplier回を繰り返した文字列を返します
//////////////////////////////////////////////////
FUNCTION strRepeat(inputs, multiplier)
DIM res = ""
FOR n = 1 TO multiplier
res = res + inputs
NEXT
RESULT = res
FEND
- 結果
復号シフト 取得される平文 1 Vjku ku c rgp. 2 Uijt jt b qfo. 3 This is a pen. 4 Sghr hr z odm. 5 Rfgq gq y ncl. 6 Qefp fp x mbk. 7 Pdeo eo w laj. 8 Ocdn dn v kzi. 9 Nbcm cm u jyh. 10 Mabl bl t ixg. 11 Lzak ak s hwf. 12 Kyzj zj r gve. 13 Jxyi yi q fud. 14 Iwxh xh p etc. 15 Hvwg wg o dsb. 16 Guvf vf n cra. 17 Ftue ue m bqz. 18 Estd td l apy. 19 Drsc sc k zox. 20 Cqrb rb j ynw. 21 Bpqa qa i xmv. 22 Aopz pz h wlu. 23 Znoy oy g vkt. 24 Ymnx nx f ujs. 25 Xlmw mw e tir. 26 Wklv lv d shq. - 結果
Guvf vf n cra.
- 結果
This is a pen. This is a pen.
- 与えられた2つの入力のうち片方が真・片方が偽のとき真を出力し、両方とも真もしくは偽のときは偽を出力する。
- ビットごとの排他的論理和は特定ビットの反転操作なので、2回繰り返せばもとに戻る。
暗号化︰ lqir@hadpsoh.frp
復号︰ info@example.com
シーザー暗号
シーザー暗号は単一換字式暗号の一種で、平文の各文字を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\]シーザー暗号の解析
シーザー暗号で暗号化されていることがわかっている場合、26パターンしかないので総当たりをすることで解読することができます。
以下のプログラムで全パターンを出力することができ、その結果の中から暗号化する前の文字列を見つけることができます。
DIM str = "シーザー暗号で暗号化した文字列"
FOR i = 1 TO 26
PRINT i + "<#TAB>" + Cipher.Caesar.decode(str, i)
NEXT
例えばWklv lv d shq.という文字列を解析したい場合は、以下のプログラムで全パターンを出力します。出力された結果の中から、出力された平文を順に調べていくと3番目のThis is a pen.が元の文だということがわかります。
DIM str = "Wklv lv d shq."
FOR i = 1 TO 26
PRINT i + "<#TAB>" + Cipher.Caesar.decode(str, i)
NEXT
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\]DIM str = "This is a pen."
PRINT Cipher.ROT13.encode(str)
ROT13の解析
ROT13はアルファベットを13文字シフトしただけなので、もう一度ROT13で暗号化(13文字後ろにシフト)するか復号(13文字前にシフト)することで解析することができます。
DIM str = "Guvf vf n cra."
PRINT Cipher.ROT13.encode(str)
PRINT Cipher.ROT13.decode(str)
ヴィジュネル暗号
アルファベットを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(排他的論理和)には、以下の特徴があります。
関連記事
- MODULE化
- QuotedPrintable関数 (自作関数)
- Quoted-printableのエンコード・デコードを行います。
- Base64関数 (自作関数)
- Base64のエンコード・デコードを行います。
- Morse関数 (自作関数)
- モールス信号の符号化・復号を行います。