Can anyone tell me:
1. How to get the characters from EditText into a char array without using a string
and
2. How to display the contents of a char array in TextView or EditText, again without using a string.
I can do it if I use a string as an intermediate step, but I don't want to do that for security reasons.
To read an EditText directly into charArray without using String.
val password:CharArray = CharArray(editText.length())
editText.text.getChars(0, editText.length(), password, 0)
To write into an editText without using String
editText.setText(password, password.size, 0)
The relation between the strings is stored in the array data, which will be eventually GC-ed (or you may even overwrite it by filling up the array with null, so the array memory will no longer contain references to particular String instances).
So if somebody will find the strings content in String pool memory (that may be kept intact for much longer time, than the GC managed memory pool), they will have to figure out which 10 strings were together in the array - from the strings content itself.
Then again if your code is creating and assigning the array and 10 strings in the same place and time, it's very likely the String pool memory will allocate all 10 strings near each other, so even without the array data it may be easy to spot those 10 strings belong to each other (especially if the content of sensitive strings is distinct from other ordinary strings you use in the code).
You may consider creating your own "SecureString" class implementing CharSequence interface over char[], and having destructor cleaning up the content.. oh wait, this is stupid Java, not C++. Hmmm... bad luck then, you would have to call some .wipe() method manually to make sure those "SecureString" instances get wiped out as soon, as you want it.
And of course you would have to guard yourself to not cast those into String ... which may happen quite easily if you implement CharSequence, so that's probably not very clever idea, from security point of view it's maybe best to have some SecureString class which doesn't implement any common interface (and overloads toString to return something non-sensitive, maybe even removing reference address, maybe just few asterisks for fun). And just endure the pain of using it as such.
To create passwords that can be cleaned up safely, use char[] and fill it with 0 as soon as password verification is done and you no longer need the password.
//example password
char[] pass = {'t', 'e', 's', 't', '_', 'p', 'a', 's', 's'};
//validate your password here
boolean isValid = validatePass(pass);
//now explicitly override the password's characters
for (int c = 0; c < pass.length; c++)
pass[c] = 0;
//do something depending isValid
if (isValid) {
//show logged user or whatever
} else {
//show error message or whatever
}
Related
I know there are many alternatives to reach what I wish, but I wont this solution because it is the most comfortable to me. I wish to use enum that starts with number, like so.
public enum Quality {
1080p,
720p,
BlueRay //this one OK
}
And then use it like so when converting to string:
Quality.1080p.name();
Why it is not possible?
Because the Java language doesn't allow variable names to start with a number- just a letter or underscore. Any character after the first may be a number. The main reason for this is to make parsing easier, and prevent situations where the parser can't tell if a symbol is a number or a variable name.
For example, if numbers were valid at the start of a variable I could do the following:
String 1 = "string";
System.out.println(1);
Does this print 1 or "string"? They avoid the problem by not allowing it. Many (most?) languages have that restriction.
One string size is about 200 bytes,
and it stores 10~20 size in a daily array.
(Store 10~20 strings of 200bytes, as array type)
I have found a way to convert an array to a string
and store it in SQLite.
However, I do not know it's a good idea
because the size of the string is large.
1.
If large arrays of strings,
is it a good idea to store arrays as a string?
2.
or is there a better way?
I would like advice. Thank you.
You're actually placing your concern onto the wrong part of your database design.
For SQLite, the maximum length of a String is 1 billion bytes, so your worries about your 10-20 strings of 200 bytes each actually isn't considered that large.
There's really no harm in storing your array as a single long String in your database. Especially when it's nowhere close to the maximum limit of a String.
Your database query time won't become longer due to your String being long. The real concern here is the processing you'll be doing on that String to turn it back into an Array. Typically, if the String is extremely long, the real performance hit is when you're flattening the array into a String and when you're transforming that String back into an Array.
However, typically, this is something you'll show a loading indicator for to your users.
For storing an Array into a database, there's really only two ways to do so:
Flatten array into a single String and store the String as TEXT
Create a table meant to store the individual elements of the string, and include a column for a Foreign Key that allows you to associate those rows with the same array. Then you'll store each element of your String arrays as a row in this table.
Depending on what you need, one design is better than the other.
For example, you would normally prefer the second implementation if your app requires you to constantly edit individual elements of an array.
For such an example, it wouldn't make much sense to use the first solution, because this means every time you want to edit the contents of an array, you'll be fetching back the complete array in it's entirety. This is impractical when you only want to fetch or edit a particular portion of that String.
Therefore, in such an example, it is much more practical to store the individual elements of the arrays into individual rows of a Table meant for this type of data. You'll be querying only the row you want and updating only the row you want.
So to answer your questions, there's really only two ways to store your String array as a TEXT type in your SQLite database. Both ways work and the real concern is to consider which solution fits your needs best.
If your app only requires you to store and fetch the array in it's entirety each time, then the single String method might be more preferable.
But if your app requires you to work with individual elements of your array, then using the table method would be more convenient.
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?
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, ' ');
There are two possible situations your application may encounter:
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.
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.
Editable implements CharSequence, which, according to the docs, is a "readable sequence of char values".
I have a very basic TCP socket connection to a remote device that I can poll for status.
Aside from the socket programming, which I have mostly figured out through asynctask, I'm trying to come up with a way to parse out the returning string.
I query the device with something like "VOL?"
The device responds with the Volume of 12 different audio outputs with this:
"VOL:33,0,21,12,0,43,0,0,0,0,20,0"
The ":" character always and only comes back after the echo of the initial command, so I can use whatever comes before the colon to flag what sort of answer is coming in. (VOL, BAS, MUT, TRE, BAL, etc)
In the case of VOL, I simply want to chunk out everything that comes between the commas, so I can chop up and place into an array the volumes of all zones.
The only thing I can think of is to grab the length of the string, then run a for loop through it searching for commas one by one, but it seems ridiculously messy:
int oldPos = 0; //used in the upcoming 'if clause' to mark where the last comma was found
int y = 0; //used to old the resulting value's array position
String strIncoming; = //the incoming TCP string
for(int x = 0; x <= strIncoming.length(); x++){
if(",".equals(strIncoming[x]){
volzoneVal[y] = strIncoming.subString(oldPos,x);
oldPos = x;
y++;
}
}
there has GOT to be a better way, (and I'm not even sure this is going to work, I'm typing it here for the first time as I brainstorm this problem, so it's not been run or compiled)
Is there a better way to scan through a string looking for hits?
strIncoming.split(":")[0] will give you what was before first colon
strIncoming.split(":")[1].split(",") will give you array of individual strings
First, split the string on the colon, and then split[0] is your type. Then take split[1] and split it on the comma, and you'll have all your 12 different outputs ready to go (just convert them to integers).
Use Java's string split function and split on the comma as the delimiter. You will then have an array of your parameters. If you append some kind of "end string" character to each response, you will know the start and end based on the colon for the start and your end character for the end.
I have a number (123456) converted to a hash key and stored in SharedPrefs using:
String correctMd5 = passwdfile.getString(PhoneFinder.PASSWORD_PREF_KEY, null);
I then retreive the number from a string:
String[] tokens = msg.getMessageBody().split(":");
String md5hash = PhoneFinder.getMd5Hash(tokens[1]);
and compare the two:
if (correctMd5 == md5hash) {
Toast.makeText(context, "Hash OK: " + md5hash, Toast.LENGTH_SHORT).show();
}
However, this check does not complete succesfully.
If I convert to strings and display them, the hashes are the same, however if I convert to bytes the 4 right most bytes are different. I assume some special character is hidden in there somewhere, how do I check and kill it?
You should probably use correctMd5.equals(md5hash) instead of the correctMd5 == md5hash.
Is it solving the problem ?
The problem appears to be:
correctMd5 == md5hash
Because a String is an Object in Java (Android) this will compare the Object, not its String value. For instance, if you have two different variables they might be in 2 different memory locations, or they might be references to the same memory location.
On the other hand, if you want to find out if the VALUES stored by the memory location are equal, you should use
correctMd5.equals(md5hash)
In your conditional, you could have two strings "1000" and "1000" but stored at different memory locations. In my conditional, it will still be true regardless of memory location, if the String values are equal.
If == is true, .equals() should be true (in most cases, if not all). But if .equals() is true, there is no guarantee that == is true.