Android,SharedPreferences 使用 AES-128 加密记住登录详细信息,但不会解密

标签 android android-activity encryption cryptography sharedpreferences

我正在尝试做什么:

在 Android 中,我尝试使用 SharedPreferences 将用户名存储在应用程序内存中。因此用户不需要每次都输入用户名,但应用程序不会解密用户名。如果不加密,它会存储并返回用户名,但使用 AES-128 加密时,用户名不会解密/返回。

发生了什么:

程序将新加密的用户名存储在内存中,但是当应用程序尝试解密它们时,什么也没有发生(用户名文本框返回为空)。

应用程序打算执行的操作:(但没有执行)

用户应输入其用户名和密码,如果单击“记住”复选框,则在按下登录按钮后,应用程序将存储并加密其用户名。

将来运行应用程序时,如果之前选中了该复选框,则其用户名将已显示在用户名文本框中键入。按钮功能完成后,应用程序将通过“doSomethinghElse”子例程重新启动,以便向我确认应用程序已正常工作并且已返回未加密的用户名。 (但这现在还没有发生)

实际问题:

它不会解密并返回用户名。删除加密、try 和 catch 后,应用程序将返回先前用户的登录详细信息。但通过添加加密,该应用程序不会返回用户名。

为了帮助人们解决这个问题,以下内容主要基于以下两个链接:

Add a "Remember me" checkbox

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

代码:

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));
    }
}

最佳答案

编码:

     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;
        }
    }

解码:

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;

    }

示例:

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

我已经使用了这段代码,它工作正常..

希望对您有帮助。

关于Android,SharedPreferences 使用 AES-128 加密记住登录详细信息,但不会解密,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26908591/

相关文章:

java - 如何更改 ListView 中每个项目的背景颜色?

Java Android 开发 : Is it bad practice to reference other classes static Strings get Intent parameters?

android - cordova 7.x 添加自定义平台——我们得到了哪些好处?

android - 完成其父类(super class)的子类 Activity

android - launchMode singleTask 中的 Activity 在通过 TaskStackBuilder 启动时被销毁

android - 如何将 Activity 显示为对话框而不是新屏幕?

c++ - 我们得出 XOR 字符串加密不如众所周知的加密安全的结论是否公平(比如 Blowfish)

encryption - Vim 加密 : how to break it?

java - Android:如何告诉我的 Activity 从我的服务启动新 Activity ?

android - 关于 Google Play 应用 Assets 加密的问题