0

I'm trying to encrypt a file by passing the file stream, the resultant stream and the cipher object which has the information regarding the type of encryption. Here's what I've tried :

private void processFile(Cipher cipher,InputStream inputStream, OutputStream outputStream){
   byte[] tempInputBuffer = new byte[1024];
   int len;
   try {
        while ((len = inputStream.read(tempInputBuffer)) != -1) {
            byte[] tempOutputBuffer = cipher.update(tempInputBuffer, 0, len);
            if ( tempOutputBuffer != null ) outputStream.write(tempOutputBuffer);
        }
        byte[] obuf = cipher.doFinal();
        if ( obuf != null ) outputStream.write(obuf);
        }catch (IOException | IllegalBlockSizeException | BadPaddingException e) {
            e.printStackTrace();    
        }catch (Exception e) {
            e.printStackTrace();        
        }
    }

This is the function from where I make the call to processFile

public ByteArrayOutputStream encryptFile( InputStream fileStream, PublicKey publicKey ) throws EmprisException {

        ByteArrayOutputStream encryptedFileStream = null;
        KeyGenerator keyGenerator;
        try {

            //generate AES key
            keyGenerator = KeyGenerator.getInstance(FileUploadDownloadConstants.AES_ALGORITHM);
            keyGenerator.init(128);
            SecretKey secretKey = keyGenerator.generateKey();
            byte[] initializationVector = new byte[16];
            SecureRandom srandom = new SecureRandom();
            srandom.nextBytes(initializationVector);
            IvParameterSpec ivSpec = new IvParameterSpec(initializationVector);

            //encrypting the aes key using rsa public key and adding it to a file
            encryptedFileStream = new ByteArrayOutputStream();
            Cipher cipherRSA = Cipher.getInstance(FileUploadDownloadConstants.RSA_TRANSFORMATION);
            cipherRSA.init(Cipher.ENCRYPT_MODE, publicKey);
            byte[] secretKeyBytes = cipherRSA.doFinal(secretKey.getEncoded());
            encryptedFileStream.write(secretKeyBytes);
            encryptedFileStream.write(initializationVector);

            //call processFile to encrypt the file
            Cipher cipherAES = Cipher.getInstance(FileUploadDownloadConstants.AES_TRANSFORMATION);
            cipherAES.init(Cipher.ENCRYPT_MODE, secretKey, ivSpec);
            processFile(cipherAES, fileStream, encryptedFileStream);
            encryptedFileStream.close();
            logger.logExiting(METHOD_NAME);
            return encryptedFileStream;             
        }catch(Exception e) {
            e.printStackTrace();
        }
    }

This is the stack trace I'm getting :

java.lang.OutOfMemoryError: Java heap space
    at java.util.Arrays.copyOf(Arrays.java:3236)
    at java.io.ByteArrayOutputStream.grow(ByteArrayOutputStream.java:118)
    at java.io.ByteArrayOutputStream.ensureCapacity(ByteArrayOutputStream.java:93)
    at java.io.ByteArrayOutputStream.write(ByteArrayOutputStream.java:153)
    at java.io.OutputStream.write(OutputStream.java:75)

I'm getting the out of memory error in the line if ( tempOutputBuffer != null ) outputStream.write(tempOutputBuffer);

Is there anything wrong with the way of writing to output stream? And this happens when I'm trying to larger files like around 15 Mb. Would greatly appreciate your help and thanks in advance.

13
  • How do you invoke this function? What OutputStream do you pass Commented Apr 23, 2018 at 15:12
  • 1
    At first glance, what you are doing looks correct as far as the streaming implementation is concerned. But be aware that ByteArrayOutputStream writes the content inside the heap memory. Therefore, as long as you hold on to this variable, you have a large (e.g. 15MB) chunk of memory that stays in memory. This may add up. What are you doint with the returned encryptedFileStream that retains this memory chunk ? And where does the InputStream come from ? Commented Apr 23, 2018 at 15:28
  • I see InoutFileStream is an argument for encryptFile. How many files do you open at one time? Commented Apr 23, 2018 at 15:28
  • Have you tried increasing your heap like this example? Commented Apr 23, 2018 at 15:32
  • Your code copies file contents to the byte array hold in the memory. However, 15Mb is not that much. Do you process many files at once/in parallel? Commented Apr 23, 2018 at 17:35

1 Answer 1

1

Have you tried setting the minimum heap size for your JVM? See this related question:

What are the Xms and Xmx parameters when starting JVMs?

The default value might be too low for your example.

Sign up to request clarification or add additional context in comments.

2 Comments

Ya, I just researched on it, but I'm trying to run this program without modifying the configurations as much as possible.
In that case, you might want to consider writing to a FileOutputStream instead because that won't consume as much heap memory.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.