12

I want to acquire a password string from the user on Android.

I do not want this string to be stored in a Java String at any point in the process from when the user types it, to where it arrives in my code in a char or byte array.

The reason for this is Sun's injunction against using Java Strings for sensitive data. "Objects of type String are immutable, i.e., there are no methods defined that allow you to change (overwrite) or zero out the contents of a String after usage. This feature makes String objects unsuitable for storing security sensitive information such as user passwords. You should always collect and store security sensitive information in a char array instead." http://docs.oracle.com/javase/1.5.0/docs/guide/security/jce/JCERefGuide.html#PBEEx

So I can't use EditText, because that uses Strings internally (even though it returns an Editable which could conceivably be backed by char[] or Char[]?).

What is the simplest way to accept a char array from the user? I'm guessing a Canvas on which I listen for key events?

Peter vdL
  • 4,953
  • 10
  • 40
  • 60
  • I would suggest you read this if you haven't already: http://www.mail-archive.com/android-security-discuss@googlegroups.com/msg01647.html – Matt Wolfe May 01 '12 at 05:42
  • Thank you for the link to that discussion. The discussion mirrors the argument offered by Lenik below. I discount that for the reasons in the comment appended to his suggestion. – Peter vdL May 01 '12 at 13:54
  • There's security reasons for being immutable as well: http://www.javafaq.nu/java-article1060.html – Jason Robinson May 01 '12 at 15:05

3 Answers3

11

I don't see the EditText.java (API 17) using the String internally. It is merely 2 pages long code. Of course, TextView.java from which EditText has inherited has 9k lines in the file. You still won't see TextView.java using the String internally but with its own implementation of CharWrapper for CharSequence. (TextView.java line #8535 API 17). Here you have the method call getChars. As you will notice that buf is copied over from mChars which is char[] and not String.

    private char[] mChars;
    public void getChars(int start, int end, char[] buf, int off) {
        if (start < 0 || end < 0 || start > mLength || end > mLength) {
            throw new IndexOutOfBoundsException(start + ", " + end);
        }

        System.arraycopy(mChars, start + mStart, buf, off, end - start);
    }

Now all you have to do is call getChar and pass along the char[] to be filled in.

            int pl = mPasswordEt.length();
            char[] password = new char[pl];
            mPasswordEt.getText().getChars(0, pl, password, 0);

You have the desired char[] password without using String. After you have finish working with it you can clear it from memory as follow.

Arrays.fill(password, ' ');
Win Myo Htet
  • 5,377
  • 3
  • 38
  • 56
0

There are two possible situations your application may encounter:

  1. All applications are properly sand-boxed in their environment. In this case you should not worry about your passwords, because other processes cannot access your process memory, no matter if there are Strings or byte[] arrays in there.

  2. There's a rogue application with superuser access. In this case you should not worry about Strings either, because there are too many places to intercept your passwords, so Strings should be close to the bottom of the list of things to worry about.

lenik
  • 23,228
  • 4
  • 34
  • 43
  • 1
    That analysis would apply equally to desktop and server systems, would it not? And yet Oracle issued the guidance not to use Strings for security sensitive data. And they provided an API to get passwds in a char[]. I think we should consider coredumps as the primary way to leak String data. That requires neither root nor sandbox penetration. – Peter vdL May 01 '12 at 13:51
  • 1
    Since most android IMEs use strings internally, you might need to implement not only `EditText`, but also `BrainWave-to-byte[]` functionality as well. – lenik May 01 '12 at 14:26
  • 1
    Only if you propose to filter security-sensitive data through an IME. Basically, responding to an enquiry about a security hole by pointing to a bigger security hole is the least compelling of all arguments. It doesn't address the original issue, it just says "I've thought of something worse". I agree. You have. – Peter vdL May 01 '12 at 14:32
  • 1
    from the coredump point of view there's no discernible difference between `String` and `byte[]`. – lenik May 01 '12 at 14:51
  • 1
    yes, you are right. At the time a coredump is taken, there are no significant differences between String and byte []. However, before the coredump is taken, there are two significant differences - (1) Strings are immutable, and (2) Strings may be interned. byte [] has neither of these qualities. After I finish with the security sensitive data in my byte[], I can zero it out, and be assured it has gone from my memory image. That is not true for Strings. – Peter vdL May 02 '12 at 13:59
  • "yes, you are right.", well, finally we are getting somewhere. now please consider how many coredumps the determined attacker can take while your user inputs whatever (s)he is expected to enter? would it be enough time to sniff all the information necessary? because, from where I stand, everything entered by user is an open book, which does not deserve any encoding beyond base64 -- there are so many easy to implement ways to collect that information, so I would not even try to count them all. – lenik May 02 '12 at 14:49
  • Thank you for your suggestions, Lenik. Please don't respond further. – Peter vdL May 03 '12 at 16:14
-1

Editable implements CharSequence, which, according to the docs, is a "readable sequence of char values".

Jason Robinson
  • 31,005
  • 19
  • 77
  • 131