在java中使用aes/cbc/pkcs5p加密后的文件大小是多少

31moq8wy  于 2021-07-06  发布在  Java
关注(0)|答案(2)|浏览(400)

我尝试在使用套接字发送文件时使用加密和解密。我使用 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));
            }
3mpgtkmj

3mpgtkmj1#

这是一个android项目的问题。当我在androidstudio中运行此代码时,logcat没有显示任何异常。但当我使用eclipse在windows中运行此代码时,出现了以下异常:

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 ,然后加密流。所以我先关闭密码流,然后关闭其他流,现在加密工作正常。

ltqd579y

ltqd579y2#

错误代码
正如jamesk.polk主席所说,你需要关闭 CipherOutputStream 通过调用 .close() 调用 doFinal() 完成加密。
填充大小
尽管 java 说 PKCS5Padding 实际上是的 PKCS#7 Padding . PKCS#5 Padding 为8个八位字节定义,即具有64位块大小(如des)的块密码。
pkcs#7标准见rfc2315(10.3注2):
对于此类算法,该方法应使用k-(l mod k)八位字节填充尾端的输入,所有八位字节的值均为k-(l mod k),其中l是输入的长度。
八位字节是一个字节 k 以字节为单位的块大小 16 对于aes。
我们需要计算 IV_length + message_size_with_padding 如果我们假设你有 l 字节进行加密,则输出大小为 16 + l + 16 - (l mod 16) 因此,由于填充,最多扩展16字节。
请注意,cbc模式在适用的情况下容易受到oracle攻击。cbc模式只提供机密性。如果您需要完整性和身份验证(您应该)或者将cbc与hmac一起使用,或者更好地使用像aes-gcm这样的身份验证加密模式,它根本不需要填充,但是,您也需要存储标记。如果您担心aes-gcm的nonce重用问题,那么您可以使用aes-gcm-siv,这是一种抗nonce误用的方案。如果您没有义务使用aes,您可以选择chacha20-poly1305,它可能比aes gcm更容易使用[1][2]。

相关问题