【问题标题】:Android - Removing padded bits in decryptionAndroid - 在解密中删除填充位
【发布时间】:2013-05-18 19:29:09
【问题描述】:

我正在使用我自己的自定义加密方法开发一个安全应用程序,但在消息解密方面遇到了问题。

根据理论,必须填充输入以满足执行加密所需的位。但是即使在解密之后填充位仍然存在。

这是一个例子:

input (before padding) : q
input (after padding)  : 113 0 0 0 0 0 0 0 (in Bytes)

然后我执行一些代码:

bytes[] a = encrypt(input);
bytes[] b = decrypt(a);

String output = "";
output = new String(b, "UTF-8");

System.out.println 的输出如下:

b      : 113 0 0 0 0 0 0 0
output : q[][][][][][][]

我不知道如何删除填充位。我目前正在使用以下功能:

public String processOutput(String dtxt){
    String result = "";
    int l = dtxt.length();
    for(int i=0;i<l-16;i++) result = result + dtxt.charAt(i);
    for(int i=l-16;i<l;i++){
        if((long)dtxt.charAt(i)!=0){
            result = result + dtxt.charAt(i);
        }
    } return result;
}

但是这个函数只有在我把输出放到一个字符串时才有效。如果输出是一个文件(比如说一个图像文件)怎么办?解密后如何删除填充位?请帮忙。

【问题讨论】:

    标签: java android cryptography padding


    【解决方案1】:

    您应该使用诸如Cipher.getInstance("AES/CBC/PKCS5Padding") 之类的填充。正如您现在使用的那样,零填充存在一个问题,即您无法区分以00 值字节结尾的纯文本和填充。如果您执行取消填充,那么您至少会遇到最后一个块的问题。当然,对于文本,您可以在执行字符解码例程之前删除末尾的 00 值字节。另一种方法是在纯文本的开头添加一个 64 位大小的指示符。

    请注意,默认的 Oracle Java 提供程序没有零填充选项(据我所知),因此您要么必须自己进行取消填充,要么必须使用另一个 JCE 提供程序,例如 Bouncy Castle provider包括零填充选项(例如Cipher.getInstance("AES/CBC/ZeroPadding")

    注意Wikipedia page on padding has much to say on the matter.另请注意,CBC 模式本身不提供完整性保护或身份验证,仅提供机密性且仅在正确使用的情况下提供。

    【讨论】:

      【解决方案2】:

      您可以在流模式下使用分组密码(例如 AES)来完全摆脱填充。所以你可以使用例如Cipher.getInstance("AES/CTR/NoPadding") 或者如果您还想包含身份验证标签 Cipher.getInstance("AES/GCM/NoPadding")。后者会在密文的末尾添加一些字节,您可以使用这些字节来确保密文是使用正确的密钥创建的,并且密文没有被更改。

      请注意,您可能会泄露有关纯文本大小的信息。这对于 CBC 模式也是如此,但在这种情况下,您至少会有 16 字节(块大小)的边距。使用流模式加密,您将加密到完全相同的字节数。另请注意,您需要为具有相同密钥的每个加密使用新的 IV 值,否则您可能会直接将明文暴露给攻击者。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-03-15
        • 2012-12-26
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-12-21
        相关资源
        最近更新 更多