34

I know that in order to delete a Java object I should use character array instead of String, since I can safely erase (rewrite the character array with other data) its content. This seems not to be feasible for the String objects.

Now on BlackBerry which is Java based, I was not able to find an API to handle data as character array but i am obliged to use String. Thus my question, in case I store a password in an object, how can I securely delete it?

smiley
  • 1,214
  • 2
  • 13
  • 21

4 Answers4

44

Actually you cannot really "safely erase" an array of characters in Java. Java does memory allocation through a garbage collector, a tricky piece of software which, in practice, will move memory objects in physical RAM on a regular basis. So what you think as "a char[] instance" will be copied in several places, and the erasure will physically happen only in one of those places.

In that context, "secure deletion" cannot really exist in Java. If you use Java, you must ensure that the usage context is such that secure deletion is unnecessary: "secure deletion" is needed mostly when the OS may allocate non-zeroized RAM blocks (thus an application may get excerpts of old RAM from other applications), or in the presence of virtual memory (parts of the RAM being copied to a hard disk). I guess that these do not apply to a BlackBerry, so simple String instances ought to be fine.

An other way to state it is that if String instance are not fine for passwords, then you have bigger security issues than mere password leakage. After all, you use a password to protect access to some data, so if you need "secure erasing" for a password, then, quite logically, you would also need "secure erasing" for the protected data as well, and everything you do with it.

(One can guess that I am not a big fan of the concept of "secure erasing".)

