我正在开发一个Android模块,需要使用共享首选项存储JWT令牌以进行自动登录和其他一些操作。我使用类似“token”之类的键来存储它。
问题是:
如果开发人员导入我的模块并找到键,他可以轻松读取我的JWT令牌,这对我来说不太好。
你能提供一些替代方案吗?
编辑:我的最低API级别必须为14。
问题是:
如果开发人员导入我的模块并找到键,他可以轻松读取我的JWT令牌,这对我来说不太好。
你能提供一些替代方案吗?
编辑:我的最低API级别必须为14。
在保存到共享首选项之前,您可以加密令牌,需要使用时可以解密并使用。
我建议您在保存到共享首选项时使用不可预测的密钥,而不是"token"
这里有一个加密类,可以在Android应用程序中用于加密和解密数据。
public final class Encryption {
private static final String CHIPHER_TRANSFORMATION = "AES/ECB/PKCS5Padding";
private static final String GENERATE_KEY__ALGORITHM = "PBKDF2WithHmacSHA1";
private static final String GENERATE_KEY_ALGORITHM = "AES";
public static final int CRYPTO_TYPE_ENCRYPT = 0;
public static final int CRYPTO_TYPE_DECRYPT = 1;
public static String crypto(String inString, int type, String hashKey, String salt, String charset) {
Cipher cipher = null;
try {
cipher = Cipher.getInstance(CHIPHER_TRANSFORMATION);
byte[] inputByte = inString.getBytes(charset);
switch (type) {
case CRYPTO_TYPE_DECRYPT:
cipher.init(Cipher.DECRYPT_MODE, initKey(hashKey, salt));
return new String(cipher.doFinal(Base64.decode(inputByte, Base64.DEFAULT)));
case CRYPTO_TYPE_ENCRYPT:
cipher.init(Cipher.ENCRYPT_MODE, initKey(hashKey, salt));
return new String(Base64.encode(cipher.doFinal(inputByte), Base64.DEFAULT));
}
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (NoSuchPaddingException e) {
e.printStackTrace();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (IllegalBlockSizeException e) {
e.printStackTrace();
} catch (BadPaddingException e) {
e.printStackTrace();
} catch (InvalidKeyException e) {
e.printStackTrace();
}
return null;
}
private static SecretKey getSecretKey(char[] password, byte[] salt) throws NoSuchAlgorithmException, InvalidKeySpecException {
SecretKeyFactory factory = SecretKeyFactory.getInstance(GENERATE_KEY__ALGORITHM);
KeySpec spec = new PBEKeySpec(password, salt, 1024, 128);
SecretKey tmp = factory.generateSecret(spec);
return (new SecretKeySpec(tmp.getEncoded(), GENERATE_KEY_ALGORITHM));
}
private static SecretKey initKey(String hashKey, String salt) {
try {
return getSecretKey(hashKey.toCharArray(), salt.getBytes());
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (InvalidKeySpecException e) {
e.printStackTrace();
}
return null;
}
}
Android Keystore 系统允许您将私钥存储在容器中,使其更难从设备中提取。一旦密钥位于密钥库中,它们可以用于使用私钥材料进行加密操作而保持不可导出。(注:一个问题,它是在API级别18中引入的)
使用 Android Keystore 系统的 Android 安全共享首选项
https://github.com/ophio/secure-preferences
请参阅本文,了解详细信息:
https://medium.com/@vashisthg/android-secure-shared-preferences-10f8356a4c2b#.8nf88g4g0
另一个解决方案[API级别8]: Android 对模糊的共享首选项
[ObscuredSharedPreferences.java] https://github.com/RightHandedMonkey/WorxForUs_Library/blob/master/src/com/worxforus/android/ObscuredSharedPreferences.java
希望这能对你有所帮助!