SharedPreferences是Android提供用来存储一些简单配置信息的机制,其以KEY-VALUE对的方式进行存储,以便我们可以方便进行读取和存储。主要可以用来存储应用程序常量参数或登录账号用户名密码等。
如果我们不希望存在SharedPreferences中的数据被外界读取,可以使用AES加密算法对内容进行加密。
AES加密:密码学中的高级加密标准(Advanced Encryption Standard,AES),又称高级加密标准Rijndael加密法,是美国联邦政府采用的一种区块加密标准。这个标准用来替代原先的DES,已经被多方分析且广为全世界所使用。该算法为比利时密码学家Joan Daemen和Vincent Rijmen所设计,结合两位作者的名字,以Rijndael之命名之。
1. 创建AES加解密工具类AESEncryptor.java
其中主要提供加密encrypt、解密decrypt两个方法。
以下为该类文件的源码:
/** * AES加密器 * @author Eric_Ni * */
public class AESEncryptor {
/** * AES加密密钥 */
public static String AESkey = "0123456789012345";
/** * AES加密 */
public static String encrypt(String seed, String cleartext) throws Exception {
byte[] rawKey = getRawKey(seed.getBytes());
byte[] result = encrypt(rawKey, cleartext.getBytes());
return toHex(result);
}
/** * AES解密 */
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");
// SHA1PRNG 强随机种子算法, 要区别4.2以上版本的调用方法
SecureRandom sr = null;
if (android.os.Build.VERSION.SDK_INT >= 17) {
sr = SecureRandom.getInstance("SHA1PRNG", "Crypto");
} else {
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));
}
}
2. 使用工具类
存储:
public void store(Context context, String text) {
String afterAESEncrypt = "";
SharedPreferences mSharedPreferences= context.getSharedPreferences("NodeListOrder", context.MODE_PRIVATE);
SharedPreferences.Editor editor = mSharedPreferences.edit();
try{
afterAESEncrypt = AESEncryptor.encrypt(AESEncryptor.AESkey, nodeString);
}catch(Exception ex){}
editor.putString("nodeString", afterAESEncrypt);
editor.commit();
}
读取:
public String read (Context context) {
String afterAESdecrypt = "";
SharedPreferences mSharedPreferences= context.getSharedPreferences("NodeListOrder", context.MODE_PRIVATE);
String text= mSharedPreferences.getString("nodeString", "null");
try{
afterAESdecrypt = AESEncryptor.decrypt(AESEncryptor.AESkey, text);
}catch(Exception ex){}
return afterAESdecrypt;
}
注意:在安卓4.2及以上解密时会报Exception:
javax.crypto.BadPaddingException: pad block corrupted
所以需要修改SHA1PRNG 强随机种子算法,
sr = SecureRandom.getInstance(“SHA1PRNG”, “Crypto”);