zoukankan      html  css  js  c++  java
  • lua之base64的解码和编码(三种方案实现)

    概述

    由于涉及到java 与 lua 之间传递字节数组,如果直接传递的话会导致json解析失败,所以需要将字节数组加密为字符串,这样可以保证数据的完整传输。
    在网上找到了多个版本的lua base64的编解码代码,经过逐个测试最终方案3解决了我的问题。

    方案1:

    调用decodeBase64解码测试的时候经常返回nil值
    参考:http://www.cnblogs.com/decode1234/p/8505001.html

    -- lbase64加密和解密算法
    local function encodeBase64(source_str)
        local b64chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'
        local s64 = ''
        local str = source_str
    
        while #str > 0 do
            local bytes_num = 0
            local buf = 0
    
            for byte_cnt=1,3 do
                buf = (buf * 256)
                if #str > 0 then
                    buf = buf + string.byte(str, 1, 1)
                    str = string.sub(str, 2)
                    bytes_num = bytes_num + 1
                end
            end
    
            for group_cnt=1,(bytes_num+1) do
                local b64char = math.fmod(math.floor(buf/262144), 64) + 1
                s64 = s64 .. string.sub(b64chars, b64char, b64char)
                buf = buf * 64
            end
    
            for fill_cnt=1,(3-bytes_num) do
                s64 = s64 .. '='
            end
        end
    
        return s64
    end
    
    local function decodeBase64(str64)
        local b64chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'
        local temp={}
        for i=1,64 do
            temp[string.sub(b64chars,i,i)] = i
        end
        temp['=']=0
        local str=""
        for i=1,#str64,4 do
            if i>#str64 then
                break
            end
            local data = 0
            local str_count=0
            for j=0,3 do
                local str1=string.sub(str64,i+j,i+j)
                if not temp[str1] then
                    return
                end
                if temp[str1] < 1 then
                    data = data * 64
                else
                    data = data * 64 + temp[str1]-1
                    str_count = str_count + 1
                end
            end
            for j=16,0,-8 do
                if str_count > 0 then
                    str=str..string.char(math.floor(data/math.pow(2,j)))
                    data=math.mod(data,math.pow(2,j))
                    str_count = str_count - 1
                end
            end
        end
    
        local last = tonumber(string.byte(str, string.len(str), string.len(str)))
        if last == 0 then
            str = string.sub(str, 1, string.len(str) - 1)
        end
        return str
    end
    View Code

    方案2:

    参考:http://www.cnblogs.com/sjns/p/9958737.html

    测试ZZBase64.decode解码的时候,提示local num = a * 262144 + b * 4096 + c * 64 + d语句中的a为nil值

    ZZBase64 = {}
    local string = string
    
    ZZBase64.__code = {
        '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', '+', '/',
    };
    ZZBase64.__decode = {}
    for k,v in pairs(ZZBase64.__code) do
        ZZBase64.__decode[string.byte(v,1)] = k - 1
    end
    
    function ZZBase64.encode(text)
        local len = string.len(text)
        local left = len % 3
        len = len - left
        local res = {}
        local index  = 1
        for i = 1, len, 3 do
            local a = string.byte(text, i )
            local b = string.byte(text, i + 1)
            local c = string.byte(text, i + 2)
            -- num = a<<16 + b<<8 + c
            local num = a * 65536 + b * 256 + c
            for j = 1, 4 do
                --tmp = num >> ((4 -j) * 6)
                local tmp = math.floor(num / (2 ^ ((4-j) * 6)))
                --curPos = tmp&0x3f
                local curPos = tmp % 64 + 1
                res[index] = ZZBase64.__code[curPos]
                index = index + 1
            end
        end
        
        if left == 1 then
            ZZBase64.__left1(res, index, text, len)
        elseif left == 2 then
            ZZBase64.__left2(res, index, text, len)
        end
        return table.concat(res)
    end
    
    function ZZBase64.__left2(res, index, text, len)
        local num1 = string.byte(text, len + 1)
        num1 = num1 * 1024 --lshift 10
        local num2 = string.byte(text, len + 2)
        num2 = num2 * 4 --lshift 2
        local num = num1 + num2
        
        local tmp1 = math.floor(num / 4096) --rShift 12
        local curPos = tmp1 % 64 + 1
        res[index] = ZZBase64.__code[curPos]
        
        local tmp2 = math.floor(num / 64)
        curPos = tmp2 % 64 + 1
        res[index + 1] = ZZBase64.__code[curPos]
        
        curPos = num % 64 + 1
        res[index + 2] = ZZBase64.__code[curPos]
        
        res[index + 3] = "="
    end
    
    function ZZBase64.__left1(res, index,text, len)
        local num = string.byte(text, len + 1)
        num = num * 16
        
        tmp = math.floor(num / 64)
        local curPos = tmp % 64 + 1
        res[index ] = ZZBase64.__code[curPos]
        
        curPos = num % 64 + 1
        res[index + 1] = ZZBase64.__code[curPos]
        
        res[index + 2] = "="
        res[index + 3] = "="
    end
    
    function ZZBase64.decode(text)
        local len = string.len(text)
        local left = 0
        if string.sub(text, len - 1) == "==" then
            left = 2
            len = len - 4
        elseif string.sub(text, len) == "=" then
            left = 1
            len = len - 4
        end
        
        local res = {}
        local index = 1
        local decode = ZZBase64.__decode
        for i =1, len, 4 do
            local a = decode[string.byte(text,i    )]
            local b = decode[string.byte(text,i + 1)]
            local c = decode[string.byte(text,i + 2)]
            local d = decode[string.byte(text,i + 3)]
            
            --num = a<<18 + b<<12 + c<<6 + d
            local num = a * 262144 + b * 4096 + c * 64 + d
            
            local e = string.char(num % 256)
            num = math.floor(num / 256)
            local f = string.char(num % 256)
            num = math.floor(num / 256)
            res[index ] = string.char(num % 256)
            res[index + 1] = f
            res[index + 2] = e
            index = index + 3
        end
        
        if left == 1 then
            ZZBase64.__decodeLeft1(res, index, text, len)
        elseif left == 2 then
            ZZBase64.__decodeLeft2(res, index, text, len)
        end
        return table.concat(res)
    end
    
    function ZZBase64.__decodeLeft1(res, index, text, len)
        local decode = ZZBase64.__decode
        local a = decode[string.byte(text, len + 1)]
        local b = decode[string.byte(text, len + 2)]
        local c = decode[string.byte(text, len + 3)]
        local num = a * 4096 + b * 64 + c
        
        local num1 = math.floor(num / 1024) % 256
        local num2 = math.floor(num / 4) % 256
        res[index] = string.char(num1)
        res[index + 1] = string.char(num2)
    end
    
    function ZZBase64.__decodeLeft2(res, index, text, len)
        local decode = ZZBase64.__decode
        local a = decode[string.byte(text, len + 1)]
        local b = decode[string.byte(text, len + 2)]
        local num = a * 64 + b
        num = math.floor(num / 16)
        res[index] = string.char(num)
    end
    
    return ZZBase64
    View Code

    方案3:

    http://lua-users.org/wiki/BaseSixtyFour
    测试编解码ok

    base64 = {}
    
    local b='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/' -- You will need this for encoding/decoding
    
    -- encoding
    function base64.enc(data)
        return ((data:gsub('.', function(x) 
            local r,b='',x:byte()
            for i=8,1,-1 do r=r..(b%2^i-b%2^(i-1)>0 and '1' or '0') end
            return r;
        end)..'0000'):gsub('%d%d%d?%d?%d?%d?', function(x)
            if (#x < 6) then return '' end
            local c=0
            for i=1,6 do c=c+(x:sub(i,i)=='1' and 2^(6-i) or 0) end
            return b:sub(c+1,c+1)
        end)..({ '', '==', '=' })[#data%3+1])
    end
    
    -- decoding
    function base64.dec(data)
        data = string.gsub(data, '[^'..b..'=]', '')
        return (data:gsub('.', function(x)
            if (x == '=') then return '' end
            local r,f='',(b:find(x)-1)
            for i=6,1,-1 do r=r..(f%2^i-f%2^(i-1)>0 and '1' or '0') end
            return r;
        end):gsub('%d%d%d?%d?%d?%d?%d?%d?', function(x)
            if (#x ~= 8) then return '' end
            local c=0
            for i=1,8 do c=c+(x:sub(i,i)=='1' and 2^(8-i) or 0) end
                return string.char(c)
        end))
    end
    
    return base64
    View Code
  • 相关阅读:
    4-1 R语言函数 lapply
    3-6 向量化操作
    3-5 处理缺失值
    3-4 列表的子集
    3-3 数据框的子集
    3-2 矩阵的子集
    bootstrap 模式对话框
    手机端 超链接 识别电话号码
    jQuery设置和获取HTML、文本和值
    TP 框架 ajax[利用异步提交表单]
  • 原文地址:https://www.cnblogs.com/7qin/p/13511348.html
Copyright © 2011-2022 走看看