5

I am developing an android module, and I have to use a shared preferences to store a jwt token for auto login, and for some other thing.

I store it with a key, like "token" or something like that.

The problem is :

If the developer import my module for his application, and find out the key, he can easily read my jwt token, and It would not to good for me.

Could you provide me some alternative solution?

Edit : My minimum API level must be 14.

Robert Banyai
  • 1,329
  • 12
  • 14

3 Answers3

1

This problem is not as easy as it seems to be. For what I know the best solution is to store your key some way by using NDK; C code is harder to decompile and your protection level is higher than using simple Java.
Obfuscating Android Applications using O-LLVM and the NDK

Another solution could be to use a String obfuscator; but, generally speaking, security through obscurity is never a good idea.
Protect string constant against reverse-engineering

Community
  • 1
  • 1
Massimo
  • 3,436
  • 4
  • 40
  • 68
0

You can encrypt your token before save to shared preferences and when you need to use you can decrypt and use it.

I suggest you to use an unpredictible key when you're saving to shared preferences instead of "token"

Here's an Encryption class which can be used in Android apps to encrypt and decrypt data.

public final class Encryption {
    private static final String CHIPHER_TRANSFORMATION = "AES/ECB/PKCS5Padding";
    private static final String GENERATE_KEY__ALGORITHM = "PBKDF2WithHmacSHA1";
    private static final String GENERATE_KEY_ALGORITHM = "AES";
    public static final int CRYPTO_TYPE_ENCRYPT = 0;
    public static final int CRYPTO_TYPE_DECRYPT = 1;

    public static String crypto(String inString, int type, String hashKey, String salt, String charset) {
        Cipher cipher = null;
        try {
            cipher = Cipher.getInstance(CHIPHER_TRANSFORMATION);
            byte[] inputByte = inString.getBytes(charset);
            switch (type) {
                case CRYPTO_TYPE_DECRYPT:
                    cipher.init(Cipher.DECRYPT_MODE, initKey(hashKey, salt));
                    return new String(cipher.doFinal(Base64.decode(inputByte, Base64.DEFAULT)));
                case CRYPTO_TYPE_ENCRYPT:
                    cipher.init(Cipher.ENCRYPT_MODE, initKey(hashKey, salt));
                    return new String(Base64.encode(cipher.doFinal(inputByte), Base64.DEFAULT));
            }
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (NoSuchPaddingException e) {
            e.printStackTrace();
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        } catch (IllegalBlockSizeException e) {
            e.printStackTrace();
        } catch (BadPaddingException e) {
            e.printStackTrace();
        } catch (InvalidKeyException e) {
            e.printStackTrace();
        }

        return null;
    }

    private static SecretKey getSecretKey(char[] password, byte[] salt) throws NoSuchAlgorithmException, InvalidKeySpecException {
        SecretKeyFactory factory = SecretKeyFactory.getInstance(GENERATE_KEY__ALGORITHM);
        KeySpec spec = new PBEKeySpec(password, salt, 1024, 128);
        SecretKey tmp = factory.generateSecret(spec);
        return (new SecretKeySpec(tmp.getEncoded(), GENERATE_KEY_ALGORITHM));
    }

    private static SecretKey initKey(String hashKey, String salt) {
        try {
            return getSecretKey(hashKey.toCharArray(), salt.getBytes());
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (InvalidKeySpecException e) {
            e.printStackTrace();
        }
        return null;
    }
}
savepopulation
  • 11,736
  • 4
  • 55
  • 80
-1

The Android Keystore system lets you store private keys in a container to make it more difficult to extract from the device. Once keys are in the keystore, they can be used for cryptographic operations with the private key material remaining non-exportable.(Note: One problem, It was introduced in API level 18)

Android secure shared preferences using Android Keystore system
https://github.com/ophio/secure-preferences

Refer this article, for detailed information,
https://medium.com/@vashisthg/android-secure-shared-preferences-10f8356a4c2b#.8nf88g4g0

Another solution [API level 8]: Obscured Shared Preferences for Android

[ObscuredSharedPreferences.java] https://github.com/RightHandedMonkey/WorxForUs_Library/blob/master/src/com/worxforus/android/ObscuredSharedPreferences.java

Hope this would help you!

Karthi R
  • 1,338
  • 10
  • 25
  • I editet my question, I have to use api 14. Thank you for your answer. – Robert Banyai Jul 14 '16 at 08:39
  • 1
    The Android Keystore works on application level. As we are talking about a module in a third party app the app can access all keys the module can access. Therefore it will not help in this situation. – Robert Jul 14 '16 at 09:10