1

I need to store a username and a password that are common through the whole app, since they are for connecting to a hotspot in my Android app, but I'm not really sure how to do this, or how to encrypt them.

Any suggestion?

noloman
  • 11,411
  • 20
  • 82
  • 129
  • You can save them in a flat file or a sqlite db. If you need to save only the username and password, I would suggest you to save them in json format in a json file. – Anupam Basak Dec 31 '14 at 14:17

2 Answers2

2

Answer mentioned by Greg Ennis, provides you the code to encrypt the string. We have various encryption algorithms for this.

Now the challenge is - what if the application source code is reverse engineered and the data is stolen ?

To protect the code against this, try the below solutions.

Solution 1 - Proguard

ProGuard obfuscates the Java jar file before it’s converted to a classes.dex file.

Refer to the SO Link Enabling ProGuard in Eclipse for Android to understand how to configure proguard in your application.

Read this link to understand the different options we can configure in a proguard properties file. http://proguard.sourceforge.net/manual/examples.html#androidapplication

One other easy option would be to use the proguard GUI

To launch the GUI, download it from SourceForge at http://proguard.sourceforge.net. Unzip it and execute the following command in the lib folder, assuming you’ve copied your target proguard.cfg file into the proguard\lib folder. You should see that many of the optimization options

Solution 2 - DashO interface (Commercial Tool)

This includes Control Flow,Renaming, and String Encryption obfuscation options.

  • Control Flow - Reorders the bytecode and aims to make it impossible to decompile.
  • String Encryption - Encrypts many of the strings, which can be very useful as another defense against someone stealing API keys or passwords.
  • Overload Induction - Class renaming: more than one class can be named a() or b() because doing so is legal Java, as long as the classes have different method parameters.

Using a DashO interface is very simple with the GUI.

Hope this information helps.

Community
  • 1
  • 1
Prem
  • 4,823
  • 4
  • 31
  • 63
1

If you store credentials as plain text in your app, someone can easily decompile and see the passwords. If you attempt to encrypt the information, where do you put the encryption key? You have the same problem.

There is a blog post from Google discussing a strategy for handling credentials. However, it only discusses storing credentials received at runtime, such as auth tokens or passwords the user typed. It completely avoids the question posed and the more common scenario of storing known credentials, because there is no answer for it

So, I usually put a small effort in to obfuscate the information so that only someone really dedicated to know the information would see it. This just a small barrier to prevent casual inspection of your information (for example, API keys). To do this, I use this helper class:

public class Obfuscator {
    private final String _P = "(PUT A RANDOM 16-CHAR STRING HERE)";

    public String obfuscate(String value) throws GeneralSecurityException {
        byte[] raw = _P.getBytes(Charset.forName("US-ASCII"));
        if (raw.length != 16) {
            throw new IllegalArgumentException("Invalid key size.");
        }

        SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
        Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
        cipher.init(Cipher.ENCRYPT_MODE, skeySpec, new IvParameterSpec(new byte[16]));
        byte[] bytes = cipher.doFinal(value.getBytes(Charset.forName("US-ASCII")));
        return Base64.encodeToString(bytes, Base64.NO_WRAP);
    }

    public String deobfuscate(String encrypted) throws GeneralSecurityException {
        byte[] bytes = Base64.decode(encrypted, 0);
        byte[] raw = _P.getBytes(Charset.forName("US-ASCII"));
        if (raw.length != 16) {
            throw new IllegalArgumentException("Invalid key size.");
        }
        SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");

        Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
        cipher.init(Cipher.DECRYPT_MODE, skeySpec,
                new IvParameterSpec(new byte[16]));
        byte[] original = cipher.doFinal(bytes);
        return new String(original, Charset.forName("US-ASCII"));
    }
}
Greg Ennis
  • 14,917
  • 2
  • 69
  • 74
  • still someone can easily decompile the app and find that you are encrypting the data using `AES/CBC/PKCS5Padding` and the password (KEY) is `(PUT A RANDOM 16-CHAR STRING HERE)`, still not safe -IMO- – Yazan Dec 31 '14 at 14:43
  • Of course. Did you read my answer? I event put it in bold - this is a SMALL BARRIER and will only deter casual inspection! – Greg Ennis Dec 31 '14 at 14:44
  • I also checked http://android-developers.blogspot.pt/2013/02/using-cryptography-to-store-credentials.html – noloman Dec 31 '14 at 15:07
  • @GregEnnis consider adding this answer to the other question – petey Dec 31 '14 at 15:28
  • That blog post only talks about storing dyanmically received auth tokens or passwords the user typed. He completely avoided the more common scenario of storing known credentials, because there is no answer for it. – Greg Ennis Dec 31 '14 at 15:29
  • However I went ahead and updated the answer in case others actually need that – Greg Ennis Dec 31 '14 at 15:37