4

I'm developing an Android app which based on a web-server. Users, who installed the app, should register on web, so they can login. When someone try to login I verify their information with API.

So I'm curious about persisting and encryption processes. Should I encrypt the values or just put them all to SharedPreferences? If encryption is needed what's the efficient way?

And last but not least, Is SharedPreferences enough in terms of security?

Thanks.

Sander de Jong
  • 351
  • 6
  • 18
R. Tom
  • 43
  • 3

2 Answers2

3

Encryption is easy, but the real question is with what key? If you hardcode the key in the app, or derive it from some known value, anyone with access to the device can easily decrypt those values. What you are achieving is merely obfuscation. Since Android doesn't have a public API to the system keystore, there is not much else you can do if you need to save the actual password. Unless of course you make the user input a password each time they start the app, which kind of defeats the purpose.

If you control both the server and the client, another approach is to use some form of token-based authentication and only save the token. Since tokens can expire and be revoked, the damage by someone getting hold of your token is much less, than exposing an actual password (which may be used on other sites as well).

Nikolay Elenkov
  • 52,576
  • 10
  • 84
  • 84
2

Of course you should encrypt user settings like login, password or maybe email. I prefer SharedPreferences for storing, and yes it's enough in terms of security.

I've found this two method on StackOverflow, it's fair enough:

protected String encrypt( String value ) {
    try {
        final byte[] bytes = value!=null ? value.getBytes(UTF8) : new byte[0];
        SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("PBEWithMD5AndDES");
        SecretKey key = keyFactory.generateSecret(new PBEKeySpec(SEKRIT));
        Cipher pbeCipher = Cipher.getInstance("PBEWithMD5AndDES");
        pbeCipher.init(Cipher.ENCRYPT_MODE, key, new PBEParameterSpec(Settings.Secure.getString(context.getContentResolver(),Settings.System.ANDROID_ID).getBytes(UTF8), 20));
        return new String(Base64.encode(pbeCipher.doFinal(bytes), Base64.NO_WRAP),UTF8);
    } catch( Exception e ) {
        throw new RuntimeException(e);
    }
}

protected String decrypt(String value){
    try {
        final byte[] bytes = value!=null ? Base64.decode(value,Base64.DEFAULT) : new byte[0];
        SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("PBEWithMD5AndDES");
        SecretKey key = keyFactory.generateSecret(new PBEKeySpec(SEKRIT));
        Cipher pbeCipher = Cipher.getInstance("PBEWithMD5AndDES");
        pbeCipher.init(Cipher.DECRYPT_MODE, key, new PBEParameterSpec(Settings.Secure.getString(context.getContentResolver(),Settings.System.ANDROID_ID).getBytes(UTF8), 20));
        return new String(pbeCipher.doFinal(bytes),UTF8);
    } catch( Exception e) {
        throw new RuntimeException(e);
    }
}

Couldn't find link, if I found, I'll edit my answer.

Edit: I found the source, you may have a look at all discussion on here.

Community
  • 1
  • 1
Ogulcan Orhan
  • 5,170
  • 6
  • 33
  • 49
  • 3
    Of course storing the key in the app, and encrypting with DES will only stop casual snooping. It doesn't really achieve much on a stock device, since shared prefs are private to the app any way. – Nikolay Elenkov Jul 25 '12 at 07:00