最后一个块与CipherInputStream/CipherOutputStream不完整,即使使用填充AES/CBC/PKCS5Padding

Man*_*ani 15 java encryption android aes padding

实际上,为了这个,我也从互联网和stackoverflow搜索了很多,

最初我在加密和解密中没有使用填充,

但最后我从这里得到了解决方案

/sf/answers/754290421/

并且我使用填充更新了我的代码作为AES/CBC/PKCS5Padding并且同样的错误即将到来,并且最后一个块没有被解密...

我正在为此工作最后两天,但没有找到解决方案

我的Crypter代码:

package mani.droid.browsedropbox;

import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.math.BigInteger;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import javax.crypto.Cipher;
import javax.crypto.CipherInputStream;
import javax.crypto.CipherOutputStream;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.SecretKey;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;

public class Crypter {

    Cipher encipher;
    Cipher decipher;
CipherInputStream cis;
CipherOutputStream cos;
FileInputStream fis;
byte[] ivbytes = new byte[]{(byte)'a', (byte)'b', (byte)'c', (byte)'d', (byte)'e',                                                                                          (byte)'f', (byte)'g', (byte)'h', (byte)'i', (byte)'j', (byte)'k', (byte)'l', (byte)'m',     (byte)'n', (byte)'o', (byte)'p'};
    IvParameterSpec iv = new IvParameterSpec(ivbytes);

public boolean enCrypt(String key, InputStream is, OutputStream os)
{
    try {
        byte[] encoded = new BigInteger(key, 16).toByteArray();
        SecretKey seckey = new SecretKeySpec(encoded, "AES");
        encipher = Cipher.getInstance("AES/CBC/PKCS7Padding");
        encipher.init(Cipher.ENCRYPT_MODE, seckey, iv);
        cis = new CipherInputStream(is, encipher);
        copyByte(cis, os);
        return true;
    } 
    catch (InvalidKeyException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (NoSuchAlgorithmException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (NoSuchPaddingException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (InvalidAlgorithmParameterException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
    return false;
}

public boolean deCrypt(String key, InputStream is, OutputStream os)
{
    try {
        byte[] encoded = new BigInteger(key, 16).toByteArray();
        SecretKey seckey = new SecretKeySpec(encoded, "AES");
        encipher = Cipher.getInstance("AES/CBC/PKCS7Padding");
        encipher.init(Cipher.DECRYPT_MODE, seckey, iv);
        cos = new CipherOutputStream(os, encipher);
        copyByte(is, cos);
        //cos.close();
        return true;
    } 
    catch (InvalidKeyException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (NoSuchAlgorithmException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (NoSuchPaddingException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (InvalidAlgorithmParameterException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
    return false;
}

public void copyByte(InputStream is, OutputStream os) throws IOException
{
    byte[] buf = new byte[8192];
    int numbytes;
    while((numbytes = is.read(buf)) != -1)
    {
        os.write(buf, 0, numbytes);
        os.flush();
    }
    os.close();
    is.close();
}
}
Run Code Online (Sandbox Code Playgroud)

ph4*_*r05 13

我有完全相同的问题.已接受的解决方案有效,因为您使用了不需要填充的密码模式,但这不是解决加密相关问题的方法.

根据CipherOutputStream 文档,您必须调用close()方法才能正确完成加密(即添加填充块).

此方法调用封装的密码对象的doFinal方法,这会导致处理由封装的密码缓冲的任何字节.通过调用此输出流的flush方法写出结果.

此方法将封装的密码对象重置为其初始状态,并调用基础输出流的close方法.

如果要在调用CipherOutputStream.close()方法后保持OutputStream保持打开状态,则可以将OutputStream包装到不关闭它的流中.例如:

public class NotClosingOutputStream extends OutputStream {
  private final OutputStream os;

  public NotClosingOutputStream(OutputStream os) {
    this.os = os;
  }

  @Override
  public void write(int b) throws IOException {
    os.write(b);
  }

  @Override
  public void close() throws IOException {
    // not closing the stream.
  }

  @Override
  public void flush() throws IOException {
    os.flush();
  }

  @Override
  public void write(byte[] buffer, int offset, int count) throws IOException {
    os.write(buffer, offset, count);
  }

  @Override
  public void write(byte[] buffer) throws IOException {
    os.write(buffer);
  }
}
Run Code Online (Sandbox Code Playgroud)

然后你可以使用:

...
cos = new CipherOutputStream(new NotClosingOutputStream(os), encipher);
copyByte(is, cos);
cos.close();
...
Run Code Online (Sandbox Code Playgroud)

请注意,os流不会关闭,您需要在适当的时候自行完成.


Man*_*ani 7

最后我得到了我自己的问题的答案,试验和错误实际上这里冲突是我设置填充 encipher = Cipher.getInstance("AES/CBC/PKCS7Padding");

并设置IV有一些值.....,

最后我得到的答案只是替换了算法

从:

AES/CBC/PKCS7Paddinng

至:

AES/CFB8/NoPadding

它的工作方式就像魅力一样......所以我建议这个答案给那些在这个问题上挣扎的人,如果你解决了你的问题,那么就为别人提一下......