2

What I'm trying to do:

Within Android, I've attempted to use SharedPreferences to store usernames within application memory. So users don't need to input their usernames every-time, but the app won't decrypt usernames. Without encryption it stores and returns usernames, but with AES-128 encryption usernames not decrypted/returned.

What's happening:

The program stores newly encrypted usernames in memory, but when the application attempts to decrypt them, nothing happens (username text-box is returned empty).

What the application was intended to do: (but isn't doing)

The user should input their username and password and if they click on the "Remember" check-box, upon press of the login button the application stores and then encrypts their username.

Upon future running of the app, if the check-box was previously checked their username would already appear typed in the username text-box. When the button function is complete, the application is then restarted by the "doSomethinghElse" subroutine, so to confirm to me that the app had worked and the unencrypted username has been returned. (But this isn't happening right now)

Actual Problem:

It's not decrypting and returning usernames. When encryption, try and catches are removed, the app returns the previous user's login details. But with the addition of encryption, the app doesn't return usernames.

To help people solve this problem, the below was based largely on the 2 links below:

Add a "Remember me" checkbox

http://www.androidsnippets.com/encryptdecrypt-strings

Code:

Crypto.java

public class Crypto {
    public static String encrypt(String seed, String cleartext)
            throws Exception {
        byte[] rawKey = getRawKey(seed.getBytes());
        byte[] result = encrypt(rawKey, cleartext.getBytes());
        return toHex(result);
    }

    public static String decrypt(String seed, String encrypted)
            throws Exception {
        byte[] rawKey = getRawKey(seed.getBytes());
        byte[] enc = toByte(encrypted);
        byte[] result = decrypt(rawKey, enc);
        return new String(result);
    }

    private static byte[] getRawKey(byte[] seed) throws Exception {
        KeyGenerator kgen = KeyGenerator.getInstance("AES");
        SecureRandom sr = SecureRandom.getInstance("SHA1PRNG");
        sr.setSeed(seed);
        kgen.init(128, sr); // 192 and 256 bits may not be available
        SecretKey skey = kgen.generateKey();
        byte[] raw = skey.getEncoded();
        return raw;
    }

    private static byte[] encrypt(byte[] raw, byte[] clear) throws Exception {
        SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
        Cipher cipher = Cipher.getInstance("AES");
        cipher.init(Cipher.ENCRYPT_MODE, skeySpec);
        byte[] encrypted = cipher.doFinal(clear);
        return encrypted;
    }

    private static byte[] decrypt(byte[] raw, byte[] encrypted)
            throws Exception {
        SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
        Cipher cipher = Cipher.getInstance("AES");
        cipher.init(Cipher.DECRYPT_MODE, skeySpec);
        byte[] decrypted = cipher.doFinal(encrypted);
        return decrypted;
    }

    public static String toHex(String txt) {
        return toHex(txt.getBytes());
    }

    public static String fromHex(String hex) {
        return new String(toByte(hex));
    }

    public static byte[] toByte(String hexString) {
        int len = hexString.length() / 2;
        byte[] result = new byte[len];
        for (int i = 0; i < len; i++)
            result[i] = Integer.valueOf(hexString.substring(2 * i, 2 * i + 2),
                    16).byteValue();
        return result;
    }

    public static String toHex(byte[] buf) {
        if (buf == null)
            return "";
        StringBuffer result = new StringBuffer(2 * buf.length);
        for (int i = 0; i < buf.length; i++) {
            appendHex(result, buf[i]);
        }
        return result.toString();
    }

    private final static String HEX = "0123456789ABCDEF";

    private static void appendHex(StringBuffer sb, byte b) {
        sb.append(HEX.charAt((b >> 4) & 0x0f)).append(HEX.charAt(b & 0x0f));
    }
}
Community
  • 1
  • 1
  • It is unclear to me if your encrypt/decript is not ok or what it has to do with shared preferences. Did you try: `Crypto.decrypt(MPwd, Crypto.encrypt(MPwd, username));` ? What do you get? – greenapps Nov 13 '14 at 12:18
  • The shared preference is where encrypted passwords will be stored and pulled from to be decrypted and returned to the username textbox –  Nov 13 '14 at 12:20
  • My tipp is your crazy toHex and fromHex conversion. Why not using Base64? it is already provided by the android sdk and allows you to encode bytes to string and vice versa. – Rene M. Nov 13 '14 at 12:24
  • Be it crazy or not. But fromHex() is nowhere used. – greenapps Nov 13 '14 at 12:28
  • have you stored the KEY in SharedPreference ? – SweetWisher ツ Nov 13 '14 at 12:29
  • I have checked your code and it seems it is working. – Chitrang Nov 13 '14 at 13:21
  • It builds yes, but it doesn't perform the intended functions –  Nov 13 '14 at 13:23

1 Answers1

3

Encode :

     public String encryptString(String dataToEncrypt) {

        try {
            SharedPreferences prefs = context.getSharedPreferences("appname", 0);
            if (prefs.getString("SECRET_KEY","") == "") {
                secretKeySpec = GenerateSecretKeySpecs();
                String stringSecretKey = Base64.encodeToString(
                        secretKeySpec.getEncoded(), Base64.DEFAULT);

                SharedPreferences.Editor editor = prefs.edit();
                editor.putString("SECRET_KEY", stringSecretKey);
                editor.commit();

            }
            if (prefs.getString("SECRET_KEY","") != "") {
                byte[] encodedBytes = null;

                Cipher c = Cipher.getInstance("AES");
                String key =prefs.getString("SECRET_KEY","");

                byte[] encodedKey = Base64.decode(key, Base64.DEFAULT);
                SecretKey originalKey = new SecretKeySpec(encodedKey, 0,
                        encodedKey.length, "AES");
                c.init(Cipher.ENCRYPT_MODE, originalKey);
                encodedBytes = c.doFinal(dataToEncrypt.getBytes());

                return Base64.encodeToString(encodedBytes, Base64.DEFAULT);
            } else {
                return null;
            }
        } catch (Exception e) {
//          Log.e(TAG, "AES encryption error");
            return null;
        }
    }

Decode :

public String decryptString(String dataToDecrypt) {
        SharedPreferences prefs= context.getSharedPreferences("appname", 0);
        if (prefs.getString("SECRET_KEY","") != "") {
            byte[] decodedBytes = null;
            try {
                Cipher c = Cipher.getInstance("AES");

                String key = prefs.getString("SECRET_KEY","")
                byte[] encodedKey = Base64.decode(key, Base64.DEFAULT);
                SecretKey originalKey = new SecretKeySpec(encodedKey, 0,
                        encodedKey.length, "AES");
                c.init(Cipher.DECRYPT_MODE, originalKey);

                byte[] dataInBytes = Base64.decode(dataToDecrypt,
                        Base64.DEFAULT);

                decodedBytes = c.doFinal(dataInBytes);
                return new String(decodedBytes);
            } catch (Exception e) {
//              Log.e(TAG, "AES decryption error");
                e.printStackTrace();
                return null;
            }

        } else
            return null;

    }

Example :

String encrypted_password = encryptString(MPwd);
String decrypted_password = decryptString(encrypted_password);

I have used this code and it is working fine..

Hope it will help you.

Community
  • 1
  • 1
SweetWisher ツ
  • 7,296
  • 2
  • 30
  • 74