在java中使用AES/CBC/PKCS5P加密后的文件大小是多少
我尝试在使用套接字发送文件时使用加密和解密。我使用在java中使用AES/CBC/PKCS5P加密后的文件大小是多少,java,android,sockets,encryption,aes,Java,Android,Sockets,Encryption,Aes,我尝试在使用套接字发送文件时使用加密和解密。我使用AES/CBC/PKCS5Padding算法,首先写入IV,然后将文件写入流 问题是循环在文件接收时不会结束 我认为这是由于文件大小和加密文件似乎比原始文件小,而我给接收者原始文件的大小。如果这个假设是正确的,有没有办法计算加密文件的大小 文件发送者 SecretKey keySpec = new SecretKeySpec(key, "AES"); byte[] iv = AE
AES/CBC/PKCS5Padding
算法,首先写入IV
,然后将文件写入流
问题是循环在文件接收时不会结束
我认为这是由于文件大小和加密文件似乎比原始文件小,而我给接收者原始文件的大小。如果这个假设是正确的,有没有办法计算加密文件的大小
文件发送者
SecretKey keySpec = new SecretKeySpec(key, "AES");
byte[] iv = AES.randomNonce(16);
IvParameterSpec ivParameterSpec = new IvParameterSpec(iv);
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, keySpec, ivParameterSpec);
outputStream = socket.getOutputStream();
outputStream.write(iv);
outputStream.flush();
inputStream = context.getContentResolver().openInputStream(message.getUri());
cipherOutputStream = new CipherOutputStream(outputStream, cipher);
long size = message.getSize();
long written = 0;
byte[] buffer = new byte[8192];
int count;
int percent = 0;
while (!isStopped && (count = inputStream.read(buffer)) > 0) {
cipherOutputStream.write(buffer, 0, count);
written += count;
int p = (int) (((float) written / (float) size) * 100);
if (percent != p) {
percent = p;
if (onProgressListener != null) {
onProgressListener.onProgress(percent);
}
}
}
cipherOutputStream.flush();
if (onProgressListener != null) {
onProgressListener.onEnd(null);
}
inputStream = socket.getInputStream();
fileOutputStream = new FileOutputStream(file);
byte[] iv = new byte[16];
inputStream.read(iv);
SecretKey keySpec = new SecretKeySpec(key, "AES");
IvParameterSpec ivParameterSpec = new IvParameterSpec(iv);
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.DECRYPT_MODE, keySpec, ivParameterSpec);
cipherInputStream = new CipherInputStream(inputStream, cipher);
long size = message.getSize();
long read = size;
byte[] buffer = new byte[8192];
int count;
int percent = 0;
while (!isStopped && read > 0 && (count = cipherInputStream.read(buffer, 0, (int) Math.min(buffer.length, read))) != -1) {
fileOutputStream.write(buffer, 0, count);
read -= count;
int p = (int) (((float) read / (float) size) * 100);
if (percent != p) {
percent = p;
if (onProgressListener != null) {
onProgressListener.onProgress(100 - percent);
}
}
}
if (onProgressListener != null) {
onProgressListener.onEnd(Uri.fromFile(file));
}
文件接收器
SecretKey keySpec = new SecretKeySpec(key, "AES");
byte[] iv = AES.randomNonce(16);
IvParameterSpec ivParameterSpec = new IvParameterSpec(iv);
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, keySpec, ivParameterSpec);
outputStream = socket.getOutputStream();
outputStream.write(iv);
outputStream.flush();
inputStream = context.getContentResolver().openInputStream(message.getUri());
cipherOutputStream = new CipherOutputStream(outputStream, cipher);
long size = message.getSize();
long written = 0;
byte[] buffer = new byte[8192];
int count;
int percent = 0;
while (!isStopped && (count = inputStream.read(buffer)) > 0) {
cipherOutputStream.write(buffer, 0, count);
written += count;
int p = (int) (((float) written / (float) size) * 100);
if (percent != p) {
percent = p;
if (onProgressListener != null) {
onProgressListener.onProgress(percent);
}
}
}
cipherOutputStream.flush();
if (onProgressListener != null) {
onProgressListener.onEnd(null);
}
inputStream = socket.getInputStream();
fileOutputStream = new FileOutputStream(file);
byte[] iv = new byte[16];
inputStream.read(iv);
SecretKey keySpec = new SecretKeySpec(key, "AES");
IvParameterSpec ivParameterSpec = new IvParameterSpec(iv);
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.DECRYPT_MODE, keySpec, ivParameterSpec);
cipherInputStream = new CipherInputStream(inputStream, cipher);
long size = message.getSize();
long read = size;
byte[] buffer = new byte[8192];
int count;
int percent = 0;
while (!isStopped && read > 0 && (count = cipherInputStream.read(buffer, 0, (int) Math.min(buffer.length, read))) != -1) {
fileOutputStream.write(buffer, 0, count);
read -= count;
int p = (int) (((float) read / (float) size) * 100);
if (percent != p) {
percent = p;
if (onProgressListener != null) {
onProgressListener.onProgress(100 - percent);
}
}
}
if (onProgressListener != null) {
onProgressListener.onEnd(Uri.fromFile(file));
}
不正确的代码 与主持人jamesk.Polk一样,您需要通过调用调用
doFinal()
以完成加密的close()
函数来关闭发送方端的CipherOutputStream
填充大小
尽管Java说的是PKCS5Padding
,但实际上它是PKCS#7 Padding
PKCS#5填充
是为8个八位字节定义的,即具有64位块大小(如DES)的块密码
PKCS#7标准见(10.3注2):
对于此类算法,该方法应使用k-(l mod k)八位字节填充尾端的输入,所有八位字节的值均为k-(l mod k),其中l是输入的长度
八位字节是一个字节,k
是以字节为单位的块大小,AES是16
我们需要使用填充计算IV\u长度+消息大小
如果我们假设您有l
字节要加密,则输出大小为
16+l+16-(l mod 16)
因此,由于填充,最多扩展16字节
请注意CBC模式在适用的情况下容易受到填充oracle攻击。CBC模式仅提供机密性。如果您需要完整性和身份验证(您应该)或者将CBC与HMAC一起使用,或者更好地使用AES-GCM这样的身份验证加密模式,它根本不需要填充,但是,您也需要存储标签。如果您担心AES-GCM的临时重用问题,那么您可以使用AES-GCM-SIV,这是一种临时防误用方案。如果您没有义务使用AES,您可以选择ChaCha20-Poly1305,它可能比AES-GCM更易于使用。这是Android项目的一个问题。当我在Android Studio中运行这段代码时,Logcat没有向我显示任何异常。但是,当我在Windows中使用Eclipse运行此代码时,出现了以下异常:
java.io.IOException: javax.crypto.BadPaddingException: Given final block not properly padded. Such issues can arise if a bad key is used during decryption.
因此,根据的答案,我意识到问题在于cipherInputStream
和cipherOutputStream
没有正确关闭。事实上,我首先关闭inputStream
和outputStream
,然后关闭密码流。因此,我先关闭了密码流,然后关闭了其他流,现在加密工作正常。很抱歉代码不完整。我已经关闭了cipherOutputStream
和我完整代码中的所有其他流。@HusseinYaqoobi您应该发布一个最小的、可验证的、完整的代码。我在几次测试后尝试了这一点:long size=message.getSize()-16-(message.getSize()%16)接收器上的代码>并能够跳出环路。但是解密文件的大小比原始文件的大小稍大,加密也没有正确地进行。你考虑过BASE64编码解码吗?你能在没有填充错误的情况下解密吗?你能检查一下最后的块字节吗?