I am trying to encode my sharedPreferences username and password using Base64 but when running my program in eclipse emulator, I receive and error message saying “Array out of bounds”. I’m not sure what this error means and how to correct it.
Logcat:
10-06 13:51:24.005: E/AndroidRuntime(4272): FATAL EXCEPTION: main
10-06 13:51:24.005: E/AndroidRuntime(4272): java.lang.ArrayIndexOutOfBoundsException: length=3; index=3
10-06 13:51:24.005: E/AndroidRuntime(4272): at com.SharedPreferences.Login.SharedPrefLoginActivity.onClick(SharedPrefLoginActivity.java:84)
10-06 13:51:24.005: E/AndroidRuntime(4272): at android.view.View.performClick(View.java:3511)
10-06 13:51:24.005: E/AndroidRuntime(4272): at android.view.View$PerformClick.run(View.java:14105)
10-06 13:51:24.005: E/AndroidRuntime(4272): at android.os.Handler.handleCallback(Handler.java:605)
10-06 13:51:24.005: E/AndroidRuntime(4272): at android.os.Handler.dispatchMessage(Handler.java:92)
10-06 13:51:24.005: E/AndroidRuntime(4272): at android.os.Looper.loop(Looper.java:137)
10-06 13:51:24.005: E/AndroidRuntime(4272): at android.app.ActivityThread.main(ActivityThread.java:4424)
10-06 13:51:24.005: E/AndroidRuntime(4272): at java.lang.reflect.Method.invokeNative(Native Method)
10-06 13:51:24.005: E/AndroidRuntime(4272): at java.lang.reflect.Method.invoke(Method.java:511)
10-06 13:51:24.005: E/AndroidRuntime(4272): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:784)
10-06 13:51:24.005: E/AndroidRuntime(4272): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:551)
10-06 13:51:24.005: E/AndroidRuntime(4272): at dalvik.system.NativeStart.main(Native Method)
Here is my Registration activity which should take EditText string, encode, and save to sharedpreferences xml.
public void onClick(View arg0) {
user=rName.getText().toString().trim();
pass=rPwd.getText().toString().trim();
if(arg0==regBttn){
if((user.length()!=0))
{
if((pass.length()!=0))
{
sp=getSharedPreferences("AccessApp",MODE_WORLD_WRITEABLE);
Editor myEditor=sp.edit();
try {
myEditor.putString("USERNAME_KEY", user);
byte[ ] superSecretKeyBytes = Base64.decode(user);
byte[] key = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6 };
for (int i = 0; i < pass.length(); i++) {
key[i] = superSecretKeyBytes[i];
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
myEditor.putString("PASSWORD_KEY", pass);
byte[ ] superSecretKeyBytes = Base64.decode(pass);
byte[] key = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6 };
for (int i = 0; i < pass.length(); i++) {
key[i] = superSecretKeyBytes[i];
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
myEditor.commit();
Toast.makeText(this, "Registration is successfull",10000).show();
i=new Intent(this,AccessApp.class);
startActivity(i);
}
else
{
Toast.makeText(this, "Please Enter password", 10000).show();
}
}
else{
Toast.makeText(this,"Please Enter Username",10000).show();
}
}
else if(arg0==rtnBttn){
AlertDialog.Builder builder=new AlertDialog.Builder(this);
builder.setTitle("Exit");
builder.setMessage("Do you want to exit");
builder.setCancelable(false);
builder.setPositiveButton("Yes",new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
// TODO Auto-generated method stub
finish();
}
});
builder.setNegativeButton("No", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface arg0, int arg1) {
arg0.cancel();
}
});
AlertDialog alert=builder.create();
alert.show();
}
}
public String encrypt(String toencrypt, byte key[]) throws Exception {
SecretKeySpec secret = new SecretKeySpec(key, "AES");
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.ENCRYPT_MODE, secret);
byte[] encryptedbytes = cipher.doFinal(toencrypt.getBytes());
String encrypted = Base64.encodeBytes(encryptedbytes);
return encrypted;
}
}
Corrections:
The below corrections were applied.
(int i = 0; i < superSecretKeyBytes.length && i < key.length; i++)
Issue:
Array error has cleared but EditText string is still saved in clear text.?
Why do you use
passlength in cycle condition when it is not used inside the cycle? Are you sure thatsuperSecretKeyBytes.length == pass.length()? (probably not equals, you are decoding from Base64)It is safer to write this:
instead of:
Also, where are any guarantees that you wouldn’t get
OutOfBoundsExceptionfor yourkeyarray? Prefer to check this in the cycle as well: