开发工具: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) {
    return toStr(aBytes, null);
}

public static String toStr(byte[] aBytes, String aSplit) {
    if (aBytes == null) return null;
    int lLength = aBytes.length;
    if (lLength <= 0) return "";
    if (TextUtils.isEmpty(aSplit)) aSplit = ",";
    StringBuilder lSB = new StringBuilder();
    for (int i = 0; i < lLength; i++) {
        lSB.append(String.valueOf(aBytes[i]));
        if (i != lLength - 1) lSB.append(aSplit);
    }
    return lSB.toString();
}

public static byte[] toArr(String aStr) {
    return toArr(aStr, null, (byte) 0);
}

public static byte[] toArr(String aStr, String aSplit, byte aDefaultValue) {
    if (TextUtils.isEmpty(aStr)) return null;
    if (TextUtils.isEmpty(aSplit)) aSplit = ",";
    String[] lItems = aStr.split(aSplit);
    int lLength = lItems.length;
    byte[] lResult = new byte[lLength];
    for (int i = 0; i < lLength; i++) {
        try {
            lResult[i] = Byte.parseByte(lItems[i]);
        } catch (Exception e) {
            lResult[i] = aDefaultValue;
        }
    }
    return lResult;
}

以上代码在官方示例基础上进行简单修改,仅供参考。

 

其他方案:

网上流传最多的一种方式为:

将: 

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

尊重原创,转载请声明出处,谢谢!

 

 

 

更多相关文章

  1. Android ViewFlipper简单示例
  2. Android 开发之 定时器 Handler + Runnable方式
  3. Android定时器实现的几种方式
  4. android两种方式实现圆形图片
  5. Anko:Android 代码动态布局的新方案
  6. Android 获取系统权限的代码
  7. 编译代码报出Android library projects cannot be launched错误
  8. 解决Eclipse3.6中Android 代码自动补全卡死的问题
  9. Android 示例之 notepad

随机推荐

  1. android布局文件属性说明(转)
  2. android每日一问2【2011-8-27】
  3. webview与js交互
  4. H264解码器源码(Android(安卓)1.6 版)
  5. android摄像头获取图像——第三弹
  6. Android(安卓)打包之三配置文件
  7. LAYOUT SHOW
  8. Android库so文件及skia函数的调用
  9. Android(安卓)SDK文档离线打开慢问题
  10. .net程序员转战android第二篇---牛刀小试