我正在尝试做什么:
在 Android 中,我尝试使用 SharedPreferences 将用户名存储在应用程序内存中。因此用户不需要每次都输入用户名,但应用程序不会解密用户名。如果不加密,它会存储并返回用户名,但使用 AES-128 加密时,用户名不会解密/返回。
发生了什么:
程序将新加密的用户名存储在内存中,但是当应用程序尝试解密它们时,什么也没有发生(用户名文本框返回为空)。
应用程序打算执行的操作:(但没有执行)
用户应输入其用户名和密码,如果单击“记住”复选框,则在按下登录按钮后,应用程序将存储并加密其用户名。
将来运行应用程序时,如果之前选中了该复选框,则其用户名将已显示在用户名文本框中键入。按钮功能完成后,应用程序将通过“doSomethinghElse”子例程重新启动,以便向我确认应用程序已正常工作并且已返回未加密的用户名。 (但这现在还没有发生)
实际问题:
它不会解密并返回用户名。删除加密、try 和 catch 后,应用程序将返回先前用户的登录详细信息。但通过添加加密,该应用程序不会返回用户名。
为了帮助人们解决这个问题,以下内容主要基于以下两个链接:
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/