gpt4 book ai didi

java - 最后一个 block 使用 CipherInputStream/CipherOutputStream 不完整,即使使用填充 AES/CBC/PKCS5Padding

转载 作者:太空狗 更新时间:2023-10-29 22:54:20 26 4
gpt4 key购买 nike

其实我在网上和stackoverflow里也查了很多,

最初我在加密和解密时不使用填充,

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

https://stackoverflow.com/a/10775577/1115788

我用 AES/CBC/PKCS5Padding 填充更新了我的代码同样的错误来了,最后一个 block 没有解密......

过去两天我一直在研究这个问题,但没有找到解决方案

我的密码:

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();
}
}

最佳答案

我遇到了完全相同的问题。公认的解决方案之所以有效,是因为您使用了不需要填充的密码模式,但这不是解决与密码相关的问题的方法。

根据 CipherOutputStream documentation ,您必须调用 close() 方法才能正确完成加密(即添加填充 block )。

This method invokes the doFinal method of the encapsulated cipher object, which causes any bytes buffered by the encapsulated cipher to be processed. The result is written out by calling the flush method of this output stream.

This method resets the encapsulated cipher object to its initial state and calls the close method of the underlying output stream.

如果您希望在调用 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);
}
}

然后你可以使用:

...
cos = new CipherOutputStream(new NotClosingOutputStream(os), encipher);
copyByte(is, cos);
cos.close();
...

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

关于java - 最后一个 block 使用 CipherInputStream/CipherOutputStream 不完整,即使使用填充 AES/CBC/PKCS5Padding,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12799726/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com