美文网首页
lua-lockbox padding problem

lua-lockbox padding problem

作者: allanYan | 来源:发表于2016-08-03 17:04 被阅读0次

    前言

    在最近的项目中,使用nginx+lua来进行安全管理,其中要用到des算法;根据luajit官方的推荐,采用是lua-resty-nettle,但在使用过程中发现,lua-resty-nettle采用的是0补位,而JDK中实现的是PKCS5Padding;

    继续寻找新的类库,由于团队对c并不熟悉,考虑到后续的维护方便,优先选择纯lua的实现,这时lua-lockbox进入到我们的视野;但在使用过程中发现虽然java和lua代码采用相同的分块模式(ECB),相同的补位(java是PKCS5Padding,lua是PKCS7Padding),但lua加密的数据无法用java解密。报错信息为:

    javax.crypto.BadPaddingException: Given final block not properly padded;
    

    错误信息很明细,lua补位不正确;直接看源码pkcs7.lua,发现其补位逻辑如下:

    
    local Stream = require("lockbox.util.stream");
    
    local PKCS7Padding = function(blockSize,byteCount)
    
    local paddingCount = blockSize - ((byteCount -1) % blockSize) + 1;
    
    local bytesLeft = paddingCount;
    
    local stream = function()
    
    if bytesLeft > 0 then
    
    bytesLeft = bytesLeft - 1;
    
    return paddingCount;
    
    else
    
    return nil;
    
    end
    
    end
    
    return stream;
    
    end
    
    return PKCS7Padding;
    
    

    那么PKCS5Padding到底是如何补位的呢?具体可参考如下资料:

    • PKCS #7: Cryptographic Message Syntax Standard
      :An RSA Laboratories Technical Note, Version 1.5. Revised November 1, 1993.

    • PKCS #5: Password-Based Encryption Standard:
      An RSA Laboratories Technical Note, Version 1.5. Revised November 1, 1993. f

      阅读上面的资料,可以发现PKCS #7 填充字符串由一个字节序列组成,每个字节填充该字节序列的长度。 假定块长度为 8,数据长度为 9,则填充用八位字节数等于 7,数据等于 FF FF FF FF FF FF FF FF FF:
      数据: FF FF FF FF FF FF FF FF FF
      PKCS7 填充: FF FF FF FF FF FF FF FF FF 07 07 07 07 07 07 07

      而根据lua-lockbox的补位逻辑,补位结果为:
      lua-lockbox补位:FF FF FF FF FF FF FF FF FF 09 09 09 09 09 09 09 09 09
      因此lua-lockbox对于PKCS7Padding的实现有误,修改代码为:

    local paddingCount = blockSize - (byteCount % blockSize);
    

    加密的补位问题解决了,但又发现另外一个问题,解密时,lua-lockbox没有去掉补位数据,从上面的pkcs7.lua代码可以看到,lua-lockbox并没有实现该逻辑,采用临时解决方案,修改ecb.lua或cbc.lua,将其解密的finish方法修改为:

            local data=Stream.toArray(outputQueue.pop)
            local paddingByte=data[#data]
    
            local realLength=#data-paddingByte--如果有padding,计算去除padding后的长度
            local padded=true
            for i=#data,realLength+1,-1 do
                if(data[i]~=paddingByte) then
                    padded=false
                end
            end
            print("realLength is "..realLength)
            local paddedBytes=Array.slice(data,1,realLength)
            
            if padded then
                Array.writeToQueue(outputQueue,paddedBytes)
            end
            --paddingStream = padding(blockCipher.blockSize,inputQueue.getHead());
            --public.update(paddingStream);
    
            return public;
    

    目前的解决办法比较粗糙,后续有时间进行完善;

    PKCS#5/7区别

    在PKCS5Padding中,明确定义Block的大小是8位,而PKCS7Padding定义中,块的大小是不确定的,可以在1-255之间(块长度超出255的尚待研究),填充值的算法都是一样的:

    value=k - (l mod k)  ,K=块大小,l=数据长度,如果l=8, 则需要填充额外的8个byte的8
    

    DES填充方式

    DES是对64位数据的加密算法,如数据位数不足64位的倍数,需要填充,补充到64位的倍数。

    • NoPadding
      API或算法本身不对数据进行处理,加密数据由加密双方约定填补算法。例如若对字符串数据进行加解密,可以补充\0或者空格,然后trim

    • PKCS5Padding
      加密前:数据字节长度对8取余,余数为m,若m>0,则补足8-m个字节,字节数值为8-m,即差几个字节就补几个字节,字节数值即为补充的字节数,若为0则补充8个字节的8
      解密后:取最后一个字节,值为m,则从数据尾部删除m个字节,剩余数据即为加密前的原文

    • SSL3Padding
      SSL3.0协议定义的填补算法

    参考资料

    相关文章

      网友评论

          本文标题:lua-lockbox padding problem

          本文链接:https://www.haomeiwen.com/subject/yugqsttx.html