AES Crypto 在 Android P(Android 9.0) 被删除 解决方案
开发工具:Android Studio
项目中若使用 SecureRandom.getInstance("SHA1PRNG", "Crypto") ,会给出以下警告:
The Crypto provider has been deleted in Android P (and was deprecated in Android N), so the code will crash. less... (Ctrl+F1) The Crypto provider has been completely removed in Android P (and was deprecated in an earlier release). This means that the code will throw a NoSuchProviderException and the app will crash. Even if the code catches that exception at a higher level, this is not secure and should not be used. |
即:Crypto provider 在 Android N(7.0)中已弃用,在Android P(9.0) 中已删除。
附相关上下文参考代码:
byte[] lSeedBytes = "password".getBytes(); SecureRandom lSecureRandom = SecureRandom.getInstance("SHA1PRNG", "Crypto"); KeyGenerator lKeyGenerator = KeyGenerator.getInstance("AES"); lSecureRandom.setSeed(lSeedBytes); lKeyGenerator.init(256, lSecureRandom); SecretKey lSecretKey = lKeyGenerator.generateKey(); byte[] lResultEncoded = lSecretKey.getEncoded(); |
两种情况:
1, targetSdkVersion < 24 时,在Android P 以上的设备会出现: java.security.NoSuchProviderException: no such provider: Crypto
2,targetSdkVersion >= 24 时,在Android N 以上的设备会出现: java.security.NoSuchProviderException: no such provider: Crypto
此问题官方已经给出了参考方案: https://android-developers.googleblog.com/2018/03/cryptography-changes-in-android-p.html
但只给出了部分示例代码,对于存储,并未提供相关代码,如需要,可参考以下:
private static byte[] mSaltCache; private static byte[] getSecretKeyEncoded(String password) throws Exception { int iterationCount = 1000; int saltLength = 32; // bytes; should be the same size as the output (256 / 8 = 32) int keyLength = 256; // 256-bits for AES-256, 128-bits for AES-128, etc if (mSaltCache == null || mSaltCache.length != saltLength) { SharedPreferences lSP = Application.getInstance().getSharedPreferences("crypto_info", Context.MODE_PRIVATE); String lSaveStr = lSP.getString("salt", ""); if (!TextUtils.isEmpty(lSaveStr)) { mSaltCache = toArr(lSaveStr); } if (mSaltCache == null || mSaltCache.length != saltLength) { byte[] salt = new byte[saltLength]; // Should be of saltLength SecureRandom random = new SecureRandom(); random.nextBytes(salt); lSP.edit().putString("salt", toStr(salt)).commit(); mSaltCache = salt; } } KeySpec keySpec = new PBEKeySpec(password.toCharArray(), mSaltCache, iterationCount, keyLength); SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1"); byte[] keyBytes = keyFactory.generateSecret(keySpec).getEncoded(); SecretKey key = new SecretKeySpec(keyBytes, "AES"); return key.getEncoded(); } |
工具方法:
public static String toStr(byte[] aBytes) { public static String toStr(byte[] aBytes, String aSplit) { public static byte[] toArr(String aStr) { public static byte[] toArr(String aStr, String aSplit, byte aDefaultValue) { |
以上代码在官方示例基础上进行简单修改,仅供参考。
其他方案:
网上流传最多的一种方式为:
将:
SecureRandom.getInstance("SHA1PRNG", "Crypto") |
修改为:
SecureRandom.getInstance("SHA1PRNG", new CryptoProvider()); |
public class CryptoProvider extends Provider { public CryptoProvider() { super("Crypto", 1.0, "HARMONY (SHA1 digest; SecureRandom; SHA1withDSA signature)"); put("SecureRandom.SHA1PRNG", "org.apache.harmony.security.provider.crypto.SHA1PRNG_SecureRandomImpl"); put("SecureRandom.SHA1PRNG ImplementedIn", "Software"); } } |
但此方式仅在 24 <= targetSdkVersion < 28 时,在 Android N 到 Android P 之间生效。
原文地址: https://blog.csdn.net/u011859715/article/details/83784238
尊重原创,转载请声明出处,谢谢!
更多相关文章
- Android ViewFlipper简单示例
- Android 开发之 定时器 Handler + Runnable方式
- Android定时器实现的几种方式
- android两种方式实现圆形图片
- Anko:Android 代码动态布局的新方案
- Android 获取系统权限的代码
- 编译代码报出Android library projects cannot be launched错误
- 解决Eclipse3.6中Android 代码自动补全卡死的问题
- Android 示例之 notepad