Thomas Pornin
  • 320,799
  • 57
  • 780
  • 949
  • 2
    I suppose Java doesn't have anything along the lines of a SecureString class like in .NET? http://msdn.microsoft.com/en-us/library/system.security.securestring.aspx – Steve Sep 01 '11 at 13:51
  • Not that I am aware of. Password-related methods in the standard classes tend to use `char[]` for that (and they do that more out of tradition than rationality). – Thomas Pornin Sep 01 '11 at 13:58
  • @Thomas:Not sure on what you say here. Doesn't `Arrays. fill(password, '\u0000') ;` clear the memory contents of the `char[] password`? I believe that this is actually even recomended in SUN's links – Jim Sep 01 '11 at 19:16
  • 1
    @Jim, the answer is "No, that does not securely erase the password". Read Thomas's answer again; he already answered your question. Garbage collectors can make copies of the data underneath you, so there may be other copies of the data still laying around. – D.W. Sep 01 '11 at 19:51
  • @DW:I think you are wrong.The problem is not the garbage collector, it is the fact that the `String` is immutable. Read this from SUN http://download.oracle.com/javase/1,5.0/docs/guide/security/jce/JCERefGuide.html. Search for part --> You should always collect and store security sensitive information in a char array instead – Jim Sep 01 '11 at 21:11
  • 4
    @Jim: no, @DW is right (well, of course, since he mostly says that _I_ am right, so I will not contradict him). The problem is due to the fact that a Java object, _any_ Java object, even a `char[]`, will be copied around in physical RAM. At the Java level, you only see the most recent copy, and when you erase your array, the older copies are unaffected (they are "unallocated memory" which may be used for other allocations, but they still did not get erased). – Thomas Pornin Sep 02 '11 at 09:06
  • 1
    @Thomas:Ok, I'll "buy" that ;) But how do you explain the post of SUN that actually suggest this (the clearing of `char[]`) for safety reason?Also taking into account that they have many APIs related to security e.g. load a `Keystore` take as input for password a `char[]` and not a `String` object? – Jim Sep 02 '11 at 15:32
  • 3
    @Jin: older (much older) versions of the JVM used a conservative GC which was not moving objects around -- on those systems, programmatic erasure has a chance of having the intended result. So this began a tradition of using `char[]` for passwords. Also, erasure is most pertinent on systems where "old memory" can leak towards other applications, as in Windows 98, but this is much less relevant now. As of 2011, passwords as `char[]` are kept for the sake of tradition, and compatibility with older API. – Thomas Pornin Sep 02 '11 at 15:38
  • 1
    @Thomas:I did not know that about GC.But in your answer you mention the case of the OS allocating non-zero mem blocks.Is this something different with your comment here that `old memory can leak... is much less relevant now`? – Jim Sep 03 '11 at 08:40
  • 1
    +1 for the secure erasure of the data as well – Jim Sep 03 '11 at 08:44
  • @Jim: in any decent Unix-like system (including MacOS and Windows 2000/XP+), a process gets "fresh" memory from the OS, i.e. pages are zeroed out, so that no old memory block from an application can be observed by other. Some data can still make it to swap space ("virtual memory"), so a complete solution would require encrypting swap data (at least OpenBSD can do that) or not using swap at all (just buy more RAM). Erasing from the application code is not really the proper place to do it; it is an OS thing. – Thomas Pornin Sep 03 '11 at 16:58
  • 1
    @Thomas: Do you have any reference/article that I can read on old vs new JVM or the GC or the tradition of char[] you've mentioned? – smiley Sep 08 '11 at 12:20
  • @Thomas Pornin To nitpick a bit ;) Theoretically one can avoid the GC problems, the "solutions" are just somewhat.. complicated or need a compliant API. #1: `ByteBuffer.allocateDirect()`. #2: Use an unsafe object to allocate the necessary memory and craft your own char[] or string. #1 obviously only works with an API that would use CharBuffers (ugh) and #2 has more than enough problems (though I've wrote a small app once to win a bet). But in both situations you get memory that is not allocated on the GC heaps and therefore not copied around if you use a stop&copy GC. – Voo Sep 10 '11 at 20:59
  • @Voo, I don't think that's accurate. #1: As far as I know, the GC is still allowed to make copies of `ByteBuffer.allocateDirect()`. I'm not convinced you can rely upon this for security. (Can you cite documentation stating to the contrary? Please do note that the GC is not the same as "native I/O operations", "best effort" does not mean a guarantee, and "may reside outside of the normal GC-collected heap" does not mean it is guaranteed to be outside of the heap.) #2: I don't know what you mean by an "unsafe object". – D.W. Sep 11 '11 at 21:55
  • 1
    @smiley: on the general subject of garbage collection, see [this must-read survey](http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.47.2438). Then read [this page](http://www.ibm.com/developerworks/java/library/j-jtp11253/) which shows how things go in the JVM. To complete your trip into the realm of garbage collection, read [this very good book](http://www.amazon.com/gp/product/0471941484/ref=nosim/104-1464220-8871162?n=283155). – Thomas Pornin Sep 12 '11 at 19:22
  • @D.W. (This may be outdated by now, but just for future readers...) The "unsafe object" referred to is most likely an instance of `sun.misc.Unsafe` which has routines to allocate non-heap memory. It's also due to be removed sometime around Java 9, but no word yet on what, if anything, will replace it for "safer" usage. – Ti Strga Oct 13 '15 at 16:32
  • @ThomasPornin, I don't understand why noone mention about off-heap memory. When we keep a password in off-heap memory, the GC cannot copy it. The swapping memory still is problematic, but it is possible to turn off swapping. What do you think? – Gilgamesz Dec 15 '17 at 20:38
6

in case I store a password in an object, how can I securely delete it?

I think you mean; how can you prevent an attacker with access to the device from recovering the password?

It depends on what level of access the attacker has gained.

If the attacker is limited to the external API you provide (not a good assumption), then access control using java.security.AccessController should suffice. If you design your access controls correctly (very difficult to do) and the attacker can not bypass the access controls, then access control will prevent the attacker from obtaining the data.

If the attacker is limited to operating within the Java virtual machine but not your API, the you need to protect the data with KeyStore.PrivateKeyEntry. At this level you can not rely on the proper operation of your design to protect the data and you must rely on the Java virtual machine to provide protection.

If the attacker is limited to the operating system (not the Java virtual machine) then you can not protect your data. If the attacker can prevent the Java Virtual machine from operating as designed, then the attacker can bypass any Java security mechanism.

If the attacker has physical access to the device it is impossible to protect the data against all attacks. At this level the attacker can read data as it is being written to RAM, flash, hardware modules, etc.

this.josh
  • 8,843
  • 2
  • 29
  • 51
  • can you elaborate a little more on what special protection the Java Virtual Machine provides for `KeyStore.PrivateKeyEntry` (I assume you mean `java.security.KeyStore.PrivateKeyEntry`)? I wasn't able to find any info on that. Thanks! – jbyler May 12 '14 at 23:26
  • @jbyler From Java Cryptography Architecture (JCA) "The KeyStore class supplies well-defined interfaces to access and modify the information in a keystore." The exact protection depends on the Java implementation: Oracle/Sun, Android, or other. – this.josh May 21 '14 at 06:48
  • 1
    OK, thanks Josh. I think the KeyStore is, as that quote suggests, just an API for manipulating a keystore. There's no special protection provided by the JVM; instances of a KeyStore.PrivateKeyEntry are subject to the same copying and garbage collection characteristics as other Java objects. So you might as well just use a String to hold the password, as suggested in the answer from @thomas-pornin. – jbyler May 22 '14 at 18:26
-1

You're right. As you pointed out, the lifecycle of objects (such as immutable strings) is managed by the garbage collector. So if sensitive information is in a string, you cannot overwrite the sensitive data. Also, the lifecycle of an array is managed by the garbage collector, but you can overwrite the contents, so if you overwrite the contents with random data (or zeroes), you 'delete' the contents.

Looking at the BlackBerry site [1], it actually seems that their JVM supports char[] arrays. If - for unclear reasons - this basic construct is not available from the BlackBerry JVM, you should store your confidential bits in a byte[] array which you overwrite post usage.

[1] http://supportforums.blackberry.com/t5/Java-Development/How-to-convert-Byte-Array-to-char-Array/td-p/252772

chgeuer
  • 79
  • 1
-1

If we don't try to delete it but override it with meaningless value, it is easier. Even string.value can be override by useless char set.

Colin
  • 1