0

I am writing a Java program for fun which stores sensitive information from users.

For this reason I want to ensure that the garbage collection does not touch it, so that in the future when I am finished I can wipe it from memory.

So far I have this line of code creating 2048 bytes which is more than enough to store any user's passwords.

My question is how do I store a String such as "secret123", and after delete it? This is a very basic question I know but I could not see it in the documentation. I am probably making this more difficult than it is in my head, but better safe than sorry.

ByteBuffer pass = ByteBuffer.allocateDirect(2048); 

I am aware of other risks such as swap page files, the computer being coldboot attacked etc...

Thanks!

EDIT: In response to first answer - I mean to fill memory with '0' characters afterwards, not to free it.

13
  • They're bytes, not characters. But haven't I answered your question? Commented May 26, 2016 at 20:10
  • @erickson pass.put((byte) 0); gives me an error saying identifier is expected. Commented May 26, 2016 at 20:17
  • @erickson When I type "pass." I do not get a list of things, for example normally I would have .toString() etc... but I see none of that. Identifier expected, illegal start of type, then it says identifier expected again. Commented May 26, 2016 at 20:19
  • You'd have to provide more context. It sounds like you aren't following basic syntax rules. Commented May 26, 2016 at 20:27
  • @erickson pass.clear(); causes an error like that method does not exist. Same for pass.put etc... Commented May 26, 2016 at 20:34

2 Answers 2

2

You can't explicitly free the allocated memory, but you can clear the buffer and then write zeros (or random bytes) to the buffer when you are done. This will destroy any data that was previously stored in the buffer, reducing the window of attack.

pass.clear(); while (pass.hasRemaining()) pass.put((byte) 0); 
Sign up to request clarification or add additional context in comments.

2 Comments

If you are willing to delve into reflections and sun/oracle specific code, you can free the memory. but explicitly setting to 0 is best solution from security perspective
Right, it's called Unsafe for a reason, but there is work underway to standardize and support some of these function. I'm not sure if buffer management will be included.
1

As an alternative to @erickson's approach, if you allocate the byte array yourself and create the ByteBuffer by wrapping, then you can clear the array with a call to Arrays.fill().

byte[] byteArray = new byte[2048]; ByteBuffer bb = ByteBuffer.wrap(byteArray); //... do your thing here Arrays.fill(byteArray, (byte)0); 

As long as you maintain a reference to either the byteArray or the ByteBuffer, garbage collection won't touch the byte array. You can also get the array back later by calling ByteBuffer.array() and then zeroing it out. (NB: You are not guaranteed an actual array if you try this with a ByteBuffer created by allocateDirect().)

4 Comments

calling allocateDirect makes it very unlikely that there will be an accessible backing byte[]
Yes, I am aware of that. I was suggesting it as an alternative, if direct allocation was not actually a requirement.
@dcsohl I don't think this is correct, as it uses the garbage collector, compared to allocate direct which is handled by OS so you're sure it will be securely wiped?
The call to Arrays.fill() will wipe out the byte array before it's garbage collected. That's my whole point: if you are using direct allocation purely to be more secure, it's not necessary. If you are using it for other reasons, then ignore me and carry on.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.