Lua Base64自定义编解码

Posted 抚琴一生

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Lua Base64自定义编解码相关的知识,希望对你有一定的参考价值。

一、背景

最近在研究如何使用纯lua实现base64自定义码表编解码,记录一下。一起探讨下。

二、代码实现

1、base64编码

-- 自定义编码表
local encodeTable =  [0] =
   'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P',
   'Q','R','S','T','U','V','W','X','Y','Z','a','b','c','d','e','f',
   'g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v',
   'w','x','y','z','0','1','2','3','4','5','6','7','8','9','+','/',


-- 字符串编码
local function base64Encode(s)
   local bs = encodeTable
   local byte, rep = string.byte, string.rep
   local pad = 2 - ((#s-1) % 3)
   s = (s..rep('\\0', pad)):gsub("...", function(cs)
      local a, b, c = byte(cs, 1, 3)
      return bs[a>>2] .. bs[(a&3)<<4|b>>4] .. bs[(b&15)<<2|c>>6] .. bs[c&63]
   end)
   return s:sub(1, #s-pad) .. rep('=', pad)
end

2、base64解码

参考:http://www.ruanyifeng.com/blog/2008/06/base64.html

-- 自定义解码表
local decodeTable =  [0] =
   'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P',
   'Q','R','S','T','U','V','W','X','Y','Z','a','b','c','d','e','f',
   'g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v',
   'w','x','y','z','0','1','2','3','4','5','6','7','8','9','+','/',


local decodeArr = [0] =
	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63,
	52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1,
	-1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
	15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1,
	-1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
	41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1


-- 字节转换
local function transferBytes(arr)
	local ss = 
	local k = 1
	while true do
		if k > #arr then break end
		local c = arr[k]
		if not c then break end
		if c<192 then
	           table.insert(ss, string.char(c))
			k = k + 1
		elseif c<224 then
			k = k + 2
		elseif c<240 then
			if c>=228 and c<=233 then
				local c1 = arr[k+1]
				local c2 = arr[k+2]
				if c1 and c2 then
					local a1,a2,a3,a4 = 128,191,128,191
					if c == 228 then a1 = 184
					elseif c == 233 then a2,a4 = 190,c1 ~= 190 and 191 or 165
					end
					if c1>=a1 and c1<=a2 and c2>=a3 and c2<=a4 then
						table.insert(ss, string.char(c,c1,c2))
					end
				end
			end
			k = k + 3
		elseif c<248 then
			k = k + 4
		elseif c<252 then
			k = k + 5
		elseif c<254 then
			k = k + 6
		end
	end
	return table.concat(ss)
end

-- 字符串解码
local function base64Decode(s)
    local bs = decodeTable
    local byte, rep = string.byte, string.rep

    local pad = 0
    local lastTwoString = string.sub(s, -2)
    local lastString = string.sub(s, -1)
    if lastTwoString == '==' then
        pad = 2
    elseif lastString == '=' then
        pad = 1
    end
    s = (s..rep('\\0', pad)):gsub('....', function (cs)
        local a, b, c, d = byte(cs, 1, 4)
        local aStr, bStr, cStr, dStr = '', '', '', ''
        if decodeArr[a] and bs[decodeArr[a]] then
            aStr = bs[decodeArr[a]]
        end
        if decodeArr[b] and bs[decodeArr[b]] then
            bStr = bs[decodeArr[b]]
        end
        if decodeArr[c] and bs[decodeArr[c]] then
            cStr = bs[decodeArr[c]]
        end
        if decodeArr[d] and bs[decodeArr[d]] then
            dStr = bs[decodeArr[d]]
        end

        return aStr .. bStr .. cStr .. dStr
    end)
    -- 自定义码表转换后的字符串
    local newStr = s:sub(1, #s-pad) .. rep('=', pad)
    
    local c1, c2, c3, c4 = -1, -1, -1, -1
    local len = #newStr
    local decodeStr = ''
    local i = 1

    local byteArr = 
    local byteA, byteB, byteC = 0, 0, 0

    while i <= len do
        -- c1
        while i <= len do
            c1 = decodeArr[byte(newStr, i, i+1)] & 0xff
            i = i + 1
            if c1 ~= -1 then
                break
            end
        end
        if c1 == -1 then
            break
        end

        -- c2
        while i <= len do
            c2 = decodeArr[byte(newStr, i, i+1)] & 0xff
            i = i + 1
            if c2 ~= -1 then
                break
            end
        end
        if c2 == -1 then
            break
        end
        byteA = (c1<<2)|(c2&0x30)>>4
        table.insert(byteArr, byteA)

        -- c3
        while i <= len do
            c3 = byte(newStr, i, i+1) & 0xff
            i = i + 1
            if c3 == 61 then
                return decodeStr
            end
            c3 = decodeArr[c3]
            if c3 ~= -1 then
                break
            end
        end
        if c3 == -1 then
            break
        end
        byteB = ((c2&0xF)<<4)|((c3&0x3C)>>2)
        table.insert(byteArr, byteB)

        -- c4
        while i <= len do
            c4 = byte(newStr, i, i+1) & 0xff
            i = i + 1
            if c4 == 61 then
                return decodeStr
            end
            c4 = decodeArr[c4]
            if c4 ~= -1 then
                break
            end
        end
        if c4 == -1 then
            break
        end
        byteC = ((c3&0x03)<<6)|c4
        table.insert(byteArr, byteC)
    end
    decodeStr = transferBytes(byteArr)
    return decodeStr
end

以上是关于Lua Base64自定义编解码的主要内容,如果未能解决你的问题,请参考以下文章

Lua Base64自定义编解码

URL编码表 Base64编码表 HTTP消息含义

URL编码表%20Base64编码表%20HTTP消息含义

2018-07-17 Base64解码与编码

C语言实现Base64编码/解码

python3url编解码base64编解码ASE加解密