nslua.dllでbit演算

取り急ぎ。後で解説を追加する。

本体

do
	local bit = 8 -- 8ビットまでのxor計算をする。
	local base_table = {1} -- 桁毎の数値を入れておく。
	while bit > #base_table do -- 基数テーブルを作る。
		base_table[1+#base_table] = base_table[#base_table] * 2
	end
	
	local logic = function(box, base)
		if box.a < base then box.af = false else
			box.af = true
			box.a = box.a - base
		end
		if box.b < base then box.bf = false else
			box.bf = true
			box.b = box.b - base
		end
	end
	
	local make_box = function(a, b)
		local box = {}
		box.a = a
		box.b = b
		return box
	end
	
	local bit_not = function(num) -- 一つの数値を受け取り、ビット反転して返す。
		local res = 0
		for i = bit, 1, -1 do
			if num < base_table[i] then
				res = res + base_table[i]
			else
				num = num - base_table[i]
			end
		end
		return res
	end
	math.bit_not = bit_not

	local bit_and = function(numa, numb) -- 二つの数値を受け取り、それをandして返す。
		local box = make_box(numa, numb)
		local res = 0
		for i = bit, 1, -1 do
			logic(box, base_table[i])
			if box.af and box.bf then res = res + base_table[i] end
		end
		return res
	end
	math.bit_and = bit_and

	local bit_or = function(numa, numb) -- 二つの数値を受け取り、それをorして返す。
		local box = make_box(numa, numb)
		local res = 0
		for i = bit, 1, -1 do
			logic(box, base_table[i])
			if box.af or box.bf then res = res + base_table[i] end
		end
		return res
	end
	math.bit_or = bit_or

	local bit_xor = function(numa, numb) -- 二つの数値を受け取り、それをxorして返す。
		local box = make_box(numa, numb)
		local res = 0
		for i = bit, 1, -1 do
			logic(box, base_table[i])
			if box.af then
				if box.bf then else res = res + base_table[i] end
			else
				if box.bf then res = res + base_table[i] else end
			end
		end
		return res
	end
	math.bit_xor = bit_xor
	
	local bit_xand = function(numa, numb) -- 二つの数値を受け取り、それをxandして返す。
		local box = make_box(numa, numb)
		local res = 0
		for i = bit, 1, -1 do
			logic(box, base_table[i])
			if box.af then
				if box.bf then res = res + base_table[i] else end
			else
				if box.bf then else res = res + base_table[i] end
			end
		end
		return res
	end
	math.bit_xand = bit_xand
	
	string.bit_not = function(str)
		local res = {}
		for i, letter in ipairs({str:byte(1, str:len())}) do
			res[i] = string.char(bit_not(letter))
		end
		return table.concat(res)
	end

	string.bit_xor = function(str, key)
		local res = {}
		local keys = {key:byte(1, key:len())}
		local key_num = 1
		for i, letter in ipairs({str:byte(1, str:len())}) do
			res[i] = string.char(bit_xor(letter, keys[key_num]))
			key_num = key_num + 1
			if type(keys[key_num]) == "nil" then key_num = 1 end
		end
		return table.concat(res)
	end
end
  • math.bit_not
  • math.bit_and
  • math.bit_or
  • math.bit_xand
  • math.bit_xor
  • string.not
  • string.xor

を追加する。math系のnot以外は数値を二つ渡して名前のとおりの処理をした後結果を一つ返す。notは引数を一つだけ取る。
string.notは、ある文字列に対して全ての文字の文字コードをnot処理して返す。そのため、8bitしか扱わないように制限してある。
string.xorは、第二引数として別の文字列を与える。それを使ってxor処理して返す。
string系で注意しなければならないのは、変換した結果に文字コード0が含まれた場合であり、それをNScripterの文字列変数に渡すとそこで文字列が切れてしまうことである。
よって、string系で変換した内容は、Luaの中だけで扱うようにするのが無難である。

文字列をなんちゃって暗号化する

NSExec("luasub coding")
function NSCOM_coding()
	local res = NSPopStrRef()
	NSPopComma()
	local str = NSPopStr()
	NSSetStrValue(res, string.bit_not(str))
end

NScripter側にcoding命令を追加する。
codingでなんちゃって暗号化した文字列は、もう一度codingに渡すことで元の文字列に戻る。