Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/visual-studio-2012/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何在C#AES256加密和Java解密期间处理BadPaddingException_Java_C#_Security_Encryption_Aes - Fatal编程技术网

如何在C#AES256加密和Java解密期间处理BadPaddingException

如何在C#AES256加密和Java解密期间处理BadPaddingException,java,c#,security,encryption,aes,Java,C#,Security,Encryption,Aes,我不知道为什么会出现错误 线程“main”javax.crypto.BadPaddingException中的异常:给定的最后一个块没有正确填充。如果在解密过程中使用了坏密钥,则可能会出现此类问题。 我知道在解密过程中使用不正确的密钥时会发生此错误。但是,如果您查看下面的测试结果,您可以看到C#和Java都是相同的(Key,IV,Salt是Base64编码的) C#测试结果 Java测试结果 都一样!(钥匙、IV、盐) 但会生成当前的BadpaddingException错误。有什么问题吗?

我不知道为什么会出现错误

线程“main”javax.crypto.BadPaddingException中的异常:给定的最后一个块没有正确填充。如果在解密过程中使用了坏密钥,则可能会出现此类问题。

我知道在解密过程中使用不正确的密钥时会发生此错误。但是,如果您查看下面的测试结果,您可以看到C#和Java都是相同的(Key,IV,Salt是Base64编码的)

  • C#测试结果
  • Java测试结果
  • 都一样!(钥匙、IV、盐)

    但会生成当前的BadpaddingException错误。有什么问题吗? 我正在附加我的源文件

  • C#(加密)
  • Java(解密)
  • 我已验证如下。

  • C#
  • Java中的验证密钥和IV
  • 已更新

    netframework4.5/Java8修改了@Topaco所说的内容,并确认它运行良好

    我想对@Topaco和@Gusto2表示非常感谢,我将对在安全方面修改过的部件进行更改,正如@Gusto2所说的

    while((read = input.read(buffer)) != -1){
           output.write(c.update(buffer, 0, read));
    }
    byte[] deryptedBytes = c.doFinal(buffer)
    
    您正在对文件的输入进行解密,然后使用相同的密码实例将最后读取的块(再次)解密到一个单独的数组中,而不是文件

    快速修复:

    while((read = input.read(buffer)) != -1){
           output.write(c.update(buffer, 0, read));
    }
    output.write(c.doFinal()); // write the padded block
    
    如果要创建并打印解密的字符串,则需要创建一个新的密码实例(或者,我不确定是否足以重新初始化该实例),假设缓冲区包含整个输入

    c.init(Cipher.DECRYPT_MODE, keySpec, ivSpec);
    // assuming the buffer contains the whole input again
    byte[] deryptedBytes = c.doFinal(buffer); // decrypting the whole file again
    
    正确的方法:

    • IV用于安全地重复使用同一加密密钥进行多次加密。因此,如果您的密钥不是随机的,那么您应该为每次加密生成新的随机IV(并沿着密文传递IV,通常是在前面加上)。否则,加密在语义上是不安全的,您可能会为双键盘攻击创建漏洞。因此,从密钥派生IV可能不是很安全

    • 我建议使用随密文传递的任何MAC(身份验证码),以确保完整性(例如HMAC)

    • 您仍在将所有输入的文件完全读取到内存中,这对于真正大的文件是不起作用的。您可以将缓冲区初始化为任意长度(几MB?),并将输入文件分块处理

    1)在C#
    加密
    方法中,先加密纯文本,然后进行Base64编码。因此,在解密过程中,必须先对数据进行Base64解码,然后再进行解密。目前,这是以错误的顺序处理的,即数据先解密,然后解码。因此,在Java
    fileProcessing
    -方法中

    while((read = input.read(buffer)) != -1){
        output.write(c.update(buffer, 0, read));
    }
    

    2) 无需将
    buffer
    (或
    bufferDecoded
    )传递给
    doFinal
    -方法,因为这已经在
    update
    -方法中完成了。因此,

    byte[] deryptedBytes = c.doFinal(buffer);
    
    必须替换为

    output.write(c.doFinal());
    
    3) 由于Base64解码已在
    try
    -语句中的1)中完成,因此必须删除
    doFinal
    -语句后面的所有行。总的来说,这会导致

    try {
        input = new BufferedInputStream(new FileInputStream(source));
        output = new BufferedOutputStream(new FileOutputStream(dest));
        byte[] buffer = new byte[input.available()];
        int read = -1;
        while((read = input.read(buffer)) != -1) {
            byte[] bufferEncoded = buffer;
            if (read != buffer.length) { 
                bufferEncoded = Arrays.copyOf(buffer, read);
            }
            byte[] bufferDecoded = Base64.getDecoder().decode(bufferEncoded);
            output.write(c.update(bufferDecoded));
        }
        output.write(c.doFinal()); 
    }
    
    4) 缓冲区的大小必须是4的倍数,以确保正确的Base64解码。因此,更换更可靠

    byte[] buffer = new byte[input.available()];
    


    只要在一个块中读取数据(这不是保证的,请参见示例),就没有问题。但是,如果数据是以多个块读取的,则必须读取4字节的倍数,否则Base64解码将失败。这可以通过使用缓冲区大小(不是4的倍数)轻松证明。如果针对较大的文件明确定义了缓冲区大小,则还必须考虑这一点。

    我从您的答案中得到了很多帮助,我发现我的解码顺序是错误的,但是错误仍然被输出的原因是什么呢?当我使用您未更改的C#代码和您的Java代码(包括建议的修改1-4)时,我无法再现任何错误。我对一些文本文件进行了加密,没有任何问题。因此,您是否得到了相同的异常(BadPaddingException)?ist是否再次抛出到同一行(现在已修改)最后一行?您是否确定更改(1-4)已完成(最好复制并粘贴try块)?我没有更改c代码,我通过引用您的测试源代码进行了更改,但BadPaddingException仍然是结果。我可以检查一下你的测试源吗?我已经加密和解密了几个文件,包括“100个销售记录”(一个5 KB的压缩文件)。我使用了zip文件本身(即没有提取)。代码再次执行时没有任何问题。因此,我无法复制BadPaddingException。可能它与某个JDK/JRE版本有关,可能与一个特殊的配置相结合。
    while((read = input.read(buffer)) != -1) {
        byte[] bufferEncoded = buffer;
        if (read != buffer.length) { 
            bufferEncoded = Arrays.copyOf(buffer, read);
        }
        byte[] bufferDecoded = Base64.getDecoder().decode(bufferEncoded);
        output.write(c.update(bufferDecoded));
    }
    
    byte[] deryptedBytes = c.doFinal(buffer);
    
    output.write(c.doFinal());
    
    try {
        input = new BufferedInputStream(new FileInputStream(source));
        output = new BufferedOutputStream(new FileOutputStream(dest));
        byte[] buffer = new byte[input.available()];
        int read = -1;
        while((read = input.read(buffer)) != -1) {
            byte[] bufferEncoded = buffer;
            if (read != buffer.length) { 
                bufferEncoded = Arrays.copyOf(buffer, read);
            }
            byte[] bufferDecoded = Base64.getDecoder().decode(bufferEncoded);
            output.write(c.update(bufferDecoded));
        }
        output.write(c.doFinal()); 
    }
    
    byte[] buffer = new byte[input.available()];
    
    byte[] buffer = new byte[4 * (input.available() / 4)];